expanded menu chapter and refactored old chapters
This commit is contained in:
parent
d9738776b2
commit
20aef6e741
3 changed files with 69 additions and 13 deletions
|
@ -118,12 +118,16 @@ To make this change we need to pass an options array to the `Mustache_Engine` co
|
||||||
```php
|
```php
|
||||||
$injector->define('Mustache_Engine', [
|
$injector->define('Mustache_Engine', [
|
||||||
':options' => [
|
':options' => [
|
||||||
'loader' => new Mustache_Loader_FilesystemLoader(dirname(__DIR__) . '/templates'),
|
'loader' => new Mustache_Loader_FilesystemLoader(dirname(__DIR__) . '/templates', [
|
||||||
|
'extension' => '.html',
|
||||||
|
]),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
```
|
```
|
||||||
|
|
||||||
In your project root folder, create a `templates` folder. In there, create a file `Homepage.mustache`. The content of the file should look like this:
|
We are passing an options array because we want to use the `.html` extension instead of the default `.mustache` extension. Why? Other template languages use a similar syntax and if we ever decide to change to something else then we won't have to rename all the template files.
|
||||||
|
|
||||||
|
In your project root folder, create a `templates` folder. In there, create a file `Homepage.html`. The content of the file should look like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
<h1>Hello World</h1>
|
<h1>Hello World</h1>
|
||||||
|
|
|
@ -86,7 +86,7 @@ You could also put the page related things into it's own package and reuse it in
|
||||||
|
|
||||||
Because PHP does not have the ability to type hint for scalar values (things like strings and integers), we have to manually check that `$pageFolder` is a string. If we don't do that, there might be a bug in the future that is hard to find if a wrong type is injected. By throwing an exception, this can be caught and debugged immediately.
|
Because PHP does not have the ability to type hint for scalar values (things like strings and integers), we have to manually check that `$pageFolder` is a string. If we don't do that, there might be a bug in the future that is hard to find if a wrong type is injected. By throwing an exception, this can be caught and debugged immediately.
|
||||||
|
|
||||||
This will do for now. Let's create a template file for our pages with the name `Page.mustache` in the `templates` folder. For now just add `{{ content }}` in there.
|
This will do for now. Let's create a template file for our pages with the name `Page.html` in the `templates` folder. For now just add `{{ content }}` in there.
|
||||||
|
|
||||||
Add the following to your `Dependencies.php` file so that the application know which implementation to inject for our new interface. We also define the the `pageFolder` there.
|
Add the following to your `Dependencies.php` file so that the application know which implementation to inject for our new interface. We also define the the `pageFolder` there.
|
||||||
|
|
||||||
|
|
|
@ -6,26 +6,78 @@ Now we have some sweet dynamic pages. But nobody can find them.
|
||||||
|
|
||||||
Let's fix that now. In this chapter we will create a menu with links to all our pages.
|
Let's fix that now. In this chapter we will create a menu with links to all our pages.
|
||||||
|
|
||||||
For a start we will just send a hardcoded array to the template. Go to you `Homepage` controller and change your `$data` array to this:
|
When we have a menu, we will want to be able to reuse the same code on multiple page. We could create a separate file and include it every time, but there is a better solution.
|
||||||
|
|
||||||
|
It is more practical to have templates that are able to extend other templates, like a layout for example. Then we can have all the layout related code in a single file and we don't have to include header and footer files in every template.
|
||||||
|
|
||||||
|
Sadly our implementation of mustache does not support this. We could write code to work around this, which will take time and could introduce some bugs. Or we could switch to a library that already supports this and is well tested. [Twig](http://twig.sensiolabs.org/) for example.
|
||||||
|
|
||||||
|
Now you might wonder why we didn't start with Twig right away. This is a good example to show why using interfaces and writing loosely-coupled code is a good idea.
|
||||||
|
|
||||||
|
Remember how you created a `MustacheRenderer` in [chapter 9](09-templating.md)? This time, we create a `TwigRenderer` that implements the same interface.
|
||||||
|
|
||||||
|
But before we start, install the latest version of Twig with composer.
|
||||||
|
|
||||||
|
Then create the a `TwigRenderer.php` in your `src/Template` folder that looks like this:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Example\Template;
|
||||||
|
|
||||||
|
use Twig_Environment;
|
||||||
|
|
||||||
|
class TwigRenderer implements Renderer
|
||||||
|
{
|
||||||
|
private $renderer;
|
||||||
|
|
||||||
|
public function __construct(Twig_Environment $renderer)
|
||||||
|
{
|
||||||
|
$this->renderer = $renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render($template, $data = [])
|
||||||
|
{
|
||||||
|
return $this->renderer->render("$template.html", $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, on the render function call a `.html` is added. This is because Twig does not add a file ending by default and you would have to specifiy it on every call otherwise. By doing it like this, you can use it in the same way as you used Mustache.
|
||||||
|
|
||||||
|
Add the following code to your `Dependencies.php` file:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$injector->delegate('Twig_Environment', function() use ($injector) {
|
||||||
|
$loader = new Twig_Loader_Filesystem(dirname(__DIR__) . '/templates');
|
||||||
|
$twig = new Twig_Environment($loader);
|
||||||
|
return $twig;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of just defining the dependencies, we are using a delegate to give the responsibility to create the class to a function. This will be useful in the future.
|
||||||
|
|
||||||
|
Now you can switch the `Renderer` alias from `MustacheRenderer` to `TwigRenderer`. Now by default Twig will be used instead of Mustache.
|
||||||
|
|
||||||
|
If you have a look at the site in your browser, everything should work now as before. Now let's get started with the actual menu.
|
||||||
|
|
||||||
|
To start we will just send a hardcoded array to the template. Go to you `Homepage` controller and change your `$data` array to this:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$data = [
|
$data = [
|
||||||
'name' => $this->request->getParameter('name', 'stranger'),
|
'name' => $this->request->getParameter('name', 'stranger'),
|
||||||
'menuItems' => ['href' => '/', 'text' => 'Homepage'],
|
'menuItems' => 'menuItems' => [['href' => '/', 'text' => 'Homepage']],
|
||||||
];
|
];
|
||||||
```
|
```
|
||||||
|
|
||||||
Now add the following at the top of your `Homepage.mustache` file:
|
At the top of your `Homepage.html` file add this code:
|
||||||
|
|
||||||
```
|
```
|
||||||
{{#menuItems}}
|
{% for item in menuItems %}
|
||||||
<a href="{{ href }}">{{ text }}</a><br>
|
<a href="{{ item.href }}">{{ item.text }}</a><br>
|
||||||
{{/menuItems}}
|
{% endfor %}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now if you navigate to your homepage, you should see a link at the top.
|
Now if you refresh the homepage in the browser, you should see a link.
|
||||||
|
|
||||||
So far so good. But now we realize that we want to reuse this code snippet on every page. We could create a separate file and include it every time, but there is a better solution.
|
|
||||||
|
|
||||||
|
|
||||||
[<< previous](10-dynamic-pages.md)
|
[<< previous](10-dynamic-pages.md)
|
Loading…
Reference in a new issue