Views & Templating

While the controller handles the incoming request, the view is responsible for rendering the response. To achieve this, it utilizes a templating engine. In Pagekit, you can use plain PHP templates or the Twig templating engine.

Rendered view response

The most common way to render a view is to return an array from your controller action. Use the $view property to pass parameters to your view renderer.

  1. public function indexAction($name = '')
  2. {
  3. return [
  4. '$view' => [
  5.  
  6. // Rendered in the site's <title>
  7. 'title' => 'Hello World',
  8.  
  9. // view file that is rendered
  10. 'name' => 'hello:views/index.php',
  11. ],
  12.  
  13. // pass parameters to view file
  14. 'name' => $name
  15. ];
  16. }

The rendered view file could look like this:

  1. <!-- packages/pagekit/extension-hello/views/index.php -->
  2.  
  3. <h1>Hello <?= $name ?></h1>
  4. <p>
  5. ...
  6. </p>

This view is wrapped in the main layout by default. To avoid this behavior, you can change 'layout' => false in the $view array.

Render a view manually

You can also manually access the View service to render a template file. This may come in handy, if you dynamically determine which view to load. Note that hello: in the example below refers to the resource shorthand as defined in the package's module definition.

  1. use Pagekit\Application as App;
  2.  
  3. class MyController {
  4.  
  5. public function anotherViewAction()
  6. {
  7. return App::view()->render('hello:views/view.php', ['id' => 1]);
  8. }
  9.  
  10. }

The according view file:

  1. <!-- packages/pagekit/extension-hello/views/index.php -->
  2.  
  3. <h1>You are viewing article number <?= $id ?></h1>
  4. <p>
  5. ...
  6. </p>

Templating

The views are rendered using the PHP templating engine, which offers defined global template variables and a set of view helpers.

Including other views

Rendering sub views from your view is done with the $view helper. The render method evaluates and returns the content of the given template file. This is identical to rendering the view manually from the controller.

  1. $view->render('hello:views/view.php', ['id' => 1])

As seen earlier, each route has a name that you can use to dynamically generate links to the specific route. There is a Url helper that exposes the functions of the UrlProvider.

  1. <a href="<?= $view->url('@hello/default/view') ?>">View all articles</a>
  2. <a href="<?= $view->url('@hello/default/view', ['id' => 23]) ?>">View article 23</a>

You can link to assets, like images or other files, using the getStatic($path) method of the URL provider.

  1. <img src="<?= $view->url()->getStatic('hello:extension.svg') ?>" alt="Extension icon" />

Working with Assets

Assets are the static files needed in your project, including CSS, JS and image files.

Generate URL to static assets

To generate a route to a static asset, use the getStatic method of the UrlProvider class.

  1. <img src="<?= $view->url()->getStatic('my-assets/image.jpg') ?>">

Include CSS in view file

To include a CSS file in your view, call the style helper from the View.

  1. $view->style($id, $path [, $dependencies ])

The first parameter is a unique identifier for the stylesheet. If you use the same identifier for multiple stylesheets, Pagekit will only include the last one. The second parameter is the path of the stylesheet where you can use theme: as a reference to the root directory of the 'theme' package. You can define its dependencies through the optional third parameter.

Example:

  1. <?php $view->style('theme', 'theme:css/theme.css') ?>
  2. <?php $view->style('theme', 'theme:css/theme.css', 'uikit') ?>
  3. <?php $view->style('theme', 'theme:css/theme.css', ['uikit', 'somethingelse']) ?>

Note This will not directly output the required line in HTML. Instead, it will add the CSS file to the Pagekit Asset Manager. The stylesheet will be included in the <head> section of your theme.

Include JS in view file

To include a JavaScript file in your template, call the script helper from the $view object which works exactly like the style helper.

  1. $view->script($id, $path [, $dependencies ])

The first parameter is a unique identifier for the script asset. If you use the same identifier for multiple scripts, Pagekit will only include the last one. The second parameter is the path of the script where you can use theme: as a reference to the root directory of the 'theme' package. You can define its dependencies through the optional third parameter.

Example:

  1. <?php $view->script('theme', 'theme:js/theme.js') ?>
  2. <?php $view->script('theme', 'theme:js/theme.js', 'jquery') ?>
  3. <?php $view->script('theme', 'theme:js/theme.js', ['jquery', 'uikit']) ?>

Note Internally, style() and script() each work with their own Asset Manager. As these are separate from each other, you can assign the same name to a CSS and JS file without conflict (both called theme in the above example). However, no two scripts or stylesheets may have the same identifier. For example, when adding two stylesheets, one could be named 'theme', and the other 'custom'.

Async and deferred script execution

By default, a script that is included in the head section of the rendered HML markup, is fetched and executed immediately. Only afterwards does the browser continue to parse the page.

To change this behaviour, you can use the keywords async and defer when loading a script. Set the appropriate option in your PHP code and the resulting <script> tag will have these attributes set accordingly.

AttributeDescription
asyncTell the browser to execute the script asynchronously which means that parsing the page continues even while the script is being executed
deferTell the browser that the script is meant to be executed after the document has been parsed. Browser support of this HTML feature is not perfect, but using it might only cause problems in cases where the execution order of scripts is important.

Example: Deferred execution, no dependencies.

  1. <?php $view->script('theme', 'theme:js/theme.js', [], ['defer' => true]) ?>

Example: Deferred and async execution, with dependencies.

  1. <?php $view->script('theme', 'theme:js/theme.js', ['jquery', 'uikit'], ['defer' => true, 'async' => true]) ?>

Twig templates

Instead of using plain PHP for templating, you can also use Twig for your theme and extension templates. You can find documentation on the basic Twig syntax and features in the official Twig docs. Similar to the official Hello theme for default PHP templating, a boilerplate Twig theme also exists and can be used as a starting point.

Building themes with Twig

By default, the main template file that Pagekit uses from a theme is located at views/template.php and it is rendered using the default PHP renderer. In your theme's index.php you can define a different layout file to be used as the main template.

  1. /**
  2. * Change default layout to use a Twig template.
  3. */
  4. 'layout' => 'views:template.twig',

The file extension *.twig will cause Pagekit to render this template with the Twig engine. A basic example for your theme's views/template.twig looks as follows.

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. {{ view.render('head') | raw }}
  8. {{ view.style('theme', 'theme:css/theme.css') }}
  9. {{ view.script('theme', 'theme:js/theme.js') }}
  10. </head>
  11. <body>
  12. <!-- Render logo or title with site URL -->
  13. <a href="{{ view.url().get() }}">
  14. {% set logo = params.logo %}
  15. {% if logo %}
  16. <img src="{{ logo }}" alt="Logo">
  17. {% else %}
  18. {{ params.title }}
  19. {% endif %}
  20. </a>
  21. <!-- Render menu position -->
  22. {% if view.menu().exists('main') %}
  23. {{ view.menu('main') | raw }}
  24. {% endif %}
  25. <!-- Render widget position -->
  26. {% if view.position().exists('sidebar') %}
  27. {{ view.position('sidebar') | raw }}
  28. {% endif %}
  29. <!-- Render system messages -->
  30. {{ view.render('messages') | raw }}
  31. <!-- Render content -->
  32. {{ view.render('content') | raw }}
  33. <!-- Insert code before the closing body tag -->
  34. {{ view.render('footer') | raw }}
  35. </body>
  36. </html>

As you can see, you can use basic Twig syntax for outputting escaped content ({{ … }}) and non-escaped output ({{ … | raw }}). Default control structures like if and for are available, for details please look at the Twig syntax documentation.

Pagekit's view helpers and functions are exposed via the view renderer, which is available as view inside the template. PHP expressions can simply be translated to Twig syntax, for example for adding a CSS file to the current page:

  1. <!-- PHP version -->
  2. <?php $view->style('theme', 'theme:css/theme.css'); ?>
  3.  
  4. <!-- Twig version -->
  5. {{ view.style('theme', 'theme:css/theme.css') }}