Layouts provide a frame for your pages, containing all the common elements shared by most, if not all, of your templates.

The intended purpose of layouts is to avoid unnecessary repetition: instead of each view file individually including a bunch of shared files – header.php, footer.php, etc. – a layout contains all the shared elements, while the contents of the view file get injected into the layout. In many cases this approach provides greater flexibility, as well as makes the big picture easier to grasp – even more so if you're just stepping into an unfamiliar project.

Example layout file

Here's an example of what a layout file might look like (/site/templates/layouts/default.php):

<!doctype html>
<html lang="<?= $this->lang ?>">
        <!-- metadata -->
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="generator" content="ProcessWire CMS/CMF">
        <?php if ($page->meta_description): ?>
            <meta name="description" content="<?= $page->meta_description ?>">
        <?php endif; ?>
        <?php if ($page->meta_keywords): ?>
            <meta name="keywords" content="<?= $page->meta_keywords ?>">
        <?php endif; ?>
        <!-- page title -->
        <title><?= $page->title ?></title>
        <!-- stylesheets -->
        <link rel="stylesheet" href="<?= $config->urls->resources ?>css/main.css">
    <body class="template-<?= $page->template ?>">
        <header class="header">
            <h1 itemprop="headline"><?= $page->get('headline|title') ?></h1>
            <?php include $partials->menu->top ?>
            <?php include $partials->menu->breadcrumbs ?>
            <div id="content"><?= $placeholders->default ?></div>
        <footer class="footer">
            <div class="footer__column"><?= $home->footer_1 ?></div>
            <div class="footer__column"><?= $home->footer_2 ?></div>
        <script src="<?= $config->urls->resources ?>js/main.js"></script>

One key point here is that the layout file is really no more than just a regular PHP / HTML file with access to ProcessWire's API, any data you might've passed to Wireframe in the bootstrap file while initiating it (in this example the $this->lang attribute), as well as any additional data that you've passed to View from a Controller.

Actual page content is injected into $placeholders->default through the use of view placeholders. This is technically optional – you could just output the page data in the layout file itself – but often pages will have different requirements for output, in which case you need to depend on View files and View Placeholders.

Back to top