Views a formuláře
Renderer vykreslí PHP view, funkce e() escapuje dynamický výstup a csrfField() vloží skryté pole s CSRF tokenem.
Předání dat do view
Controller načte článek z aplikační ArticleRepository a předá jej ViewRendererInterface::render() pod klíčem article. Název articles.detail vybírá PHP view z dalšího souboru; render() vrací HTML odpověď. Pokud je potřeba jen vykreslený řetězec, rozhraní má také content().
<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Services\ArticleRepository;
use Lemonade\Framework\View\ViewRendererInterface;
use Psr\Http\Message\ResponseInterface;
final readonly class ArticleController
{
public function __construct(
private ViewRendererInterface $views,
private ArticleRepository $articles,
) {}
public function detail(string $id): ResponseInterface
{
return $this->views->render('articles.detail', [
'article' => $this->articles->get($id),
]);
}
}Šablona čte pole article předané controllerem a vypisuje title a body. Helper e() escapuje obě dynamické hodnoty; typ a existence článku jsou odpovědností aplikační repository a controlleru.
<?php
declare(strict_types=1);
/** @var array{id:string,title:string,body:string} $article */ ?>
<article>
<h1><?= e($article['title']) ?></h1>
<p><?= e($article['body']) ?></p>
</article>Formulář a CSRF
Routing.php registruje GET akci pro formulář a POST akci pro odeslání. Na POST routě CsrfMiddleware ověří token před ContactController::store(); token vloží view v dalším souboru. CSRF vyžaduje nakonfigurovanou session.
<?php
use App\Controllers\ContactController;
use Lemonade\Framework\Routing\ControllerAction;
use Lemonade\Framework\Security\Csrf\CsrfMiddleware;
$router->getNamed('contact.form', '/contact', ControllerAction::for(ContactController::class, 'form'));
$router->postNamed('contact.store', '/contact', ControllerAction::for(ContactController::class, 'store'))
->middleware(CsrfMiddleware::class);View odesílá data na pojmenovanou POST route contact.store. csrfField() vloží skryté pole s tokenem a e() escapuje URL i hodnotu emailu při vykreslení; email dodává akce form().
<form method="post" action="<?= e($this->url('contact.store')) ?>">
<?= $this->csrfField() ?>
<label for="email">E-mail</label>
<input id="email" name="email" value="<?= e($email) ?>">
<button type="submit">Send</button>
</form>Validace vstupu
ContactController zobrazuje formulář s prázdným emailem. Při POST ověří, že getParsedBody() vrátil pole, a předá ho FormValidation. Chyby vrátí přes Responses jako JSON 422; při úspěchu vrátí validated() jako JSON 200. Zprávu neodesílá ani neukládá.
<?php
declare(strict_types=1);
namespace App\Controllers;
use Lemonade\Framework\Http\Response\Responses;
use Lemonade\Framework\Validation\FormValidation;
use Lemonade\Framework\View\ViewRendererInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class ContactController
{
public function __construct(
private ViewRendererInterface $views,
private FormValidation $validator,
private Responses $responses,
) {}
public function form(): ResponseInterface
{
return $this->views->render('contact.form', ['email' => '']);
}
public function store(ServerRequestInterface $request): ResponseInterface
{
$body = $request->getParsedBody();
$data = is_array($body) ? $body : [];
$result = $this->validator->field('email', 'E-mail')
->required()->email()->maxLength(150)->validate($data);
if (!$result->isValid()) {
return $this->responses->json(['errors' => $result->errors()], 422);
}
return $this->responses->json(['data' => $result->validated()], 200);
}
}