Il componente Form di SismaFramework è uno strumento potente che semplifica la gestione dei form HTML. Si occupa di tre compiti principali:
$_POST) a un'entità.FormFilterError per gestire errori e ripopolamento automatico.
Gestire un form in SismaFramework segue tre passi principali. Vediamoli con un esempio pratico: la creazione e modifica di un articolo di un blog (Post).
Per prima cosa, crea una classe Form nella cartella Forms del tuo modulo. Questa classe definisce a quale entità è associato il form e quali sono le regole di validazione per ogni campo.
MyBlog/Application/Forms/PostForm.php
namespace MyBlog\Application\Forms;
use SismaFramework\Core\BaseClasses\BaseForm;
use SismaFramework\Core\Enumerations\FilterType;
use MyBlog\Application\Entities\Post;
class PostForm extends BaseForm
{
/**
* Specifica la classe dell'entità gestita da questo form.
*/
protected static function getEntityName(): string
{
return Post::class;
}
/**
* Definisce le regole di validazione per ogni campo del form.
*/
protected function setFilterFieldsMode(): void
{
$this->addFilterFieldMode('title', FilterType::string, ['minLength' => 3, 'maxLength' => 255]);
$this->addFilterFieldMode('content', FilterType::string, ['minLength' => 10]);
$this->addFilterFieldMode('publicationDate', FilterType::datetime, [], true); // Il campo può essere nullo
$this->addFilterFieldMode('isPublished', FilterType::boolean);
}
/**
* Usato per validazioni personalizzate più complesse.
* Deve ritornare true se la validazione ha successo, false altrimenti.
*/
protected function customFilter(): bool
{
// Esempio: se il titolo contiene una parola specifica, aggiungi un errore.
// if (str_contains($this->entity->getTitle(), 'spam')) {
// $this->formFilterErrorManager->addErrorMessage('title', 'Il titolo non può contenere la parola "spam".');
// return false;
// }
return true;
}
/**
* Usato per gestire form annidati (entità correlate).
* In questo esempio non è necessario.
*/
protected function setEntityFromForm(): void
{
}
/**
* Usato per iniettare dati nel form da fonti esterne (es. sessione).
* In questo esempio non è necessario.
*/
protected function injectRequest(): void
{
}
}
Nel controller, devi creare un'action per gestire la richiesta del form. Il flusso è sempre lo stesso:
Request al metodo handleRequest().isSubmitted()) e se è valido (isValid()).resolveEntity() e reindirizza l'utente.
MyBlog/Application/Controllers/PostController.php
namespace MyBlog\Application\Controllers;
use SismaFramework\Core\BaseClasses\BaseController;
use SismaFramework\Core\HttpClasses\Request;
use SismaFramework\Core\HttpClasses\Response;
use SismaFramework\Core\HelperClasses\Render;
use SismaFramework\Core\HelperClasses\Router;
use MyBlog\Application\Entities\Post;
use MyBlog\Application\Forms\PostForm;
class PostController extends BaseController
{
// L'action per creare un nuovo post
public function create(Request $request): Response
{
$form = new PostForm(); // Creiamo un form per una nuova entità
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// Grazie a injectRequest(), non dobbiamo più gestire manualmente l'ID dell'autore.
$nuovoPost = $form->resolveEntity();
$this->dataMapper->save($nuovoPost);
return $this->router->redirect('post/show/id/' . $nuovoPost->getId());
}
// Se il form non è valido o è la prima visita, mostriamo il form
$this->vars['pageTitle'] = 'Modifica Articolo';
// Passiamo l'entità per il ripopolamento e gli errori alla vista
$this->vars['formEntity'] = $form->isSubmitted() ? $form->getEntityDataToStandardEntity() : $post;
$this->vars['errors'] = $form->getFilterErrors();
return $this->render->generateView('post/form', $this->vars);
}
}
Infine, crea il file della vista. I nomi dei campi (name="...") nel form HTML devono corrispondere ai nomi delle proprietà dell'entità. La gestione degli errori è particolarmente elegante.
L'oggetto $errors (di tipo FormFilterError) restituito dal form utilizza i metodi magici di PHP. Questo significa che:
Error (es. $errors->titleError). Se l'errore esiste, restituirà il messaggio (una stringa, che valuta a true); altrimenti, restituirà false.CustomMessage (es. $errors->titleCustomMessage). Questo conterrà la stringa del messaggio e ha la priorità su quello standard.isset() o metodi come hasError(), rendendo il codice della vista molto più pulito e leggibile.it_IT.php) e richiamato nella vista.MyBlog/Application/Views/post/form.php
<?php require_once __DIR__ . '/../layout/header.php'; ?>
<h2><?= htmlspecialchars($pageTitle) ?></h2>
<form method="post">
<div class="form-group">
<label for="title">Titolo</label>
<input type="text" id="title" name="title" value="<?= htmlspecialchars($formEntity->getTitle() ?? '') ?>">
<?php // Controlla prima un messaggio personalizzato. Se non c'è, controlla se c'è un errore standard e mostra il messaggio dal file di lingua. ?>
<?php if ($errors->titleCustomMessage) : ?>
<div class="error"><?= $errors->titleCustomMessage ?></div>
<?php elseif ($errors->titleError) : ?>
<div class="error"><?= $defaulErrorMessage // Variabile dal file di lingua (es. 'it_IT.php') ?></div>
<?php endif; ?>
</div>
<div class="form-group">
<label for="content">Contenuto</label>
<textarea id="content" name="content"><?= htmlspecialchars($formEntity->getContent() ?? '') ?></textarea>
<?php if ($errors->contentCustomMessage) : ?>
<div class="error"><?= $errors->contentCustomMessage ?></div>
<?php elseif ($errors->contentError) : ?>
<div class="error"><?= $defaulErrorMessage // Variabile dal file di lingua ?></div>
<?php endif; ?>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="isPublished" value="1" <?= $formEntity->isPublished() ? 'checked' : '' ?>>
Pubblicato
</label>
</div>
<button type="submit">Salva</button>
</form>
<?php require_once __DIR__ . '/../layout/footer.php'; ?>
injectRequest() e addRequest()
Il metodo injectRequest() è un hook potente che viene eseguito dopo che il form ha ricevuto l'oggetto Request, ma prima che inizi il processo di validazione e mappatura dei dati sull'entità.
All'interno di questo metodo, puoi usare il metodo helper addRequest(string $propertyName, string|int|float|bool|array|null $value, bool $override = true) per aggiungere o sovrascrivere un singolo valore nella richiesta del form.
Il parametro $override (introdotto nella 11.8.0) controlla cosa succede se la proprietà è già presente nella richiesta:
override: true (default) → il valore passato sovrascrive sempre quello esistente.override: false → il valore viene impostato solo se la proprietà non è già presente nella richiesta; un valore già inviato dal form (es. tramite un campo <input>) non viene toccato.Questo approccio è estremamente utile per:
<input type="hidden">.override: false puoi fornire un default solo quando il form non ha già fornito un valore.Immaginiamo di voler associare automaticamente un post all'utente loggato, il cui ID è salvato in sessione.
// In MyBlog/Application/Forms/PostForm.php
protected function injectRequest(): void
{
// La sessione è accessibile tramite $this->session nel form.
// Se l'utente è loggato, aggiungiamo il suo ID alla richiesta
// sotto la chiave 'authorId'.
if ($this->session->has('user_id')) {
$this->addRequest('authorId', $this->session->get('user_id'));
}
}
$override: falseSe vuoi impostare un valore di default solo quando il form non lo ha già fornito (ad esempio per non sovrascrivere un campo opzionale inviato dall'utente):
protected function injectRequest(): void
{
// Imposta 'status' a 'draft' solo se il form non ha già inviato un valore
$this->addRequest('status', 'draft', override: false);
}
Request
La classe Request è un wrapper orientato agli oggetti per le variabili superglobali di PHP. Viene iniettata automaticamente nelle action dei controller quando la si dichiara come argomento.
Le sue proprietà pubbliche mappano le superglobali:
$request->query: Corrisponde a $_GET.$request->request: Corrisponde a $_POST.$request->files: Corrisponde a $_FILES.$request->cookies: Corrisponde a $_COOKIE.$request->server: Corrisponde a $_SERVER.Indice | Precedente: Viste e Template | Successivo: Internazionalizzazione (i18n)
Se hai trovato errori o vuoi suggerire miglioramenti, apri una issue su GitHub.
Report Issue Edit on GitHub