└── 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 | --------------------------------------------------------------------------------