Documentation · Chapter 03

Workshop: build
the Books page.

You will rebuild the entire chain without copying the About page. Every step includes a check before continuing.

You will change one element at a time, in an exact file, then verify the result.

MISSION

Display three books at /books

  1. Generate BookController.
  2. Prepare an array of three books.
  3. Pass the array to books.php.
  4. Display every title and author with foreach.
  5. Declare GET /books, then verify with aml routes.

Step 1 — The controller

phpaml — zsh
aml make:controller Book

src/controllers/BookController.php

phpaml — zsh
<?php

declare(strict_types=1);

namespace App\Controllers;

use PHPAML\Http\Request;
use PHPAML\Http\Response;
use PHPAML\Mvc\Controller;

final class BookController extends Controller
{
    public function index(Request $request): Response
    {
        $books = [
            ['title' => 'Clean Code', 'author' => 'Robert C. Martin'],
            ['title' => 'The Pragmatic Programmer', 'author' => 'David Thomas & Andrew Hunt'],
            ['title' => 'Design Patterns', 'author' => 'Erich Gamma et al.'],
        ];

        return $this->view('books.php', ['books' => $books]);
    }
}

Here the data is deliberately written in the controller to learn the flow. Later, a service or repository can fetch it without changing the view's responsibility.

Step 2 — The view

src/views/books.php

phpaml — zsh
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My books</title>
</head>
<body>
    <main>
        <h1>My books</h1>
        <ul>
            <?php foreach ($books as $book): ?>
                <li>
                    <strong><?= htmlspecialchars($book['title'], ENT_QUOTES, 'UTF-8') ?></strong>
                    — <?= htmlspecialchars($book['author'], ENT_QUOTES, 'UTF-8') ?>
                </li>
            <?php endforeach; ?>
        </ul>
    </main>
</body>
</html>

foreach repeats the same HTML fragment for every array item. The colon and endforeach syntax is native PHP and especially readable inside HTML.

Step 3 — The route

src/routes/WebApp.php

phpaml — zsh
use App\Controllers\AboutController;
use App\Controllers\BookController;
use App\Controllers\HomeController;

// Dans routes():
$this->get('/', [HomeController::class, 'index']);
$this->get('/about', [AboutController::class, 'index']);
$this->get('/books', [BookController::class, 'index']);

Do not replace existing routes: add the import and new line. A class used without its full use import cannot be found.

Step 4 — Verification recipe

phpaml — zsh
aml routes
# Vérifier GET /books

aml test
  1. Confirm GET /books appears in aml routes.
  2. Open http://127.0.0.1:8910/books.
  3. Verify the three titles and authors.
  4. Run aml test to verify the project.

Useful challenges

  • Add a fourth book without changing the view.
  • Add a year property and display it as an integer.
  • Add a link from the About page to /books.
  • Later, move array creation into a BookCatalog after studying services.

SUMMARY

What to remember

  • A route connects an address to an action.
  • The controller prepares and passes data.
  • The view displays and escapes values.
  • aml routes, the browser, and aml test provide progressive verification.