PageResponse - viames/pair GitHub Wiki

Pair framework: PageResponse

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.

Constructor

new PageResponse(string $templateFile, object $state, ?string $title = null)

Arguments:

  • templateFile: absolute path to the layout file.
  • state: typed state object exposed to the layout as $state.
  • title: optional page title forwarded to Application.

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>

Behavior

  • 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 Observability is enabled, send() records a page.response span with the template filename and state class.

See also: Application, Controller, Input, ReadModel, ResponseInterface, Observability, View.

⚠️ **GitHub.com Fallback** ⚠️