Przewodnik

Controllery i odpowiedzi

Co zapewnia `AbstractController` i kiedy warto dodać wspólną warstwę aplikacji.

Baza frameworka: AbstractController

Framework udostępnia AbstractController z helperami do requestów, response i usług, między innymi view(), url(), validator(), flash(), filesystem(), upload(), translator() i breadcrumb().

example.php
<?php

declare(strict_types=1);

namespace App\Controllers;

use Lemonade\Framework\Core\AbstractController;
use Psr\Http\Message\ResponseInterface;

final class ArticleController extends AbstractController
{
    public function detail(int $id): ResponseInterface
    {
        return $this->json([
            'id' => $id,
            'expects_json' => $this->expectsJson(),
        ]);
    }
}

Wspólny controller aplikacji

Aplikacja może opcjonalnie dodać AppController extends AbstractController. Przydaje się do wspólnego renderowania, współdzielonych danych, metadanych, breadcrumbs lub drobnych helperów. Nie jest to wymaganie frameworka.

example.php
<?php

declare(strict_types=1);

namespace App\Controllers;

use Lemonade\Framework\Core\AbstractController;
use Psr\Http\Message\ResponseInterface;

abstract class AppController extends AbstractController
{
    /**
     * @param array<string, mixed> $data
     */
    protected function page(string $view, array $data = [], int $status = 200): ResponseInterface
    {
        return $this->html(
            $this->view()->template(
                'layouts.app',
                $view,
                $data,
            ),
            $status,
        );
    }
}

Dodatkowe warstwy w większych aplikacjach

W większej aplikacji nad AppController możesz dodać kolejne warstwy dla strony publicznej, administracji, obsługi locale lub canonical redirectów. To decyzja architektoniczna aplikacji, a nie wymagana hierarchia frameworka.

example.php
AbstractController
    ↓
Optional application base controller
    ↓
Optional specialized controller
    ↓
Concrete controller

Możesz też używać czystych controllerów PSR

Controller nie musi dziedziczyć po AbstractController, jeśli wolisz składać odpowiedzi PSR bezpośrednio za pomocą ResponseFactoryInterface i StreamFactoryInterface.

example.php
<?php

declare(strict_types=1);

namespace App\Controllers;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;

final class StatusController
{
    public function __construct(
        private readonly ResponseFactoryInterface $responses,
        private readonly StreamFactoryInterface $streams,
    ) {}

    public function index(): ResponseInterface
    {
        return $this->responses
            ->createResponse(200)
            ->withHeader('Content-Type', 'text/html; charset=UTF-8')
            ->withBody($this->streams->createStream('<h1>Status OK</h1>'));
    }
}