(You are reading the documentation for HTML v2. Switch to the documentation for Html v1.)

HTML

Install

In order to have an HTML reprensentation, Let’s install Twig v2 module with composer.

composer require madapaja/twig-module ^2.0

Next create the context file src/Module/HtmlModule.php and install the TwigModule.

namespace MyVendor\MyPackage\Module;

use BEAR\AppMeta\AppMeta;
use Madapaja\TwigModule\TwigErrorPageModule;
use Madapaja\TwigModule\TwigModule;
use Ray\Di\AbstractModule;

class HtmlModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new TwigModule);
        $this->install(new TwigErrorPageModule);
    }
}

Update the context in bin/page.php or public/index.php and enable html.

$context = 'cli-html-app'; // or 'html-app'

Template

One template file is required for one resource object class in var/templates directory to represent in HTML. For example, for src/Page/Index.php resource class, a template file is required in var/templates/Page/Index.html.twig.

The body of the resource is assigned to the template.

example)

src/Page/Index.php

class Index extend ResourceObject
{
    public $body = [
        ['greeting' => 'Hello BEAR.Sunday']
    ];
}

var/templates/Page/Index.twig.php

<h1>{{ greeting }}</h1>

Output:

php bin/page.php get /
200 OK
content-type: text/html; charset=utf-8

<h1>Hello BEAR.Sunday</h1>

Select template file

Resource does not select the template file. It includes depending on the state of the resource.

{% if user.is_login %}
    {{ include('member.html.twig') }}
{% else %}
    {{ include('guest.html.twig') }}
{% endif %}

In the resource class, you should only concern resource state. Then template should concern the resource representation. See Separation of concerns (SoC).

Error Page

Edit var/templates/error.html.twig. Following values are assigned to the error page.

Variable Title Key
status HTTP status code, message
e Exception code, message, class
logref Log ID n/a

{% extends 'layout/base.html.twig' %}
{% block title %}{{ status.code }} {{ status.message }}{% endblock %}
{% block content %}
    <h1>{{ status.code }} {{ status.message }}</h1>
    {% if status.code == 404 %}
        <p>The requested URL was not found on this server.</p>
    {% else %}
        <p>The server is temporarily unable to service your request.</p>
        <p>refference number: {{ logref }}</p>
    {% endif %}
{% endblock %}

Assign resource

To refer to the properties of the resource object class, Use _ro (resource object) to which the entire resource object is assigned

exmaple)

Todos.php

class Todos extend ResourceObject
{
    public $code = 200;

    public $text = [
        'name' => 'BEAR';
    ];    

    public $body = [
        ['title' => 'run']
    ];
}

Todos.html.twig

{{ _ro.code }} // 200
{{ _ro.text.name }} // 'BEAR'
{% for todo in _ro.body %}
  {{ todo.title }} // 'run'
{% endfor %}

Hierarchical view structure

You can have a view on a resource class basis. It represents the structure well. Also, the cache is also hierarchically done on a resource basis, so it is efficient.

example) page://self/index which embeds app://self/todos

app://self/todos

class Todos extends ResourceObject
{
    use AuraSqlInject;
    use QueryLocatorInject;

    public function onGet() : ResourceObject
    {
        $this->body = $this->pdo->fetchAll($this->query['todos_list'])
        return $this;
    }
}
{% for todo in _ro.body %}
  {{ todo.title }}</td>
{% endfor %}

page://self/index

class Index extends ResourceObject
{
    /**
     * @Embed(rel="todos", src="app://self/todos")
     */
    public function onGet() : ResourceObject
    {
        return $this;
    }
}
{% extends 'layout/base.html.twig' %}
{% block content %}
  {{ todos|raw }}
{% endblock %}

Extending Twig

When you extend Twig with the addExtension() method, prepare Twig’s Provider class which performs extension and bind Provider to Twig_Environment class.

use Ray\Di\Di\Named;
use Ray\Di\ProviderInterface;

class MyTwigProvider implements ProviderInterface
{
    private $twig;

    /**
     * @Named("original")
     */
    public function __construct(\Twig_Environment $twig)
    {
        // $twig is an original \Twig_Environment instance
        $this->twig = $twig;
    }

    public function get()
    {
        // Extending Twig
        $this->twig->addExtension(new MyTwigExtension());

        return $this->twig;
    }
}
class HtmlModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new TwigModule);
        $this->bind(\Twig_Environment::class)->toProvider(MyTwigProvider::class)->in(Scope::SINGLETON);
    }
}

Template for mobile device

To use the template for mobile devices, install MobileTwigModule.

class HtmlModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new TwigModule);
        $this->install(new MobileTwigModule);
    }
}

If there is a mobile site template Index.mobile.twig that will replace Index.html.twig, it will be used in preference.

Custom Settings

If you would like to change options depending on the context or add a template path, configuration values are bound to @TwigPathsand @TwigOptions annotations.

Note: Since caches are always created in the var/tmp folder, there is no particular need for special settings for production.

namespace MyVendor\MyPackage\Module;

use Madapaja\TwigModule\Annotation\TwigDebug;
use Madapaja\TwigModule\Annotation\TwigOptions;
use Madapaja\TwigModule\Annotation\TwigPaths;
use Madapaja\TwigModule\TwigModule;
use BEAR\Package\AbstractAppModule;

class AppModule extends AbstractAppModule
{
    protected function configure()
    {
        // ...
        $this->install(new TwigModule);

        // You can add twig template paths by the following
        $appDir = $this->appMeta->appDir;
        $paths = [
            $appDir . '/src/Resource',
            $appDir . '/var/templates'
        ];
        $this->bind()->annotatedWith(TwigPaths::class)->toInstance($paths);

        // Also you can set environment options
        // @see http://twig.sensiolabs.org/doc/api.html#environment-options
        $options = [
            'debug' => false,
            'cache' => $appDir . '/tmp'
        ];
        $this->bind()->annotatedWith(TwigOptions::class)->toInstance($options);
        
        // Only for debug option
        $this->bind()->annotatedWith(TwigDebug::class)->toInstance(true);
    }
}