PageResponse - viames/pair GitHub Wiki
Pair\Web\PageResponse is the explicit Pair v4 HTML page response.
Use it from Pair\Web\Controller actions when a module should render a PHP layout with a typed page-state object.
Arguments:
-
templateFile: absolute path to the layout file. -
state: typed state object exposed to the layout as$state. -
title: optional page title forwarded toApplication.
Example:
use Pair\Web\PageResponse;
return new PageResponse(
APPLICATION_PATH . '/modules/audit/layouts/default.php',
new AuditPageState($rows),
'Audit'
);Most application code should build it through Pair\Web\Controller::page() so the layout path is resolved from the current module:
use Pair\Web\Controller;
use Pair\Web\PageResponse;
require_once __DIR__ . '/classes/AuditDefaultPageState.php';
/**
* Audit web module using the explicit Pair v4 page response.
*/
final class AuditController extends Controller {
/**
* Render the default audit page.
*/
public function defaultAction(): PageResponse {
$state = new AuditDefaultPageState(
title: 'Audit',
rows: Audit::query()->latest('createdAt')->limit(20)->get()
);
return $this->page('default', $state, 'Audit');
}
}Typed page state:
use Pair\Data\ArraySerializableData;
use Pair\Data\ReadModel;
use Pair\Orm\Collection;
/**
* State exposed to the audit default layout as $state.
*/
final readonly class AuditDefaultPageState implements ReadModel {
use ArraySerializableData;
/**
* Build the audit page state.
*/
public function __construct(
public string $title,
public Collection $rows
) {}
/**
* Export the state for optional JSON/debug reuse.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'title' => $this->title,
'rows' => $this->rows->all(),
];
}
}Layout file:
<?php
/** @var AuditDefaultPageState $state */
?>
<section class="audit-page">
<h1><?= htmlspecialchars($state->title, ENT_QUOTES, 'UTF-8') ?></h1>
<ul>
<?php foreach ($state->rows as $row): ?>
<li><?= htmlspecialchars((string)$row->message, ENT_QUOTES, 'UTF-8') ?></li>
<?php endforeach; ?>
</ul>
</section>-
send()validates that the template file exists. - If a title is provided, it updates
Application::pageTitle(...). - The layout receives only
$state, keeping the template contract explicit. - When
Observabilityis enabled,send()records apage.responsespan with the template filename and state class.
See also: Application, Controller, Input, ReadModel, ResponseInterface, Observability, View.