Welcome to FrostSW!

FrostMVC PHP Framework

Documentation   |   Version
FrostMVC / app / views

views/

Views are the pages your visitors see. FrostMVC uses Twig as its template engine, and every view lives in app/views with the .php.twig extension.

Rendering a view

Render a view from a controller with View::get(). The name is the path under app/views without the extension:

View::get('blog/view', ['post' => $post, 'related' => $related]);   // app/views/blog/view.php.twig

Each key of the array becomes a Twig variable:

<h1>{{ post.title }}</h1>
<p>{{ post.body|raw }}</p>

{% for item in related %}
    <a href="{{ BASEPATH }}/blog/view/{{ item.id }}">{{ item.title }}</a>
{% else %}
    <p>No related posts.</p>
{% endfor %}
Twig escapes every {{ value }} automatically. Only use |raw for HTML you trust, such as content you sanitised with Form::fip('body', 'html').

Layouts

Put the shared page frame in a base template and let each view fill in its blocks:

{# app/views/templates/base.template.php.twig #}
<html>
    <head><title>{% block pagename %}{% endblock %}{{ site.getName() }}</title></head>
    <body>{% block content %}{% endblock %}</body>
</html>

{# app/views/blog/view.php.twig #}
{% extends "templates/base.template.php.twig" %}

{% block pagename %}{{ post.title }} — {% endblock %}
{% block content %}
    <h1>{{ post.title }}</h1>
{% endblock %}

Use {% include "templates/menu.php.twig" %} for smaller reusable pieces.

Available in every view

BASEPATHYour site URL, e.g. {{ BASEPATH }}/blog.
RESOURCEPATHURL of the assets folder, e.g. {{ RESOURCEPATH }}/css/style.css.
siteThe Site instance: site.getName(), site.getEmail(), site.getEnvironment(), site.getCurrentURL()…
sessionSession: session.get('user'), and session.flash('success') to show a message once.
formForm: form.start(), form.end() and input helpers.
security, words, cookie, date_timeThe Security, Words, Cookie and Date_Time helpers.

Add your own with $instance->twig->addGlobal('name', $value) in app/settings.php. The starter settings add version (for cache-busting asset URLs) and nonce (for the Content-Security-Policy of inline scripts).

Messages after a redirect

Set a message in the controller, redirect, and show it once on the next page:

Session::set('success', 'Post saved!');
Functions::io_relocate(BASEPATH . '/blog');
{% if session.get('success') %}
    <div class="alert alert-success">{{ session.flash('success') }}</div>
{% endif %}

Forms

Open POST forms with form.start() so they carry the CSRF token FrostMVC checks on every POST request:

{{ form.start(BASEPATH ~ '/blog/save', 'post') }}
    <input name="title" value="{{ post.title }}"/>
    <button type="submit">Save</button>
{{ form.end() }}

A POST without a valid token is rejected before your controller runs. The token settings are in Security::$CSRFTokenConfig in app/settings.php.

Custom functions and filters

Register your own Twig functions and filters in libraries/TwigExtensions.php, which the starter loads at the end of settings.php. For example, the starter's makeTitle filter turns my-blog-post into My Blog Post:

$fw->twig->addFilter(new TwigFilter('makeTitle', function ($title) {
    return makeTitle($title);
}));
{{ 'my-blog-post'|makeTitle }}

Debugging

In the Development environment Twig runs in debug mode, so {{ dump(post) }} prints a variable. Compiled templates are cached in libraries/vendor/twig/tmp; delete that folder if a view does not update.

Reference: View, Form, Session