Formular pentru crearea și editarea înregistrărilor
Cum să implementăm corect adăugarea și editarea unei înregistrări în Nette, folosind același formular pentru ambele operațiuni?
În multe cazuri, formularele pentru adăugarea și editarea înregistrărilor sunt identice, diferind poate doar prin eticheta butonului. Vom prezenta exemple de presenteri simpli, unde vom folosi formularul mai întâi pentru adăugarea unei înregistrări, apoi pentru editare și, în final, vom combina ambele soluții.
Adăugarea unei înregistrări
Exemplu de presenter utilizat pentru adăugarea unei înregistrări. Vom lăsa lucrul efectiv cu baza de date în seama clasei
Facade
, al cărei cod nu este esențial pentru exemplu.
use Nette\Application\UI\Form;
class RecordPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Facade $facade,
) {
}
protected function createComponentRecordForm(): Form
{
$form = new Form;
// ... adăugăm câmpurile formularului ...
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // adăugarea înregistrării în baza de date
$this->flashMessage('Adăugat cu succes');
$this->redirect('...');
}
public function renderAdd(): void
{
// ...
}
}
Editarea unei înregistrări
Acum vom arăta cum ar arăta un presenter utilizat pentru editarea unei înregistrări:
use Nette\Application\UI\Form;
class RecordPresenter extends Nette\Application\UI\Presenter
{
private $record;
public function __construct(
private Facade $facade,
) {
}
public function actionEdit(int $id): void
{
$record = $this->facade->get($id);
if (
!$record // verificarea existenței înregistrării
|| !$this->facade->isEditAllowed(/*...*/) // verificarea permisiunilor
) {
$this->error(); // eroare 404
}
$this->record = $record;
}
protected function createComponentRecordForm(): Form
{
// verificăm dacă acțiunea este 'edit'
if ($this->getAction() !== 'edit') {
$this->error();
}
$form = new Form;
// ... adăugăm câmpurile formularului ...
$form->setDefaults($this->record); // setarea valorilor implicite
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->update($this->record->id, $data); // actualizarea înregistrării
$this->flashMessage('Actualizat cu succes');
$this->redirect('...');
}
}
În metoda action, care se execută chiar la începutul ciclului de viață al presenterului, verificăm existența înregistrării și permisiunea utilizatorului de a o edita.
Salvăm înregistrarea în proprietatea $record
, pentru a o avea disponibilă în metoda
createComponentRecordForm()
pentru setarea valorilor implicite și în recordFormSucceeded()
pentru ID.
O soluție alternativă ar fi setarea valorilor implicite direct în actionEdit()
și obținerea valorii ID-ului,
care face parte din URL, folosind getParameter('id')
:
public function actionEdit(int $id): void
{
$record = $this->facade->get($id);
if (
// verificarea existenței și controlul permisiunilor
) {
$this->error();
}
// setarea valorilor implicite ale formularului
$this->getComponent('recordForm')
->setDefaults($record);
}
public function recordFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data);
// ...
}
}
Cu toate acestea, și aceasta ar trebui să fie cea mai importantă concluzie a întregului cod, trebuie să ne
asigurăm la crearea formularului că acțiunea este într-adevăr edit
. Altfel, verificarea din metoda
actionEdit()
nu ar avea loc deloc!
Același formular pentru adăugare și editare
Și acum vom combina ambii presenteri într-unul singur. Fie am putea distinge în metoda
createComponentRecordForm()
despre ce acțiune este vorba și să configurăm formularul în consecință, fie putem
lăsa acest lucru direct pe seama metodelor action și să scăpăm de condiție:
class RecordPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Facade $facade,
) {
}
public function actionAdd(): void
{
$form = $this->getComponent('recordForm');
$form->onSuccess[] = [$this, 'addingFormSucceeded'];
}
public function actionEdit(int $id): void
{
$record = $this->facade->get($id);
if (
!$record // verificarea existenței înregistrării
|| !$this->facade->isEditAllowed(/*...*/) // verificarea permisiunilor
) {
$this->error(); // eroare 404
}
$form = $this->getComponent('recordForm');
$form->setDefaults($record); // setarea valorilor implicite
$form->onSuccess[] = [$this, 'editingFormSucceeded'];
}
protected function createComponentRecordForm(): Form
{
// verificăm dacă acțiunea este 'add' sau 'edit'
if (!in_array($this->getAction(), ['add', 'edit'])) {
$this->error();
}
$form = new Form;
// ... adăugăm câmpurile formularului ...
return $form;
}
public function addingFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // adăugarea înregistrării în baza de date
$this->flashMessage('Adăugat cu succes');
$this->redirect('...');
}
public function editingFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data); // actualizarea înregistrării
$this->flashMessage('Actualizat cu succes');
$this->redirect('...');
}
}