Declare the POST destination
src/routes/WebApp.php
$this->get('/books/create', [BookController::class, 'create']);
$this->post('/books', [BookController::class, 'store']);The same address can behave differently depending on its method. Here GET /books displays the list and POST /books adds a book.
Read fields without global variables
public function store(Request $request): Response
{
$title = trim((string) $request->input('title', ''));
$author = trim((string) $request->input('author', ''));
return $this->view('books/received.php', [
'title' => $title,
'author' => $author,
]);
}input('title', '') looks for the title key and returns an empty string when missing. The string cast normalizes its type; trim removes unnecessary surrounding whitespace. Reading a value does not mean it is valid.
What Request actually contains
GET, POST, PUT, PATCH, or DELETE.
Requested path, such as /books.
Values placed after ? in the address.
Combines address and submitted body values.
Request centralizes data access, enables testing, and also handles JSON or encoded bodies. This keeps the controller independent from how PHP received the request.
Test the journey before adding validation
- Check GET /books/create and POST /books with aml routes.
- Open /books/create and fill both fields.
- Submit and confirm the received values.
- Do not yet use these values to build SQL or a file name.