|
| 1 | +PHP for Templates |
| 2 | +================= |
| 3 | + |
| 4 | +Even if Symfony2 defaults to Twig for its template engine, you can still use |
| 5 | +plain PHP code if you want. Both templating engine are supported equally in |
| 6 | +Symfony2. Symfony2 adds some nice features on top of PHP to make writing |
| 7 | +templates with PHP more powerful. |
| 8 | + |
| 9 | +Rendering PHP Templates |
| 10 | +----------------------- |
| 11 | + |
| 12 | +To render a PHP template instead of a Twig one, use the ``.php`` suffix at the |
| 13 | +end of the template name instead of ``.twig``. The controller below renders |
| 14 | +the ``index.php`` template:: |
| 15 | + |
| 16 | + // src/Application/HelloBundle/Controller/HelloController.php |
| 17 | + |
| 18 | + public function indexAction($name) |
| 19 | + { |
| 20 | + return $this->render('HelloBundle:Hello:index.php', array('name' => $name)); |
| 21 | + } |
| 22 | + |
| 23 | +.. index:: |
| 24 | + single: Templating; Layout |
| 25 | + single: Layout |
| 26 | + |
| 27 | +Decorating Templates |
| 28 | +-------------------- |
| 29 | + |
| 30 | +More often than not, templates in a project share common elements, like the |
| 31 | +well-known header and footer. In Symfony2, we like to think about this problem |
| 32 | +differently: a template can be decorated by another one. |
| 33 | + |
| 34 | +The ``index.php`` template is decorated by ``layout.php``, thanks to the |
| 35 | +``extend()`` call: |
| 36 | + |
| 37 | +.. code-block:: html+php |
| 38 | + |
| 39 | + <!-- src/Application/HelloBundle/Resources/views/Hello/index.php --> |
| 40 | + <?php $view->extend('HelloBundle::layout.php') ?> |
| 41 | + |
| 42 | + Hello <?php echo $name ?>! |
| 43 | + |
| 44 | +The ``HelloBundle::layout.php`` notation sounds familiar, doesn't it? It is |
| 45 | +the same notation as for referencing a template. The ``::`` part simply means |
| 46 | +that the controller element is empty, so the corresponding file is directly |
| 47 | +stored under ``views/``. |
| 48 | + |
| 49 | +Now, let's have a look at the ``layout.php`` file: |
| 50 | + |
| 51 | +.. code-block:: html+php |
| 52 | + |
| 53 | + <!-- src/Application/HelloBundle/Resources/views/layout.php --> |
| 54 | + <?php $view->extend('::layout.php') ?> |
| 55 | + |
| 56 | + <h1>Hello Application</h1> |
| 57 | + |
| 58 | + <?php $view['slots']->output('_content') ?> |
| 59 | + |
| 60 | +The layout is itself decorated by another layout (``::layout.php``). Symfony2 |
| 61 | +supports multiple decoration levels: a layout can itself be decorated by |
| 62 | +another one. When the bundle part of the template name is empty, views are |
| 63 | +looked for in the ``app/views/`` directory. This directory store global views |
| 64 | +for your entire project: |
| 65 | + |
| 66 | +.. code-block:: html+php |
| 67 | + |
| 68 | + <!-- app/views/layout.php --> |
| 69 | + <!DOCTYPE html> |
| 70 | + <html> |
| 71 | + <head> |
| 72 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| 73 | + <title><?php $view['slots']->output('title', 'Hello Application') ?></title> |
| 74 | + </head> |
| 75 | + <body> |
| 76 | + <?php $view['slots']->output('_content') ?> |
| 77 | + </body> |
| 78 | + </html> |
| 79 | + |
| 80 | +For both layouts, the ``$view['slots']->output('_content')`` expression is |
| 81 | +replaced by the content of the child template, ``index.php`` and |
| 82 | +``layout.php`` respectively (more on slots in the next section). |
| 83 | + |
| 84 | +As you can see, Symfony2 provides methods on a mysterious ``$view`` object. In |
| 85 | +a template, the ``$view`` variable is always available and refers to a special |
| 86 | +object that provides a bunch of methods that makes the template engine tick. |
| 87 | + |
| 88 | +.. index:: |
| 89 | + single: Templating; Slot |
| 90 | + single: Slot |
| 91 | + |
| 92 | +Working with Slots |
| 93 | +------------------ |
| 94 | + |
| 95 | +A slot is a snippet of code, defined in a template, and reusable in any layout |
| 96 | +decorating the template. In the ``index.php`` template, define a ``title`` slot: |
| 97 | + |
| 98 | +.. code-block:: html+php |
| 99 | + |
| 100 | + <!-- src/Application/HelloBundle/Resources/views/Hello/index.php --> |
| 101 | + <?php $view->extend('HelloBundle::layout.php') ?> |
| 102 | + |
| 103 | + <?php $view['slots']->set('title', 'Hello World Application') ?> |
| 104 | + |
| 105 | + Hello <?php echo $name ?>! |
| 106 | + |
| 107 | +The base layout already have the code to output the title in the header: |
| 108 | + |
| 109 | +.. code-block:: html+php |
| 110 | + |
| 111 | + <!-- app/views/layout.php --> |
| 112 | + <head> |
| 113 | + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| 114 | + <title><?php $view['slots']->output('title', 'Hello Application') ?></title> |
| 115 | + </head> |
| 116 | + |
| 117 | +The ``output()`` method inserts the content of a slot and optionally takes a |
| 118 | +default value if the slot is not defined. And ``_content`` is just a special |
| 119 | +slot that contains the rendered child template. |
| 120 | + |
| 121 | +For large slots, there is also an extended syntax: |
| 122 | + |
| 123 | +.. code-block:: html+php |
| 124 | + |
| 125 | + <?php $view['slots']->start('title') ?> |
| 126 | + Some large amount of HTML |
| 127 | + <?php $view['slots']->stop() ?> |
| 128 | + |
| 129 | +.. index:: |
| 130 | + single: Templating; Include |
| 131 | + |
| 132 | +Including other Templates |
| 133 | +------------------------- |
| 134 | + |
| 135 | +The best way to share a snippet of template code is to define a template that |
| 136 | +can then be included into other templates. |
| 137 | + |
| 138 | +Create a ``hello.php`` template: |
| 139 | + |
| 140 | +.. code-block:: html+php |
| 141 | + |
| 142 | + <!-- src/Application/HelloBundle/Resources/views/Hello/hello.php --> |
| 143 | + Hello <?php echo $name ?>! |
| 144 | + |
| 145 | +And change the ``index.php`` template to include it: |
| 146 | + |
| 147 | +.. code-block:: html+php |
| 148 | + |
| 149 | + <!-- src/Application/HelloBundle/Resources/views/Hello/index.php --> |
| 150 | + <?php $view->extend('HelloBundle::layout.php') ?> |
| 151 | + |
| 152 | + <?php echo $view->render('HelloBundle:Hello:hello.php', array('name' => $name)) ?> |
| 153 | + |
| 154 | +The ``render()`` method evaluates and returns the content of another template |
| 155 | +(this is the exact same method as the one used in the controller). |
| 156 | + |
| 157 | +.. index:: |
| 158 | + single: Templating; Embedding Pages |
| 159 | + |
| 160 | +Embedding other Controllers |
| 161 | +--------------------------- |
| 162 | + |
| 163 | +And what if you want to embed the result of another controller in a template? |
| 164 | +That's very useful when working with Ajax, or when the embedded template needs |
| 165 | +some variable not available in the main template. |
| 166 | + |
| 167 | +If you create a ``fancy`` action, and want to include it into the ``index.php`` |
| 168 | +template, simply use the following code: |
| 169 | + |
| 170 | +.. code-block:: html+php |
| 171 | + |
| 172 | + <!-- src/Application/HelloBundle/Resources/views/Hello/index.php --> |
| 173 | + <?php echo $view['actions']->render('HelloBundle:Hello:fancy', array('name' => $name, 'color' => 'green')) ?> |
| 174 | + |
| 175 | +Here, the ``HelloBundle:Hello:fancy`` string refers to the ``fancy`` action of the |
| 176 | +``Hello`` controller:: |
| 177 | + |
| 178 | + // src/Application/HelloBundle/Controller/HelloController.php |
| 179 | + |
| 180 | + class HelloController extends Controller |
| 181 | + { |
| 182 | + public function fancyAction($name, $color) |
| 183 | + { |
| 184 | + // create some object, based on the $color variable |
| 185 | + $object = ...; |
| 186 | + |
| 187 | + return $this->render('HelloBundle:Hello:fancy.php', array('name' => $name, 'object' => $object)); |
| 188 | + } |
| 189 | + |
| 190 | + // ... |
| 191 | + } |
| 192 | + |
| 193 | +But where is the ``$view['actions']`` array element defined? Like |
| 194 | +``$view['slots']``, it's called a template helper, and the next section tells |
| 195 | +you more about those. |
| 196 | + |
| 197 | +.. index:: |
| 198 | + single: Templating; Helpers |
| 199 | + |
| 200 | +Using Template Helpers |
| 201 | +---------------------- |
| 202 | + |
| 203 | +The Symfony2 templating system can be easily extended via helpers. Helpers are |
| 204 | +PHP objects that provide features useful in a template context. ``actions`` and |
| 205 | +``slots`` are two of the built-in Symfony2 helpers. |
| 206 | + |
| 207 | +Creating Links between Pages |
| 208 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 209 | + |
| 210 | +Speaking of web applications, creating links between pages is a must. Instead |
| 211 | +of hardcoding URLs in templates, the ``router`` helper knows how to generate |
| 212 | +URLs based on the routing configuration. That way, all your URLs can be easily |
| 213 | +updated by changing the configuration: |
| 214 | + |
| 215 | +.. code-block:: html+php |
| 216 | + |
| 217 | + <a href="<?php echo $view['router']->generate('hello', array('name' => 'Thomas')) ?>"> |
| 218 | + Greet Thomas! |
| 219 | + </a> |
| 220 | + |
| 221 | +The ``generate()`` method takes the route name and an array of paremeters as |
| 222 | +arguments. The route name is the main key under which routes are referenced |
| 223 | +and the parameters are the values of the placeholders defined in the route |
| 224 | +pattern: |
| 225 | + |
| 226 | +.. code-block:: yaml |
| 227 | +
|
| 228 | + # src/Application/HelloBundle/Resources/config/routing.yml |
| 229 | + hello: # The route name |
| 230 | + pattern: /hello/:name |
| 231 | + defaults: { _controller: HelloBundle:Hello:index } |
| 232 | +
|
| 233 | +Using Assets: images, JavaScripts, and stylesheets |
| 234 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 235 | + |
| 236 | +What would the Internet be without images, JavaScripts, and stylesheets? |
| 237 | +Symfony2 provides three helpers to deal with them easily: ``assets``, |
| 238 | +``javascripts``, and ``stylesheets``: |
| 239 | + |
| 240 | +.. code-block:: html+php |
| 241 | + |
| 242 | + <link href="<?php echo $view['assets']->getUrl('css/blog.css') ?>" rel="stylesheet" type="text/css" /> |
| 243 | + |
| 244 | + <img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" /> |
| 245 | + |
| 246 | +The ``assets`` helper's main purpose is to make your application more portable. |
| 247 | +Thanks to this helper, you can move the application root directory anywhere under your |
| 248 | +web root directory without changing anything in your template's code. |
| 249 | + |
| 250 | +Similarly, you can manage your stylesheets and JavaScripts with the |
| 251 | +``stylesheets`` and ``javascripts`` helpers: |
| 252 | + |
| 253 | +.. code-block:: html+php |
| 254 | + |
| 255 | + <?php $view['javascripts']->add('js/product.js') ?> |
| 256 | + <?php $view['stylesheets']->add('css/product.css') ?> |
| 257 | + |
| 258 | +The ``add()`` method defines dependencies. To actually output these assets, you |
| 259 | +need to also add the following code in your main layout: |
| 260 | + |
| 261 | +.. code-block:: html+php |
| 262 | + |
| 263 | + <?php echo $view['javascripts'] ?> |
| 264 | + <?php echo $view['stylesheets'] ?> |
| 265 | + |
| 266 | +Output Escaping |
| 267 | +--------------- |
| 268 | + |
| 269 | +When using PHP templates, escape variables whenever they are displayed to the |
| 270 | +user:: |
| 271 | + |
| 272 | + <?php echo $view->escape($var) ?> |
| 273 | + |
| 274 | +By default, the ``escape()`` method assumes that the variable is outputted |
| 275 | +within an HTML context. The second argument lets you change the context. For |
| 276 | +instance, to output something in a JavaScript script, use the ``js`` context:: |
| 277 | + |
| 278 | + <?php echo $view->escape($var, 'js') ?> |
0 commit comments