Obrazec za ustvarjanje in urejanje zapisa
Kako pravilno izvajati dodajanje in urejanje zapisa v Nette, pri čemer se za oboje uporablja isti obrazec?
V številnih primerih sta obrazca za dodajanje in urejanje zapisa enaka, razlikujeta se le po oznaki na gumbu. Prikazali bomo primere preprostih predstavnikov, kjer najprej uporabimo obrazec za dodajanje zapisa, nato za njegovo urejanje in na koncu obe rešitvi združimo.
Dodajanje zapisa
Primer predstavnika, ki se uporablja za dodajanje zapisa. Dejansko delo s podatkovno bazo bomo prepustili razredu
Facade
, katerega koda za primer ni pomembna.
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;
// ... dodajanje polj obrazca ...
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // dodajanje zapisa v zbirko podatkov
$this->flashMessage('Successfully added');
$this->redirect('...');
}
public function renderAdd(): void
{
// ...
}
}
Urejanje zapisa
Zdaj si oglejmo, kako je videti predstavitev, ki se uporablja za urejanje zapisov:
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 // preverjanje obstoja zapisa.
|| !$this->facade->isEditAllowed(/*...*/) // preverjanje dovoljenj.
) {
$this->error(); // Napaka 404
}
$this->record = $record;
}
protected function createComponentRecordForm(): Form
{
// preverite, ali je dejanje "uredi".
if ($this->getAction() !== 'edit') {
$this->error();
}
$form = new Form;
// ... dodajte polja obrazca ...
$form->setDefaults($this->record); // nastavite privzete vrednosti
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->update($this->record->id, $data); // posodobi zapis
$this->flashMessage('Successfully updated');
$this->redirect('...');
}
}
V metodi action, ki se sproži na začetku življenjskega cikla predstavnika, preverimo obstoj zapisa in uporabnikovo dovoljenje za njegovo urejanje.
Zapis shranimo v lastnost $record
, tako da je na voljo v metodi createComponentRecordForm()
za
nastavitev privzetih vrednosti in recordFormSucceeded()
za ID. Alternativna rešitev bi bila, da bi privzete
vrednosti nastavili neposredno v metodi actionEdit()
, vrednost ID, ki je del naslova URL, pa bi pridobili z uporabo
metode getParameter('id')
:
public function actionEdit(int $id): void
{
$record = $this->facade->get($id);
if (
// preverjanje obstoja in preverjanje dovoljenj
) {
$this->error();
}
// nastaviti privzete vrednosti obrazca.
$this->getComponent('recordForm')
->setDefaults($record);
}
public function recordFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data);
// ...
}
}
Vendar, in to bi morala biti najpomembnejša ugotovitev iz celotne kode, moramo pri ustvarjanju obrazca zagotoviti, da
je dejanje res edit
. Kajti v nasprotnem primeru se preverjanje v metodi actionEdit()
sploh ne bi
zgodilo!
Isti obrazec za dodajanje in urejanje
Zdaj bomo oba predstavnika združili v enega. Lahko razlikujemo, katero dejanje je vključeno v metodo
createComponentRecordForm()
, in ustrezno konfiguriramo obrazec ali pa to prepustimo neposredno metodam dejanj in se
znebimo pogoja:
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 // preverjanje obstoja zapisa.
|| !$this->facade->isEditAllowed(/*...*/) // preverjanje dovoljenj.
) {
$this->error(); // Napaka 404
}
$form = $this->getComponent('recordForm');
$form->setDefaults($record); // nastavite privzete nastavitve
$form->onSuccess[] = [$this, 'editingFormSucceeded'];
}
protected function createComponentRecordForm(): Form
{
// preveri, ali je dejanje "dodaj" ali "uredi".
if (!in_array($this->getAction(), ['add', 'edit'])) {
$this->error();
}
$form = new Form;
// ... dodajte polja obrazca ...
return $form;
}
public function addingFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // dodajanje zapisa v zbirko podatkov
$this->flashMessage('Successfully added');
$this->redirect('...');
}
public function editingFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data); // posodobitev zapisa
$this->flashMessage('Successfully updated');
$this->redirect('...');
}
}