└── README.md
/README.md:
--------------------------------------------------------------------------------
1 | # Awesome Symfony
2 |
3 | A curated list of useful Symfony snippets.
4 |
5 | Contributions are highly encouraged and very welcome :)
6 |
7 | ## Table of Contents
8 |
9 | - [Configuration](#configuration)
10 | - [Assets](#assets)
11 | - [Directories, Paths](#directories-paths)
12 | - [Get the Project Root Directory](#get-the-project-root-directory)
13 | - [Email Errors](#email-errors)
14 | - [Email Logs Related to 5xx Errors (action_level: critical)](#email-logs-related-to-5xx-errors-action_level-critical)
15 | - [Email Logs Related to 4xx Errors (action_level: error)](#email-logs-related-to-4xx-errors-action_level-error)
16 | - [Do Not Email Logs for 404 Errors (excluded_404)](#do-not-email-logs-for-404-errors-excluded_404)
17 | - [Import](#import)
18 | - [Import Mixed Configuration Files](#import-mixed-configuration-files)
19 | - [Import All Resources From a Directory](#import-all-resources-from-a-directory)
20 | - [Import Configuration Files Using Glob Patterns](#import-configuration-files-using-glob-patterns)
21 | - [Log](#log)
22 | - [Enable the Monolog processor PsrLogMessageProcessor](#enable-the-monolog-processor-psrlogmessageprocessor)
23 | - [Hide Event Logs](#hide-event-logs)
24 | - [Organizing Log Files Using Channels (Log Messages to Different Files)](#organizing-log-files-using-channels-log-messages-to-different-files))
25 | - [Security](#security)
26 | - [Impersonating Users](#impersonating-users)
27 | - [Session](#session)
28 | - [Profiler](#profiler)
29 | - [Console](#console)
30 | - [Parallel Asset Dump](#parallel-asset-dump)
31 | - [Controller](#controller)
32 | - [Cookie](#cookie)
33 | - [Directories, Paths, and Filesystem](#directories-paths-and-filesystem)
34 | - [Download](#download)
35 | - [JSON](#json)
36 | - [Flash Messages](#flash-messages)
37 | - [Form](#form)
38 | - [Redirect](#redirect)
39 | - [Request](#request)
40 | - [Response](#response)
41 | - [Routing](#routing)
42 | - [External URLs](#external-urls)
43 | - [External URLs - Using a Key to Reference a URL](#external-urls-using-a-key-to-reference-a-url)
44 | - [Service](#service)
45 | - [Retrieve a Service](#retrieve-a-service)
46 | - [YAML](#yaml)
47 | - [Parse YAML File](#parse-yaml-file)
48 | - [Environment Variables](#environment-variables)
49 | - [Custom Loader for Environment Variables](#custom-loader-for-environment-variables)
50 | - [Routing](#routing)
51 | - [Generate Absolute URL](#generate-absolute-url)
52 | - [Trailing Slash with an Optional Parameter](#trailing-slash-with-an-optional-parameter)
53 | - [Twig](#twig)
54 | - [Absolute URLs](#absolute-urls)
55 | - [Assets Versioning](#assets-versioning)
56 | - [Get the Authenticated Username](#get-the-authenticated-username)
57 | - [Get the Base URL](#get-the-base-url)
58 | - [Localized Date String](#localized-date-string)
59 | - [Inject All GET Parameters in a Route](#inject-all-get-parameters-in-a-route)
60 | - [Make the `form_rest()` and `form_end()` not Display a Specific Field](#make-the-form_rest-and-form_end-not-display-a-specific-field)
61 | - [Override the 404 Error Template](#override-the-404-error-template)
62 | - [Render a Controller Asynchronously](#render-a-controller-asynchronously)
63 | - [Render Just the Close Form HTML Tag](#render-just-the-close-form-html-tag)
64 | - [Render a Template without a Specific Controller for a Static Page](#render-a-template-without-a-specific-controller-for-a-static-page)
65 | - [Using Localized Data (Date, Currency, Number, ...)](#using-localized-data-date-currency-number-)
66 |
67 | ## Configuration
68 |
69 | ### Assets
70 |
71 | #### Assets Base URL
72 | `Symfony 2.6`
73 | ```yaml
74 | # app/config/config.yml
75 | framework:
76 | templating:
77 | assets_base_urls:
78 | http: ['http://cdn.domain.com']
79 | ssl: ['https://secure.domain.com']
80 | packages:
81 | # ...
82 | ```
83 |
84 | `Symfony 2.7+`
85 | ```yaml
86 | # app/config/config.yml
87 | framework:
88 | assets:
89 | base_path: ~
90 | base_urls: ['http://cdn.domain.com', 'https://secure.domain.com']
91 | ```
92 | [[1]](http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component)
93 |
94 | #### Assets Base URL (Protocol-Relative)
95 | ```yaml
96 | # app/config/config.yml
97 | framework:
98 | templating:
99 | assets_base_urls: '//static.domain.com/images'
100 | ```
101 |
102 | #### Assets Versioning
103 | `Symfony 2.6`
104 | ```yaml
105 | # app/config/config.yml
106 | framework:
107 | templating:
108 | assets_version: 'v5'
109 | assets_version_format: '%%s?version=%%s'
110 | ```
111 |
112 | `Symfony 2.7+`
113 | ```yaml
114 | # app/config/config.yml
115 | framework:
116 | assets:
117 | version: 'v5'
118 | version_format: '%%s?version=%%s'
119 | ```
120 | [[1]](http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component)
121 |
122 | #### Named Assets
123 | ```yaml
124 | # app/config/config.yml
125 | assetic:
126 | assets:
127 | bootstrap_js:
128 | inputs:
129 | - '@AppBundle/Resources/public/js/jquery.js'
130 | - '@AppBundle/Resources/public/js/bootstrap.js'
131 | ```
132 |
133 | Using in Twig templates:
134 | ```twig
135 | {% javascripts
136 | '@bootstrap_js'
137 | '@AppBundle/Resources/public/js/*' %}
138 |
139 | {% endjavascripts %}
140 | ```
141 |
142 | #### Context-Aware CDNs
143 | ```yaml
144 | # app/config/config.yml
145 | framework:
146 | assets:
147 | base_urls:
148 | - 'http://static1.domain.com/images/'
149 | - 'https://static2.domain.com/images/'
150 | ```
151 |
152 | Using in Twig templates:
153 | ```twig
154 | {{ asset('logo.png') }}
155 | {# in a regular page: http://static1.domain.com/images/logo.png #}
156 | {# in a secure page: https://static2.domain.com/images/logo.png #}
157 | ```
158 | [[1]](http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component#context-aware-cdns)
159 |
160 | #### Packages (Different Base URLs)
161 |
162 | To specify different base URLs for assets, group them into packages:
163 | ```yaml
164 | # app/config/config.yml
165 | framework:
166 | # ...
167 | assets:
168 | packages:
169 | avatars:
170 | base_urls: 'http://static_cdn.domain.com/avatars'
171 | ```
172 |
173 | Using the `avatars` package in a Twig template:
174 | ```twig
175 |
176 | ```
177 |
178 | ### Directories, Paths
179 |
180 | #### Get the Project Root Directory
181 |
182 | Use the config parameter `%kernel.root_dir%/../`:
183 | ```yaml
184 | some_service:
185 | class: \path\to\class
186 | arguments: [%kernel.root_dir%/../]
187 | ```
188 |
189 | `Symfony 2`
190 | In a Controller:
191 |
192 | `$projectRoot = $this->container->getParameter('kernel.root_dir');`
193 |
194 | `Symfony 3.3`
195 |
196 | In a Controller:
197 |
198 | `$projectRoot = $this->get('kernel')->getProjectDir();`
199 |
200 | `Symfony 4+`
201 |
202 | Using autowiring (argument binding):
203 | ```yaml
204 | # config/services.yaml
205 | services:
206 | _defaults:
207 | bind:
208 | string $projectDir: '%kernel.project_dir%'
209 | ```
210 |
211 | Then in your class:
212 | ```php
213 | class YourClass
214 | {
215 | private $projectDir;
216 |
217 | public function __construct(string $projectDir)
218 | {
219 | $this->$projectDir = $projectDir;
220 | }
221 |
222 | // ...
223 | ```
224 |
225 | ### Email Errors
226 |
227 | #### Email Logs Related to 5xx Errors (`action_level: critical`)
228 | ```yaml
229 | # app/config/config_prod.yml
230 | monolog:
231 | handlers:
232 | mail:
233 | type: fingers_crossed
234 | action_level: critical
235 | handler: buffered
236 | buffered:
237 | type: buffer
238 | handler: swift
239 | swift:
240 | type: swift_mailer
241 | from_email: error@domain.com
242 | to_email: error@domain.com
243 | subject: An Error Occurred!
244 | level: debug
245 | ```
246 |
247 | #### Email Logs Related to 4xx Errors (`action_level: error`)
248 | ```yaml
249 | # app/config/config_prod.yml
250 | monolog:
251 | handlers:
252 | mail:
253 | type: fingers_crossed
254 | action_level: error
255 | handler: buffered
256 | buffered:
257 | type: buffer
258 | handler: swift
259 | swift:
260 | type: swift_mailer
261 | from_email: error@domain.com
262 | to_email: error@domain.com
263 | subject: An Error Occurred!
264 | level: debug
265 | ```
266 |
267 | #### Do Not Email Logs for 404 Errors (`excluded_404`)
268 | ```yaml
269 | # app/config/config_prod.yml
270 | monolog:
271 | handlers:
272 | mail:
273 | type: fingers_crossed
274 | action_level: error
275 | excluded_404:
276 | - ^/
277 | handler: buffered
278 | buffered:
279 | type: buffer
280 | handler: swift
281 | swift:
282 | type: swift_mailer
283 | from_email: error@domain.com
284 | to_email: error@domain.com
285 | subject: An Error Occurred!
286 | level: debug
287 | ```
288 |
289 | ### Import
290 |
291 | #### Import Mixed Configuration Files
292 | ```yaml
293 | # app/config/config.yml
294 | imports:
295 | - { resource: '../common/config.yml' }
296 | - { resource: 'dynamic-config.php' }
297 | - { resource: 'parameters.ini' }
298 | - { resource: 'security.xml' }
299 | # ...
300 | ```
301 |
302 | #### Import All Resources From a Directory
303 | ```yaml
304 | # app/config/config.yml
305 | imports:
306 | - { resource: '../common/' }
307 | - { resource: 'acme/' }
308 | # ...
309 | ```
310 |
311 | #### Import Configuration Files Using Glob Patterns
312 | `Symfony 3.3`
313 | ```yaml
314 | # app/config/config.yml
315 | imports:
316 | - { resource: "*.yml" }
317 | - { resource: "common/**/*.xml" }
318 | - { resource: "/etc/myapp/*.{yml,xml}" }
319 | - { resource: "bundles/*/{xml,yaml}/services.{yml,xml}" }
320 | # ...
321 | ```
322 | [[1]](http://symfony.com/blog/new-in-symfony-3-3-import-config-files-with-glob-patterns)
323 |
324 | ### Log
325 |
326 | #### Enable the Monolog processor PsrLogMessageProcessor
327 | ```yaml
328 | # app/config/config_prod.yml
329 | services:
330 | monolog_processor:
331 | class: Monolog\Processor\PsrLogMessageProcessor
332 | tags:
333 | - { name: monolog.processor }
334 | ```
335 |
336 | #### Hide Event Logs
337 | ```yaml
338 | # app/config/dev.yml
339 | monolog:
340 | handlers:
341 | main:
342 | type: stream
343 | path: "%kernel.logs_dir%/%kernel.environment%.log"
344 | level: debug
345 | channels: "!event"
346 | ```
347 |
348 | #### Organizing Log Files Using Channels (Log Messages to Different Files)
349 | ```yaml
350 | # app/config/config_prod.yml
351 | monolog:
352 | handlers:
353 | main:
354 | type: stream
355 | path: "%kernel.logs_dir%/%kernel.environment%.log"
356 | level: debug
357 | channels: ["!event"]
358 | security:
359 | type: stream
360 | path: "%kernel.logs_dir%/security-%kernel.environment%.log"
361 | level: debug
362 | channels: "security"
363 | ```
364 | [[1]](http://symfony.com/doc/current/logging/channels_handlers.html)
365 |
366 | ### Security
367 |
368 | #### Impersonating Users
369 | ```yaml
370 | # app/config/security.yml
371 | security:
372 | firewalls:
373 | main:
374 | # ...
375 | switch_user: true
376 | ```
377 |
378 | Switching the user in the URL:
379 | `http://domain.com/path?_switch_user=john`
380 |
381 | ### Session
382 |
383 | #### Define Session Lifetime
384 | ```yaml
385 | # app/config/config.yml
386 | framework:
387 | session:
388 | cookie_lifetime: 3600
389 | ```
390 |
391 | ### Profiler
392 |
393 | #### Enable the Profiler on Prod For Specific Users
394 | ```yaml
395 | # app/config/config.yml
396 | framework:
397 | # ...
398 | profiler:
399 | matcher:
400 | service: app.profiler_matcher
401 |
402 | services:
403 | app.profiler_matcher:
404 | class: AppBundle\Profiler\Matcher
405 | arguments: ["@security.context"]
406 | ```
407 |
408 | ```php
409 | namespace AppBundle\Profiler;
410 |
411 | use Symfony\Component\Security\Core\SecurityContext;
412 | use Symfony\Component\HttpFoundation\Request;
413 | use Symfony\Component\HttpFoundation\RequestMatcherInterface;
414 |
415 | class Matcher implements RequestMatcherInterface
416 | {
417 | protected $securityContext;
418 |
419 | public function __construct(SecurityContext $securityContext)
420 | {
421 | $this->securityContext = $securityContext;
422 | }
423 |
424 | public function matches(Request $request)
425 | {
426 | return $this->securityContext->isGranted('ROLE_ADMIN');
427 | }
428 | }
429 | ```
430 |
431 | ## Console
432 |
433 | ### Parallel Asset Dump
434 | `Symfony 2.8`
435 | ```bash
436 | $ php app/console --env=prod assetic:dump --forks=4
437 | ```
438 |
439 | `Symfony 3+`
440 | ```bash
441 | $ php bin/console --env=prod assetic:dump --forks=4
442 | ```
443 |
444 | ## Controller
445 |
446 | ### Cookie
447 |
448 | #### Set a Cookie
449 | ```php
450 | use Symfony\Component\HttpFoundation\Cookie;
451 |
452 | $response->headers->setCookie(new Cookie('site', 'bar'));
453 | ```
454 |
455 | ### Directories, Paths, and Filesystem
456 |
457 | #### Root Directory of the Project
458 | The parameter `kernel.root_dir` points to the `app` directory. To get to the root project directory, use `kernel.root_dir/../`
459 | ```php
460 | realpath($this->getParameter('kernel.root_dir')."/../")
461 | ```
462 |
463 | #### Check If a Path is Absolute
464 | ```php
465 | use Symfony\Component\Filesystem\Filesystem;
466 |
467 | //...
468 |
469 | $fs = new FileSystem();
470 | $fs->isAbsolutePath('/tmp'); // return true
471 | $fs->isAbsolutePath('c:\\Windows'); // return true
472 | $fs->isAbsolutePath('tmp'); // return false
473 | $fs->isAbsolutePath('../dir'); // return false
474 | ```
475 | [[1]](symfony.com/doc/current/components/filesystem.html)
476 |
477 | ### Download
478 |
479 | #### Download (Serve) a Static File
480 | ```php
481 | use Symfony\Component\HttpFoundation\BinaryFileResponse;
482 |
483 | // ...
484 |
485 | return new BinaryFileResponse('path/to/file');
486 | ```
487 |
488 | #### Check If a File Exists
489 | ```php
490 | use Symfony\Component\Filesystem\Filesystem;
491 |
492 | //...
493 |
494 | $fs = new FileSystem();
495 | if (!$fs->exists($filepath)) {
496 | throw $this->createNotFoundException();
497 | }
498 | ```
499 | [[1]](symfony.com/doc/current/components/filesystem.html)
500 |
501 | #### Download a File Without Directly Expose it and Change the Filename
502 | ```php
503 | use Symfony\Component\HttpFoundation\BinaryFileResponse;
504 | use Symfony\Component\Filesystem\Filesystem;
505 |
506 | $filename = // define your filename
507 | $basePath = $this->getParameter('kernel.root_dir').'/../uploads';
508 | $filePath = $basePath.'/'.$filename;
509 |
510 | $fs = new FileSystem();
511 | if (!$fs->exists($filepath)) {
512 | throw $this->createNotFoundException();
513 | }
514 |
515 | $response = new BinaryFileResponse($filePath);
516 | $response->trustXSendfileTypeHeader();
517 | $response->setContentDisposition(
518 | ResponseHeaderBag::DISPOSITION_INLINE,
519 | $filename,
520 | iconv('UTF-8', 'ASCII//TRANSLIT', $filename)
521 | );
522 |
523 | return $response;
524 | ```
525 |
526 | #### Using `X-Sendfile` Header with `BinaryFileResponse`
527 |
528 | BinaryFileResponse supports `X-Sendfile` (Nginx and Apache). To use of it,
529 | you need to determine whether or not the `X-Sendfile-Type` header should be
530 | trusted and call `trustXSendfileTypeHeader()` if it should:
531 | ```php
532 | BinaryFileResponse::trustXSendfileTypeHeader();
533 | ```
534 | or
535 | ```php
536 | $response = new BinaryFileResponse($filePath);
537 | $response->trustXSendfileTypeHeader();
538 | ```
539 |
540 | ### Flash Messages
541 |
542 | #### Set Multiple Flash Messages
543 | ```php
544 | use Symfony\Component\HttpFoundation\Session\Session;
545 |
546 | $session = new Session();
547 | $session->start();
548 |
549 | $session->getFlashBag()->add(
550 | 'warning',
551 | 'Your config file is writable, it should be set read-only'
552 | );
553 | $session->getFlashBag()->add('error', 'Failed to update name');
554 | $session->getFlashBag()->add('error', 'Invalid email');
555 | ```
556 | [[1]](https://symfony.com/doc/current/components/http_foundation/sessions.html#flash-messages)
557 |
558 | ### Form
559 |
560 | #### Get Errors for All Form Fields
561 | `Symfony 2.5+`
562 | ```php
563 | $allErrors = $form->getErrors(true);
564 | ```
565 |
566 | ### JSON
567 |
568 | #### Avoiding XSSI JSON Hijacking (only GET requests are vulnerable)
569 | Pass an associative array as the outer-most array to `JsonResponse`
570 | and not an indexed array so that the final result is an object:
571 | `{"object": "not inside an array"}`
572 | instead of an array:
573 | `[{"object": "inside an array"}]`
574 |
575 | #### Create a JSON Response with `JsonResponse` Class
576 | ```php
577 | use Symfony\Component\HttpFoundation\JsonResponse;
578 |
579 | $response = new JsonResponse();
580 | $response->setData(array(
581 | 'name' => 'John'
582 | ));
583 | ```
584 |
585 | #### Create a JSON Response with `Response` Class
586 | ```php
587 | use Symfony\Component\HttpFoundation\Response;
588 |
589 | $response = new Response();
590 | $response->setContent(json_encode(array(
591 | 'name' => 'John',
592 | )));
593 | $response->headers->set('Content-Type', 'application/json');
594 | ```
595 |
596 | #### Set JSONP Callback Function
597 | ```php
598 | $response->setCallback('handleResponse');
599 | ```
600 |
601 | ### Redirect
602 |
603 | #### Redirect to Another URL
604 | ```php
605 | return $this->redirect('http://domain.com');
606 | ```
607 | or
608 | ```php
609 | use Symfony\Component\HttpFoundation\RedirectResponse;
610 |
611 | $response = new RedirectResponse('http://domain.com');
612 | ```
613 |
614 | ### Request
615 |
616 | #### Get the Request Object
617 |
618 | `Symfony 2`
619 | ```php
620 | namespace Acme\FooBundle\Controller;
621 |
622 | class DemoController
623 | {
624 | public function showAction()
625 | {
626 | $request = $this->getRequest();
627 | // ...
628 | }
629 | }
630 | ```
631 |
632 | `Symfony 3`
633 | ```php
634 | namespace Acme\FooBundle\Controller;
635 |
636 | use Symfony\Component\HttpFoundation\Request;
637 |
638 | class DemoController
639 | {
640 | public function showAction(Request $request)
641 | {
642 | // ...
643 | }
644 | }
645 | ```
646 | [[1]](https://github.com/symfony/symfony/blob/2.8/UPGRADE-3.0.md#frameworkbundle)
647 |
648 | #### Get the Request Raw Data Sent with the Request Body
649 | ```php
650 | $content = $request->getContent();
651 | ```
652 |
653 | #### Fetch a GET Parameter
654 | ```php
655 | $request->query->get('site');
656 | ```
657 |
658 | #### Fetch a GET Parameter in array format (data['name'])
659 | ```php
660 | $request->query->get('data')['name'];
661 | ```
662 |
663 | #### Fetch a POST Parameter
664 | ```php
665 | $request->request->get('name');
666 | ```
667 |
668 | #### Fetch a GET Parameter Specifying the Data Type
669 | ```php
670 | $isActive = $request->query->getBoolean('active');
671 | $page = $request->query->getInt('page');
672 | ```
673 | Other methods are:
674 | - getAlpha('param');
675 | - getAlnum('param');
676 | - getDigits('param');
677 | [[1]](http://symfony.com/doc/current/components/http_foundation.html#accessing-request-data)
678 |
679 | ### Response
680 |
681 | #### Set a HTTP Status Code
682 | ```php
683 | use Symfony\Component\HttpFoundation\Response;
684 |
685 | $response->setStatusCode(Response::HTTP_NOT_FOUND);
686 | ```
687 |
688 | ### Routing
689 |
690 | #### External URLs
691 | ```yaml
692 | google_search:
693 | path: /search
694 | host: www.google.com
695 | ```
696 |
697 | ```twig
698 | Jules Verne
699 | ```
700 |
701 | #### External URLs - Using a Key to Reference a URL
702 | ```yaml
703 | framework:
704 | assets:
705 | packages:
706 | symfony_site:
707 | version: ~
708 | base_urls: 'https://symfony.com/images'
709 | ```
710 |
711 | Add images from the URL above into your views, using the "symfony_site" key in the second argument of asset():
712 | ```twig
713 |
714 | ```
715 |
716 | #### Generate Absolute URL
717 | `Symfony 2`
718 | ```php
719 | $this->generateUrl('blog_show', array('slug' => 'my-blog-post'), true);
720 | ```
721 |
722 | `Symfony 3`
723 | ```php
724 | $this->generateUrl('blog_show', array('slug' => 'my-blog-post'), UrlGeneratorInterface::ABSOLUTE_URL);
725 | ```
726 |
727 | #### Trailing Slash with an Optional Parameter
728 | ```yaml
729 | my_route:
730 | pattern: /blog/{var}
731 | defaults: { _controller: TestBundle:Blog:index, var: ''}
732 | requirements:
733 | var: ".*"
734 | ```
735 |
736 | ### Service
737 |
738 | #### Retrieve a Service
739 | ```php
740 | $this->get('service.name');
741 | ```
742 | or
743 | ```php
744 | $this->container->get('service.name'),
745 | ```
746 |
747 | `Symfony 4+`
748 |
749 | Using autowiring, just type-hint the desired service. E.g. getting the routing service:
750 |
751 | ```php
752 | use Symfony\Component\Routing\RouterInterface;
753 |
754 | class SomeClass
755 | {
756 | private $router;
757 |
758 | public function __construct(RouterInterface $router)
759 | {
760 | $this->router = $router;
761 | }
762 |
763 | public function doSomething($id)
764 | {
765 | $url = $this->router->generate('route_name', ['id' => $id]);
766 |
767 | // ...
768 | }
769 |
770 | // ...
771 | ```
772 |
773 | ### YAML
774 |
775 | #### Parse YAML File
776 | ```php
777 | use Symfony\Component\Yaml\Exception\ParseException;
778 |
779 | try {
780 | $value = Yaml::parse(file_get_contents('/path/to/file.yml'));
781 | } catch (ParseException $e) {
782 | printf("Unable to parse the YAML string: %s", $e->getMessage());
783 | }
784 | ```
785 | [[1]](http://symfony.com/doc/current/components/yaml.html#using-the-symfony-yaml-component)
786 |
787 | ## Environment Variables
788 |
789 | ### Custom Loader for Environment Variables
790 | `Symfony 4.4`
791 | ```yaml
792 | # config/services.yaml
793 | bind:
794 | string $name: '%env(name)%'
795 | ```
796 |
797 | Implement the `EnvVarLoaderInterface` in a service:
798 | ```php
799 | namespace App\Env;
800 |
801 | use Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
802 |
803 | class ConsulEnvVarLoader implements EnvVarLoaderInterface
804 | {
805 | public function loadEnvVars(): array
806 | {
807 | $response = file_get_contents('http://127.0.0.1:8500/v1/kv/website-config');
808 |
809 | $consulValue = json_decode($response, true)[0]['Value'];
810 | $decoded = json_decode(base64_decode($consulValue), true);
811 |
812 | // e.g.:
813 | // array:1 [
814 | // "name" => "my super website"
815 | // ]
816 |
817 | return $decoded;
818 | }
819 | }
820 | ```
821 |
822 | Update the consul KV:
823 | ```bash
824 | ./consul kv put website-config '{"name": "Symfony read this var from consul"}'
825 | ```
826 | [[1]](https://github.com/symfony/symfony/pull/34295#issuecomment-551899027)
827 |
828 | ## Twig
829 |
830 | ### Absolute URLs
831 | `Symfony 2.6`
832 | ```twig
833 | {{ asset('logo.png', absolute = true) }}
834 | ```
835 |
836 | `Symfony 2.7+`
837 | ```twig
838 | {{ absolute_url(asset('logo.png')) }}
839 | ```
840 |
841 | ### Assets Versioning
842 | `Symfony 2.6`
843 | ```twig
844 | {{ asset('logo.png', version = 'v5') }}
845 | ```
846 |
847 | `Symfony 2.7+`
848 | Version is automatically appended.
849 | ```twig
850 | {{ asset('logo.png') }}
851 |
852 | {# use the asset_version() function if you need to output it manually #}
853 | {{ asset_version('logo.png') }}
854 | ```
855 | [[1]](http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component#template-function-changes)
856 |
857 | ### Get the Authenticated Username
858 | ```twig
859 | {{ app.user.username }}
860 | ```
861 |
862 | ### Localized Date String
863 | In your Twig template, you can use [pre-defined](http://twig.sensiolabs.org/doc/extensions/intl.html) or [custom date formats](http://userguide.icu-project.org/formatparse/datetime) with the `localizeddate`:
864 |
865 | ```twig
866 | {{ blog.created|localizeddate('none', 'none', 'pt_BR', null, "cccc, d MMMM Y 'às' hh:mm aaa")}}
867 | ```
868 | The pattern `"cccc, d MMMM Y 'às' hh:mm aaa"` will show the date in this format:
869 |
870 | `domingo, 5 janeiro 2014 às 03:00 am`
871 |
872 | #### Get the Base URL
873 | ```php
874 | {{ app.request.getSchemeAndHttpHost() }}
875 | ```
876 |
877 | ### Inject All GET Parameters in a Route
878 | ```twig
879 | {{ path('home', app.request.query.all) }}
880 | ```
881 |
882 | ### Make the `form_rest()` and `form_end()` not Display a Specific Field
883 | Mark the field as rendered (`setRendered`)
884 | ```twig
885 | {% do form.somefield.setRendered %}
886 | ```
887 |
888 | ### Render a Template without a Specific Controller for a Static Page
889 | Use the special controller FrameworkBundle:Template:template in the route definition:
890 | ```yaml
891 | # AppBundle/Resources/config/routing.yml
892 | static_page:
893 | path: /about
894 | defaults:
895 | _controller: FrameworkBundle:Template:template
896 | template: AppBundle:default:about.html.twig
897 | ```
898 |
899 | ### Override the 404 Error Template
900 | Create a new `error404.html.twig` template at:
901 | ```twig
902 | app/Resources/TwigBundle/views/Exception/
903 | ```
904 | [[1]](https://symfony.com/doc/current/controller/error_pages.html#example-404-error-template)
905 |
906 | ### Render a Controller Asynchronously
907 | ```twig
908 | {{ render_hinclude(controller('AppBundle:Features:news', {
909 | 'default': 'Loading...'
910 | })) }}
911 | ```
912 | [[1]](http://symfony.com/doc/current/templating/hinclude.html)
913 |
914 | ### Render Just the Close Form HTML Tag
915 | ```twig
916 | {{ form_end(form, {'render_rest': false}) }}
917 | ```
918 |
919 | ### Using Localized Data (Date, Currency, Number, ...)
920 | Enable the `intl` twig extension in `config.yml` or `services.yml` file:
921 |
922 | ```yaml
923 | services:
924 | twig.extension.intl:
925 | class: Twig_Extensions_Extension_Intl
926 | tags:
927 | - { name: twig.extension }
928 | ```
929 |
--------------------------------------------------------------------------------