diff --git a/templating.rst b/templating.rst index 46753815714..00cd2c27602 100644 --- a/templating.rst +++ b/templating.rst @@ -575,7 +575,7 @@ configuration: /** * @Route("/", name="welcome") */ - public function indexAction() + public function index() { // ... } @@ -586,11 +586,11 @@ configuration: # config/routes.yaml welcome: path: / - defaults: { _controller: AppBundle:Welcome:index } + controller: App\Controller\WelcomeController::index .. code-block:: xml - + - AppBundle:Welcome:index + App\Controller\WelcomeController::index @@ -610,7 +610,7 @@ configuration: $collection = new RouteCollection(); $collection->add('welcome', new Route('/', array( - '_controller' => 'AppBundle:Welcome:index', + '_controller' => 'App\Controller\WelcomeController::index', ))); return $collection; @@ -644,7 +644,7 @@ route: /** * @Route("/article/{slug}", name="article_show") */ - public function showAction($slug) + public function show($slug) { // ... } @@ -654,8 +654,8 @@ route: # config/routes.yaml article_show: - path: /article/{slug} - defaults: { _controller: AppBundle:Article:show } + path: /article/{slug} + controller: App\Controller\ArticleController::show .. code-block:: xml @@ -667,7 +667,7 @@ route: http://symfony.com/schema/routing/routing-1.0.xsd"> - AppBundle:Article:show + App\Controller\ArticleController::show @@ -679,7 +679,7 @@ route: $collection = new RouteCollection(); $collection->add('article_show', new Route('/article/{slug}', array( - '_controller' => 'AppBundle:Article:show', + '_controller' => 'App\Controller\ArticleController::show', ))); return $collection; @@ -791,10 +791,10 @@ advantage of Symfony's template inheritance. .. tip:: This section will teach you the philosophy behind including stylesheet - and JavaScript assets in Symfony. Symfony is also compatible with another - library, called Assetic, which follows this philosophy but allows you to do - much more interesting things with those assets. For more information on - using Assetic see :doc:`/frontend/assetic/asset_management`. + and JavaScript assets in Symfony. If you are interested in compiling and + creating those assets, check out the :doc:`Webpack Encore documentation ` + a tool that seamlessly integrates Webpack and other modern JavaScript tools + into Symfony applications. Start by adding two blocks to your base template that will hold your assets: one called ``stylesheets`` inside the ``head`` tag and another called ``javascripts`` @@ -878,7 +878,7 @@ to add to the parent block's content (and not actually *replace* it), you should use the ``parent()`` Twig function to include everything from the ``stylesheets`` block of the base template. -You can also include assets located in your bundles' ``Resources/public`` folder. +You can also include assets located in your bundles' ``Resources/public/`` folder. You will need to run the ``php bin/console assets:install target [--symlink]`` command, which copies (or symlinks) files into the correct location. (target is by default the "web/" directory of your application). diff --git a/templating/PHP.rst b/templating/PHP.rst index b9449edd8b2..ef7f39247d8 100644 --- a/templating/PHP.rst +++ b/templating/PHP.rst @@ -24,7 +24,7 @@ your application configuration file: .. code-block:: yaml - # app/config/config.yml + # config/packages/framework.yaml framework: # ... templating: @@ -32,7 +32,7 @@ your application configuration file: .. code-block:: xml - + loadFromExtension('framework', array( // ... 'templating' => array( @@ -67,28 +68,12 @@ below renders the ``index.html.php`` template:: // src/Controller/HelloController.php // ... - public function indexAction($name) + public function index($name) { - return $this->render( - 'AppBundle:Hello:index.html.php', - array('name' => $name) - ); - } - -You can also use the `@Template`_ shortcut to render the default -``AppBundle:Hello:index.html.php`` template:: - - // src/Controller/HelloController.php - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; - - // ... - - /** - * @Template(engine="php") - */ - public function indexAction($name) - { - return array('name' => $name); + // template is stored in src/Resources/views/hello/index.html.php + return $this->render('hello/index.html.php', array( + 'name' => $name + )); } .. caution:: @@ -98,24 +83,24 @@ You can also use the `@Template`_ shortcut to render the default the ``@`` notation for Twig namespaces will no longer be supported for the ``render()`` method:: - public function indexAction() + public function index() { // ... // namespaced templates will no longer work in controllers - $this->render('@App/Default/index.html.twig'); + $this->render('@SomeNamespace/hello/index.html.twig'); // you must use the traditional template notation - $this->render('AppBundle:Default:index.html.twig'); + $this->render('hello/index.html.twig'); } .. code-block:: twig {# inside a Twig template, namespaced templates work as expected #} - {{ include('@App/Default/index.html.twig') }} + {{ include('@SomeNamespace/hello/index.html.twig') }} {# traditional template notation will also work #} - {{ include('AppBundle:Default:index.html.twig') }} + {{ include('hello/index.html.twig') }} .. index:: @@ -134,36 +119,29 @@ the ``extend()`` call: .. code-block:: html+php - - extend('AppBundle::layout.html.php') ?> + + extend('layout.html.php') ?> Hello ! -The ``AppBundle::layout.html.php`` notation sounds familiar, doesn't it? It -is the same notation used to reference a template. The ``::`` part simply -means that the controller element is empty, so the corresponding file is -directly stored under ``views/``. - Now, have a look at the ``layout.html.php`` file: .. code-block:: html+php - - extend('::base.html.php') ?> + + extend('base.html.php') ?>

Hello Application

output('_content') ?> -The layout is itself decorated by another one (``::base.html.php``). Symfony +The layout is itself decorated by another one (``base.html.php``). Symfony supports multiple decoration levels: a layout can itself be decorated by -another one. When the bundle part of the template name is empty, views are -looked for in the ``templates/`` directory. This directory stores -global views for your entire project: +another one: .. code-block:: html+php - + @@ -196,8 +174,8 @@ decorating the template. In the ``index.html.php`` template, define a .. code-block:: html+php - - extend('AppBundle::layout.html.php') ?> + + extend('layout.html.php') ?> set('title', 'Hello World Application') ?> @@ -207,7 +185,7 @@ The base layout already has the code to output the title in the header: .. code-block:: html+php - + <?php $view['slots']->output('title', 'Hello Application') ?> @@ -238,17 +216,17 @@ Create a ``hello.html.php`` template: .. code-block:: html+php - + Hello ! And change the ``index.html.php`` template to include it: .. code-block:: html+php - - extend('AppBundle::layout.html.php') ?> + + extend('layout.html.php') ?> - render('AppBundle:Hello:hello.html.php', array('name' => $name)) ?> + render('hello/hello.html.php', array('name' => $name)) ?> The ``render()`` method evaluates and returns the content of another template (this is the exact same method as the one used in the controller). @@ -268,35 +246,17 @@ If you create a ``fancy`` action, and want to include it into the .. code-block:: html+php - + render( - new \Symfony\Component\HttpKernel\Controller\ControllerReference('AppBundle:Hello:fancy', array( - 'name' => $name, - 'color' => 'green', - )) + new \Symfony\Component\HttpKernel\Controller\ControllerReference( + 'App\Controller\HelloController::fancy', + array( + 'name' => $name, + 'color' => 'green', + ) + ) ) ?> -Here, the ``AppBundle:Hello:fancy`` string refers to the ``fancy`` action of the -``Hello`` controller:: - - // src/Controller/HelloController.php - - class HelloController extends Controller - { - public function fancyAction($name, $color) - { - // create some object, based on the $color variable - $object = ...; - - return $this->render('AppBundle:Hello:fancy.html.php', array( - 'name' => $name, - 'object' => $object - )); - } - - // ... - } - But where is the ``$view['actions']`` array element defined? Like ``$view['slots']``, it's called a template helper, and the next section tells you more about those. @@ -332,10 +292,10 @@ pattern: .. code-block:: yaml - # src/Resources/config/routing.yml - hello: # The route name - path: /hello/{name} - defaults: { _controller: AppBundle:Hello:index } + # config/routes.yaml + hello: + path: /hello/{name} + controller: App\Controller\HelloController::index Using Assets: Images, JavaScripts and Stylesheets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/templating/debug.rst b/templating/debug.rst index 691dd2f731b..2f22b107494 100644 --- a/templating/debug.rst +++ b/templating/debug.rst @@ -7,7 +7,7 @@ How to Dump Debug Information in Twig Templates =============================================== -When using PHP, you can use the +When using PHP templates, you can use the :ref:`dump() function from the VarDumper component ` if you need to quickly find the value of a variable passed. This is useful, for example, inside your controller:: @@ -19,7 +19,7 @@ for example, inside your controller:: class ArticleController extends Controller { - public function recentListAction() + public function recentList() { $articles = ...; dump($articles); diff --git a/templating/embedding_controllers.rst b/templating/embedding_controllers.rst index 8f8f8e11336..437ac6f080b 100644 --- a/templating/embedding_controllers.rst +++ b/templating/embedding_controllers.rst @@ -26,7 +26,7 @@ articles:: class ArticleController extends Controller { - public function recentArticlesAction($max = 3) + public function recentArticles($max = 3) { // make a database call or other logic // to get the "$max" most recent articles @@ -68,7 +68,7 @@ The ``recent_list`` template is perfectly straightforward: you'll learn how to do this correctly. To include the controller, you'll need to refer to it using the standard -string syntax for controllers (i.e. **controllerPath**::**action**): +string syntax for controllers (i.e. **controllerNamespace**::**action**): .. configuration-block:: @@ -98,4 +98,4 @@ string syntax for controllers (i.e. **controllerPath**::**action**): ) ?> -The result of an embedded controler can also be :doc:`cached ` +The result of an embedded controller can also be :doc:`cached ` diff --git a/templating/formats.rst b/templating/formats.rst index 7d1893b50f8..45f7274a7a5 100644 --- a/templating/formats.rst +++ b/templating/formats.rst @@ -30,7 +30,7 @@ pattern is to do the following:: /** * @Route("/{slug}") */ - public function showAction(Request $request, $slug) + public function show(Request $request, $slug) { // retrieve the article based on $slug $article = ...; @@ -53,7 +53,7 @@ special ``_format`` placeholder in your route definition:: /** * @Route("/{slug}.{_format}", defaults={"_format": "html"}) */ - public function showAction(Request $request, $slug) + public function show(Request $request, $slug) { // ... } diff --git a/templating/global_variables.rst b/templating/global_variables.rst index 332ddefaa0c..bfc2dcef08a 100644 --- a/templating/global_variables.rst +++ b/templating/global_variables.rst @@ -5,13 +5,13 @@ How to Inject Variables into all Templates (i.e. global Variables) ================================================================== Sometimes you want a variable to be accessible to all the templates you use. -This is possible inside your ``app/config/config.yml`` file: +This is possible inside your ``config/packages/twig.yaml`` file: .. configuration-block:: .. code-block:: yaml - # app/config/config.yml + # config/packages/twig.yaml twig: # ... globals: @@ -19,7 +19,7 @@ This is possible inside your ``app/config/config.yml`` file: .. code-block:: xml - + loadFromExtension('twig', array( // ... 'globals' => array( @@ -61,7 +61,7 @@ system, which lets you isolate or reuse the value: .. code-block:: yaml - # app/config/parameters.yml + # config/services.yaml parameters: ga_tracking: UA-xxxxx-x @@ -69,14 +69,14 @@ system, which lets you isolate or reuse the value: .. code-block:: yaml - # app/config/config.yml + # config/packages/twig.yaml twig: globals: ga_tracking: '%ga_tracking%' .. code-block:: xml - + loadFromExtension('twig', array( 'globals' => array( 'ga_tracking' => '%ga_tracking%', @@ -122,7 +122,7 @@ This should feel familiar, as it's the same syntax you use in service configurat .. code-block:: yaml - # app/config/config.yml + # config/packages/twig.yaml twig: # ... globals: @@ -131,7 +131,7 @@ This should feel familiar, as it's the same syntax you use in service configurat .. code-block:: xml - + loadFromExtension('twig', array( // ... 'globals' => array( diff --git a/templating/hinclude.rst b/templating/hinclude.rst index c1fa4fa7a07..2768b15875b 100644 --- a/templating/hinclude.rst +++ b/templating/hinclude.rst @@ -44,14 +44,14 @@ tags: .. code-block:: yaml - # app/config/config.yml + # config/packages/framework.yaml framework: # ... fragments: { path: /_fragment } .. code-block:: xml - + loadFromExtension('framework', array( // ... 'fragments' => array('path' => '/_fragment'), @@ -81,7 +81,7 @@ in your application configuration: .. code-block:: yaml - # app/config/config.yml + # config/packages/framework.yaml framework: # ... templating: @@ -89,7 +89,7 @@ in your application configuration: .. code-block:: xml - + loadFromExtension('framework', array( // ... 'templating' => array( diff --git a/templating/namespaced_paths.rst b/templating/namespaced_paths.rst index 8c191ad4b2e..59e76e7477f 100644 --- a/templating/namespaced_paths.rst +++ b/templating/namespaced_paths.rst @@ -4,40 +4,35 @@ How to Use and Register Namespaced Twig Paths ============================================= -Usually, when you refer to a template, you'll use the Twig namespaced paths, which -are automatically registered for your bundles: +Usually, when you refer to a template, you'll use the relative path from the +main ``templates/`` dir at the root of the project: .. code-block:: twig - {% extends "@App/layout.html.twig" %} - {{ include('@App/Foo/bar.html.twig') }} + {# this template is located in templates/layout.html.twig #} + {% extends "layout.html.twig" %} -.. note:: + {# this template is located in templates/user/profile.html.twig #} + {{ include('user/profile.html.twig') }} - In the past, Symfony used a different syntax to refer to templates. This - format, which uses colons (``:``) to separate each template path section, is - less consistent and has worse performance than the Twig syntax. For reference - purposes, this is the equivalent notation of the previous example: - - .. code-block:: twig - - {# the following template syntax is no longer recommended #} - {% extends "AppBundle::layout.html.twig" %} - {{ include('AppBundle:Foo:bar.html.twig') }} +If the application defines lots of templates and stores them in deep nested +directories, you may consider using **Twig namespaces**, which create shortcuts +to template directories. Registering your own Namespaces ------------------------------- -You can also register your own custom namespaces. Suppose that you're using -some third-party library that includes Twig templates that live in -``vendor/acme/foo-bar/templates``. First, register a namespace for this -directory: +Suppose that you're using some third-party library that includes Twig templates +that live in ``vendor/acme/foo-bar/templates/``. This path is too long, so you +can define a ``foo_bar`` Twig namespace as a shortcut. + +First, register a namespace for this directory: .. configuration-block:: .. code-block:: yaml - # app/config/config.yml + # config/packages/twig.yaml twig: # ... paths: @@ -45,7 +40,7 @@ directory: .. code-block:: xml - + loadFromExtension('twig', array( 'paths' => array( '%kernel.project_dir%/vendor/acme/foo-bar/templates' => 'foo_bar', ), )); -The registered namespace is called ``foo_bar``, which refers to the -``vendor/acme/foo-bar/templates`` directory. Assuming there's a file -called ``sidebar.twig`` in that directory, you can use it easily: +The registered namespace is called ``foo_bar``, but you must prefix the ``@`` +character when using it in templates (that's how Twig can differentiate +namespaces from regular paths). Assuming there's a file called ``sidebar.twig`` +in the ``vendor/acme/foo-bar/templates/`` directory, you can refer to it as: .. code-block:: twig @@ -78,7 +74,7 @@ called ``sidebar.twig`` in that directory, you can use it easily: Multiple Paths per Namespace ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can also assign several paths to the same template namespace. The order in +A single Twig namespace can be associated with multiple paths. The order in which paths are configured is very important, because Twig will always load the first template that exists, starting from the first configured path. This feature can be used as a fallback mechanism to load generic templates when the @@ -88,7 +84,7 @@ specific template doesn't exist. .. code-block:: yaml - # app/config/config.yml + # config/packages/twig.yaml twig: # ... paths: @@ -98,7 +94,7 @@ specific template doesn't exist. .. code-block:: xml - + loadFromExtension('twig', array( 'paths' => array( '%kernel.project_dir%/vendor/acme/themes/theme1' => 'theme', diff --git a/templating/overriding.rst b/templating/overriding.rst index 6b5f96c6efe..5247c155aa0 100644 --- a/templating/overriding.rst +++ b/templating/overriding.rst @@ -15,8 +15,8 @@ the template for a blog list page. Inside the bundle, the template you want to override lives at ``Resources/views/Blog/index.html.twig``. To override the bundle template, just copy the ``index.html.twig`` template -from the bundle to ``app/Resources/AcmeBlogBundle/views/Blog/index.html.twig`` -(the ``app/Resources/AcmeBlogBundle`` directory won't exist, so you'll need +from the bundle to ``templates/bundles/AcmeBlogBundle/Blog/index.html.twig`` +(the ``templates/bundles/AcmeBlogBundle/`` directory won't exist, so you'll need to create it). You're now free to customize the template. .. caution:: @@ -25,12 +25,7 @@ to create it). You're now free to customize the template. cache (``php bin/console cache:clear``), even if you are in debug mode. This logic also applies to *any* template that lives in a bundle: just follow the -convention: ``app/Resources/{BUNDLE_NAME}/views/{PATH/TO/TEMPLATE.html.twig}``. - -.. note:: - - You can also override templates from within a bundle by using bundle - inheritance. For more information, see :doc:`/bundles/inheritance`. +convention: ``templates/bundles/{BUNDLE_NAME}/{PATH/TO/TEMPLATE.html.twig}``. .. _templating-overriding-core-templates: @@ -40,10 +35,10 @@ convention: ``app/Resources/{BUNDLE_NAME}/views/{PATH/TO/TEMPLATE.html.twig}``. Overriding Core Templates ~~~~~~~~~~~~~~~~~~~~~~~~~ -Since the Symfony Framework itself is just a bundle, core templates can be +Since the Symfony framework itself uses lots of bundles, core templates can be overridden in the same way. For example, the core TwigBundle contains a number of different "exception" and "error" templates that can be overridden by -copying each from the ``Resources/views/Exception`` directory of the TwigBundle -to, you guessed it, the ``app/Resources/TwigBundle/views/Exception`` directory. +copying each from the ``Resources/views/Exception/`` directory of the TwigBundle +to, you guessed it, the ``templates/bundles/TwigBundle/Exception/`` directory. .. _`KnpBundles.com`: http://knpbundles.com diff --git a/templating/render_without_controller.rst b/templating/render_without_controller.rst index 831bf327423..00b1a006f59 100644 --- a/templating/render_without_controller.rst +++ b/templating/render_without_controller.rst @@ -7,7 +7,8 @@ How to Render a Template without a custom Controller Usually, when you need to create a page, you need to create a controller and render a template from within that controller. But if you're rendering a simple template that doesn't need any data passed into it, you can avoid -creating the controller entirely, by using the built-in ``FrameworkBundle:Template:template`` +creating the controller entirely, by using the built-in +``Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction`` controller. For example, suppose you want to render a ``static/privacy.html.twig`` @@ -18,40 +19,43 @@ can do this without creating a controller: .. code-block:: yaml + # config/routes.yaml acme_privacy: - path: /privacy + path: /privacy + controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction defaults: - _controller: FrameworkBundle:Template:template - template: static/privacy.html.twig + template: static/privacy.html.twig .. code-block:: xml + - FrameworkBundle:Template:template + Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction static/privacy.html.twig .. code-block:: php + // config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('acme_privacy', new Route('/privacy', array( - '_controller' => 'FrameworkBundle:Template:template', + '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction', 'template' => 'static/privacy.html.twig', ))); return $collection; -The ``FrameworkBundle:Template:template`` controller will simply render whatever -template you've passed as the ``template`` default value. +The ``TemplateController`` will simply render whatever template you've passed as +the ``template`` default value. You can of course also use this trick when rendering embedded controllers from within a template. But since the purpose of rendering a controller from @@ -71,9 +75,6 @@ this is probably only useful if you'd like to cache this page partial (see use Symfony\Component\Routing\Generator\UrlGeneratorInterface; ?> - render( $view['router']->url('acme_privacy', array()) ) ?> @@ -91,23 +92,25 @@ other variables in your route, you can control exactly how your page is cached: .. code-block:: yaml + # config/routes.yaml acme_privacy: - path: /privacy + path: /privacy + controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction defaults: - _controller: FrameworkBundle:Template:template - template: 'static/privacy.html.twig' - maxAge: 86400 - sharedAge: 86400 + template: 'static/privacy.html.twig' + maxAge: 86400 + sharedAge: 86400 .. code-block:: xml + - FrameworkBundle:Template:template + Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction static/privacy.html.twig 86400 86400 @@ -116,12 +119,13 @@ other variables in your route, you can control exactly how your page is cached: .. code-block:: php + // config/routes.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('acme_privacy', new Route('/privacy', array( - '_controller' => 'FrameworkBundle:Template:template', + '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction', 'template' => 'static/privacy.html.twig', 'maxAge' => 86400, 'sharedAge' => 86400, diff --git a/templating/syntax.rst b/templating/syntax.rst index a2effc5a493..0dbf0f93038 100644 --- a/templating/syntax.rst +++ b/templating/syntax.rst @@ -16,4 +16,4 @@ console command: $ php bin/console lint:twig templates/article/recent_list.html.twig # or by directory: - $ php bin/console lint:twig app/Resources/views + $ php bin/console lint:twig templates/ diff --git a/templating/twig_extension.rst b/templating/twig_extension.rst index f57fd16cc63..014c2e0d1e9 100644 --- a/templating/twig_extension.rst +++ b/templating/twig_extension.rst @@ -21,17 +21,21 @@ money: {# pass in the 3 optional arguments #} {{ product.price|price(2, ',', '.') }} -Create a class that extends ``\Twig_Extension`` and fill in the logic:: +Create a class that extends the ``AbstractExtension`` class defined by Twig and +fill in the logic:: // src/Twig/AppExtension.php namespace App\Twig; - class AppExtension extends \Twig_Extension + use Twig\Extension\AbstractExtension; + use Twig\TwigFilter; + + class AppExtension extends AbstractExtension { public function getFilters() { return array( - new \Twig_SimpleFilter('price', array($this, 'priceFilter')), + new TwigFilter('price', array($this, 'priceFilter')), ); } @@ -44,14 +48,6 @@ Create a class that extends ``\Twig_Extension`` and fill in the logic:: } } -.. note:: - -   Prior to Twig 1.26, your extension had to define an additional ``getName()`` - method that returned a string with the extension's internal name (e.g. - ``app.my_extension``). When your extension needs to be compatible with Twig - versions before 1.26, include this method which is omitted in the example - above. - .. tip:: Along with custom filters, you can also add custom `functions`_ and register