Repository navigation
PageResponse
Viames Marino edited this page Jun 12, 2026
·
2 revisions
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. Use FragmentResponse instead when a progressive request should update only one HTML region.
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, FragmentResponse, Input, ReadModel, ResponseInterface, Observability, View.
Maintained by Viames Marino — VM Ingegneria · Professional enquiries
Home · Setup · Configuration
Build with Pair 4
- Generator
- Controllers and responses
- Read models
- ActiveRecord and queries
- Forms and validation
- PairUI.js and HTML fragments
APIs and authentication
- API guide and CRUD
- Middleware and rate limits
- Users, sessions, and ACL
- Passkeys and social login
- Native mobile setup
Integrate and operate
- Integrations
- Runtime extensions and adapter keys
- Cache and cache stores
- Logs and observability
- PWA and push
- Packages and distribution
- Upgrade to v4