Views and Templates

4 vues Markdown

A controller collects named values and hands them to the view with a template name. The template reads those names as variables and prints the page.

Overview

Producing a page takes two calls. chose() picks the template directory; render() runs a template inside it with the data collected so far. The data arrives in the template as ordinary variables named after the keys, so a template never fetches anything for itself.

The admin panel's templates are plain PHP and ship with the product. The website's are a theme's, and the same call selects the active theme instead of a fixed directory.

Reference

Signatures

All five are instance methods. Inside a controller the instance is $this->view; anywhere else it is the singleton View::$init.

coremio/classes/View.php
public function chose($dir, $noTemplate = false): self;
public function render($_name = null, $data = [], $return_output = false, $source = false): mixed;

public function get_template_dir($type = 'website'): string;   // TEMPLATE_DIR . $type . DS
public function get_template_url($type = 'website'): string;   // APP_URI . "/templates/{$type}/"
public function get_resources_url($str = '', $l_slash = true, $r_slash = false): string;

The Four Parameters of render()

$_name Template path relative to the chosen directory, without the extension: 'widgets/list' resolves to templates/admin/widgets/list.php. A missing file returns an empty string rather than raising.
$data Key/value map extracted into variables before the template runs. Pass the controller's collected data, $this->data. Anything that is not an array is treated as empty.
$return_output false prints the markup and returns an empty string; true returns it instead. A page method returns its page, so it passes true.
$source true includes the file and hands back the value the file returns, printing nothing. This is how a template that is really a data file (a returned array) is read. false when the file is missing.

What chose() Accepts

ArgumentResolves toWhen
'admin'templates/admin/, plain PHPEvery admin screen
'website'The active theme's directory and engineA visitor request. In an admin or cron context this falls back to templates/website/ as plain PHP
'system'templates/system/, plain PHPFatal error, maintenance, invoice document
any path with $noTemplate = trueThe path exactly as givenA module using its own template directory

How Data Reaches a Template

Values added by the controller are extracted into variables before the template runs. A value added under the name rows is read as $rows. On top of those, the view adds five of its own to every call:

$template_dir Filesystem path of the chosen directory, with a trailing separator. This is what lets one template include another without knowing where it lives.
$ui_lang The language resolved for this request, e.g. 'en'. Only set when the controller did not already supply it.
$ui_dir Writing direction for that language, 'ltr' or 'rtl'. Print it on the root element; never hard-code a direction.
$badress, $tadress, $sadress Base address of the installation, of the chosen template directory, and of the shared resources directory. Use them for asset links instead of composing URLs by hand.
$setting Themed website pages only: the active theme's merged settings, schema defaults included. Absent in admin and system templates.

Example

The two halves together: the controller names the values, the template reads those exact names back.

controller
public function page_list(&$links, &$meta, &$breadcrumbs): string
{
    $this->addData('rows', $this->model->list());
    $this->addData('total', $this->model->list(true));

    // Third argument true: return the markup instead of printing it, because the
    // page method's job is to RETURN the rendered page.
    return $this->view->chose('admin')->render('widgets/list', $this->data, true);
}
templates/admin/widgets/list.php
<?php if (!defined("CORE_DIR")) exit(); ?>

<h1><?= Language::g("widgets-title") ?> (<?= (int) ($total ?? 0) ?>)</h1>

<?php foreach (($rows ?? []) as $row): ?>
    <div class="card">
        <span><?= htmlspecialchars($row['name'] ?? '') ?></span>
    </div>
<?php endforeach; ?>

<?php include $template_dir . "inc" . DS . "footer.php"; ?>

Reading a template that returns data instead of printing it, and producing a theme view from a background job:

the other two call shapes
// $source = true: the file's own return value comes back, nothing is printed.
$columns = View::$init->chose('admin')->render('tables/widgetList', [], false, true);

// Outside a visitor request (cron, mail, PDF) the theme is NOT resolved by chose('website').
// Ask the theme itself, which resolves engine and directory regardless of context.
$html = Theme::active()->render('account/invoice-pdf', ['invoice' => $invoice]);

Pitfalls

Escape everything a person typed

An admin template is plain PHP with no automatic escaping. A value that came from a form, an API or a remote provider appears exactly as it arrived. Escaping it is your job.

A background job cannot select the theme with chose('website')

Theme resolution is skipped outside a visitor request, so the call falls back to plain PHP. It looks for a .php file the theme does not have and returns an empty string with no error. Produce the view through the theme object instead.

A template refuses to be entered directly

Every template starts by exiting when the application's constants are absent. Without that line the file is a URL that runs part of a page with no session, no permissions and no data.

Read every key with a default

A missing key inside a loop raises one warning per row, and each warning is a disk write. In a list template that is the difference between a fast page and a slow one.

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Besoin d'aide supplémentaire ?

Notre équipe d'assistance est disponible 24h/24 pour tout ce que vous ne trouvez pas ci-dessus.