Formular pentru crearea și modificarea unei înregistrări
Cum se implementează în mod corespunzător adăugarea și editarea unei înregistrări în Nette, utilizând același formular pentru ambele?
În multe cazuri, formularele de adăugare și de editare a unei înregistrări sunt identice, diferind doar prin eticheta de pe buton. Vom prezenta exemple de prezentări simple în care folosim formularul mai întâi pentru a adăuga o înregistrare, apoi pentru a o edita și, în final, vom combina cele două soluții.
Adăugarea unei înregistrări
Un exemplu de prezentator utilizat pentru a adăuga o înregistrare. Vom lăsa activitatea efectivă a bazei de date pe seama
clasei Facade
, al cărei cod nu este relevant pentru acest 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ăugați câmpuri de formular ...
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // adăugarea unei înregistrări în baza de date
$this->flashMessage('Successfully added');
$this->redirect('...');
}
public function renderAdd(): void
{
// ...
}
}
Editarea unei înregistrări
Acum să vedem cum ar arăta un prezentator utilizat pentru a edita o înregistrare:
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 // să verifice existența înregistrării
|| !$this->facade->isEditAllowed(/*...*/) // verificarea permisiunilor
) {
$this->error(); // Eroare 404
}
$this->record = $record;
}
protected function createComponentRecordForm(): Form
{
// verificați dacă acțiunea este "edit" (editare)
if ($this->getAction() !== 'edit') {
$this->error();
}
$form = new Form;
// ... adăugați câmpuri de formular ...
$form->setDefaults($this->record); // setați valorile implicite
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->update($this->record->id, $data); // actualizează înregistrarea
$this->flashMessage('Successfully updated');
$this->redirect('...');
}
}
În metoda action, care este invocată chiar la începutul ciclului de viață al prezentatorului, se verifică existența înregistrării și permisiunea utilizatorului de a o edita.
Stocăm înregistrarea în proprietatea $record
, astfel încât să fie disponibilă în metoda
createComponentRecordForm()
pentru setarea valorilor implicite și recordFormSucceeded()
pentru ID.
O soluție alternativă ar fi să setați valorile implicite direct în actionEdit()
, iar valoarea ID, care face
parte din URL, este recuperată cu ajutorul getParameter('id')
:
public function actionEdit(int $id): void
{
$record = $this->facade->get($id);
if (
// verificarea existenței și verificarea permisiunilor
) {
$this->error();
}
// stabilirea valorilor implicite ale formularelor
$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 din tot acest cod, trebuie să ne
asigurăm că acțiunea este într-adevăr edit
atunci când creăm formularul. Pentru că, altfel, validarea din
metoda actionEdit()
nu ar avea loc deloc!
Același formular pentru adăugare și editare
Și acum vom combina ambii prezentatori într-unul singur. Fie putem distinge ce acțiune este implicată în metoda
createComponentRecordForm()
și configura formularul în consecință, fie putem lăsa direct pe seama metodelor de
acțiune ș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 // să verifice existența înregistrării
|| !$this->facade->isEditAllowed(/*...*/) // verificarea permisiunilor
) {
$this->error(); // Eroare 404
}
$form = $this->getComponent('recordForm');
$form->setDefaults($record); // setați valorile implicite
$form->onSuccess[] = [$this, 'editingFormSucceeded'];
}
protected function createComponentRecordForm(): Form
{
// verifică dacă acțiunea este "add" sau "edit".
if (!in_array($this->getAction(), ['add', 'edit'])) {
$this->error();
}
$form = new Form;
// ... adaugă câmpuri de formular ...
return $form;
}
public function addingFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // adăugarea unei înregistrări în baza de date
$this->flashMessage('Successfully added');
$this->redirect('...');
}
public function editingFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data); // actualizează înregistrarea
$this->flashMessage('Successfully updated');
$this->redirect('...');
}
}