Documentation · Chapter 05

Organize views
by feature.

As an application grows, precise names and predictable folders prevent random searching.

We improve reading-list without changing its HTTP logic or temporary session storage.

Keep Books views together

phpaml — zsh
src/views/books/index.php
src/views/books/create.php
src/views/books/edit.php

The controller path is always relative to src/views. Controller calls must therefore be updated.

phpaml — zsh
return $this->view('books/index.php', ['books' => $books]);
return $this->view('books/create.php', ['errors' => [], 'old' => []]);
return $this->view('books/edit.php', ['book' => $book, 'errors' => []]);

Extract the shared form

src/views/partials/book-form.php

phpaml — zsh
<label for="title">Title</label>
<input id="title" name="title" type="text" required
       value="<?= $view->escape($values['title'] ?? '') ?>">
<?php foreach ($errors['title'] ?? [] as $error): ?>
    <p class="field-error" role="alert"><?= $view->escape($error) ?></p>
<?php endforeach; ?>

<label for="author">Author</label>
<input id="author" name="author" type="text" required
       value="<?= $view->escape($values['author'] ?? '') ?>">
<?php foreach ($errors['author'] ?? [] as $error): ?>
    <p class="field-error" role="alert"><?= $view->escape($error) ?></p>
<?php endforeach; ?>

Use it for create and edit

phpaml — zsh
<form method="post" action="<?= $view->escape($action) ?>">
    <?= $view->csrfField() ?>
    <?php $view->partial('book-form.php', [
        'values' => $values,
        'errors' => $errors,
    ]) ?>
    <button type="submit"><?= $view->escape($submitLabel) ?></button>
</form>

The controller passes action, values, and submitLabel. The same partial displays fields; the page remains responsible for submission address and button text.

Practical rule

Extract a partial when the same block truly appears on several pages or represents a clear unit such as navigation. Do not split every element into a file: too many tiny files make the flow harder to follow.