Views & Layouts

Once a controller action finishes its work, CakePHP hands off to the view layer to turn that data into HTML. Views are plain .php template files that live in predictable locations, and a layout wraps every view in the shared page furniture — header, navigation, footer — so you don't repeat that markup on every page.

Where View Files Live

Following the same convention-over-configuration idea from the previous pages, CakePHP looks for a view template at a path built from the controller and action name:

Controller / ActionTemplate file CakePHP looks for
ArticlesController::index()templates/Articles/index.php
ArticlesController::view()templates/Articles/view.php
UsersController::login()templates/Users/login.php

So the index() action on ArticlesController (the one we set up in Controllers) automatically renders templates/Articles/index.php — there's no line of code anywhere that says "render this file"; the folder and file name are the wiring.

Getting Data Into the View

A controller action makes data available to its view with $this->set(). Whatever you pass becomes a plain, directly-usable variable inside the template — no extra unpacking needed.

<?php
namespace App\Controller;

class ArticlesController extends AppController
{
    public function index()
    {
        $articles = $this->Articles->find()->all();
        $this->set('articles', $articles);
    }
}

Because of that set('articles', $articles) call, the view file at templates/Articles/index.php can simply refer to $articles directly, as shown in the worked example below.

Worked Example: A Simple Index View

Here is a realistic templates/Articles/index.php that loops over the $articles variable set by the controller above and renders a list of titles.

<h1>Articles</h1>

<ul>
<?php foreach ($articles as $article): ?>
    <li>
        <?= h($article->title) ?>
    </li>
<?php endforeach; ?>
</ul>
Note: h() is CakePHP's shortcut for htmlspecialchars() — always wrap user-supplied data with it before printing to avoid XSS, the same concern covered on Core PHP's Security page.

Layouts: The Shared Page Wrapper

A layout is the outer HTML that surrounds every view — the <html>, <head>, navigation, and footer markup you don't want to retype in each template. By default CakePHP wraps every rendered view in templates/layout/default.php. Inside that file, one line marks the spot where the current view's own content gets inserted:

<!DOCTYPE html>
<html>
<head>
    <title>My Site</title>
</head>
<body>
    <?= $this->fetch('content') ?>
</body>
</html>

Every time templates/Articles/index.php (or any other view) renders, its output is captured and dropped into that $this->fetch('content') spot inside the layout — you never have to include the layout manually.

View Blocks: Targeting Specific Layout Regions

Sometimes a single view needs to inject content into a part of the layout other than the main content area — a page-specific <title>, or an extra CSS/JS file only that page needs. CakePHP calls these named regions blocks. A view starts a block, writes into it, and ends it; the layout later fetches that named block wherever it needs it.

<?php $this->start('scripts'); ?>
    <script src="/js/articles.js"></script>
<?php $this->end(); ?>

Then, wherever the layout wants that content printed — typically just before </body> — it fetches the block by name:

<?= $this->fetch('scripts') ?>

This keeps page-specific scripts and styles defined right inside the view they belong to, while still letting the layout decide exactly where they end up on the page.

Next steps: Views display data — but where does that data actually come from? Head to Models & the ORM to see how $this->Articles fetches records from the database in the first place.