MageWork

Back to home

Add a new page

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:

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

OptionDescriptionType
classThe page class with custom logic and methodsstring
_http_codeHTTP response status codeinteger
_headersCustom headersarray

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');
    }
}