Add a new page
- Create the page
- System Options
- Request data
- Handle a form submission
- HTTP response status code
- Custom headers
- Redirection
- Forward
Create the page
Open the packages/Acme/etc/pages.php file, and add a new page:
<?php
$config = [
Core_Page::TYPE => [
/* ... */
'/contact.html' => [
'class' => Acme_Page_Contact::class, // Optional
'content' => 'content/contact',
'meta_title' => 'Contact',
'meta_description' => 'Contact our team',
'telephone' => '+33 610506070',
],
/* ... */
],
];
The configuration key is the route (with its leading slash) — there is no separate page name. class is optional: without it the page falls back to Acme_Page, then Core_Page (see Objects and class fallback).
Warning:
- For a route with an extension, the first slash is required:
/slug.html - For a route without an extension, the first and last slashes are required:
/slug/
Create a new class: packages/Acme/Page/Contact.php
<?php
declare(strict_types=1);
class Acme_Page_Contact extends Core_Page
{
public function execute(): void
{
$this->setAddress("459 Walker Cape, Powellchester, OL16 3NA");
}
public function getEmail(): string
{
return 'john.doe@example.com';
}
}
The execute method is called before template rendering. It allows you to implement the code logic and inject data into the template.
Finally, create the template file: packages/Acme/template/content/contact.phtml
<h2>Contact us!</h2>
<p>Telephone: <?= App::escapeHtml($this->getTelephone()) ?></p>
<p>Address: <?= App::escapeHtml($this->getAddress()) ?></p>
<p>Email: <?= App::escapeHtml($this->getEmail()) ?></p>
Access to /contact.html in your browser!
System Options
| Option | Description | Type |
|---|---|---|
| class | The page class with custom logic and methods | string |
| _http_code | HTTP response status code | integer |
| _headers | Custom headers | array |
Request data
Inside a page class, dataPost() and dataGet() return a DataObject built from $_POST and $_GET:
<?php
declare(strict_types=1);
class Acme_Page_Search extends Core_Page
{
public function execute(): void
{
$query = $this->dataGet()->getData('q'); // ?q=...
$page = (int)($this->dataGet()->getData('page') ?: 1);
$this->setData('results', App::getSingleton('catalog', Core_Model::TYPE)->search($query, $page));
}
}
<?php
$firstname = $this->dataPost()->getData('firstname');
$all = $this->dataPost()->getData(); // every posted field
Handle a form submission
A form posts to its own route. Declare that route like any other page and point it at a handler class:
packages/Acme/etc/pages.php
<?php
$config = [
Core_Page::TYPE => [
/* ... */
'/contact/post/' => [ // route without extension: first *and* last slash
'class' => Acme_Page_Contact_Post::class,
'template' => null,
],
/* ... */
],
];
packages/Acme/Page/Contact/Post.php
<?php
declare(strict_types=1);
class Acme_Page_Contact_Post extends Core_Page
{
public function execute(): void
{
$post = $this->dataPost();
// ... validate the fields, send the mail, store a flash message ...
$this->setSuccessMessage('Your message has been sent.');
$this->redirect('contact.html');
}
}
redirect() ends the request, so a POST handler never renders a template. See Forms for field validation and mailing, Captcha for the anti-bot check, and Session messages to display the result after the redirect.
HTTP response status code
You can force the page HTTP response code with the _http_code parameter:
<?php
$config = [
Core_Page::TYPE => [
/* ... */
'/teapot.html' => [
'_http_code' => 418,
'class' => Acme_Page_Teapot::class,
'content' => 'content/teapot',
'meta_title' => 'Teapot',
],
/* ... */
],
];
Or in the page class:
<?php
declare(strict_types=1);
class Acme_Page_Teapot extends Core_Page
{
public function execute(): void
{
$this->setData('_http_code', 418);
}
}
Custom headers
The _headers parameter allows you to send custom headers:
<?php
$config = [
Core_Page::TYPE => [
/* ... */
'default' => [
'_headers' => [
'Content-Security-Policy' => 'default-src \'self\'',
'X-Frame-Options' => 'DENY',
'X-XSS-Protection' => '1; mode=block',
'X-UA-Compatible' => 'IE=Edge',
'X-Content-Type-Options' => 'nosniff',
],
],
/* ... */
],
];
Or in the page class:
<?php
declare(strict_types=1);
class Acme_Page_Teapot extends Core_Page
{
public function execute(): void
{
$this->setData(
'_headers',
array_merge(
$this->getData('_headers') ?: [],
['X-MageWork' => 1]
)
);
}
}
Redirection
A static redirect can be declared in the configuration:
<?php
$config = [
Core_Page::TYPE => [
/* ... */
'/old-page.html' => [
'_http_code' => 301,
'_headers' => [
'location' => '/new-page.html',
],
],
/* ... */
],
];
From a page class, use redirect(). A path is turned into a full URL with getUrl(); an absolute URL is used as-is; no argument redirects to the home page.
<?php
public function execute(): void
{
if (!App::session()?->has('customer_id')) {
$this->redirect('login.html');
}
}
Forward
forward() renders another route in place of the current one, without changing the URL
or sending a redirect:
<?php
public function execute(): void
{
if (!$this->isAllowed()) {
$this->forward('/403.html');
}
}
- Installation
- Configuration
- Add a new package
- Add a new HTML page
- Templating best practices
- Add a new block
- Assets
- Serve any type of file
- Rewrite a route
- Data assignment
- Objects and class fallback
- Models
- Database
- Forms
- Session messages
- Send emails
- Captcha
- Framework tools
- Console Commands
- Hooks
- Custom shared libraries
- External libraries with composer
- Write content in Markdown
- Static Site Generator