Формуляр за създаване и редактиране на запис
Как правилно да въведем добавянето и редактирането на запис в Nette, като използваме една и съща форма и за двете?
В много случаи формулярите за добавяне и редактиране на запис са едни и същи, като се различават само по етикета на бутона. Ще покажем примери за прости презентатори, в които използваме формуляра първо за добавяне на запис, след това за редактирането му и накрая комбинираме двете решения.
Добавяне на запис
Пример за презентатор, използван за добавяне на запис. Обработката на
базата данни ще оставим на класа Facade
, чийто код не е от значение
за този пример.
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;
// ... добавляем поля форма ...
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // добавляем запис в базата данни
$this->flashMessage('Успешно добавено');
$this->redirect('...');
}
public function renderAdd(): void
{
// ...
}
}
Редактиране на запис
Сега нека видим как ще изглежда презентаторът, използван за редактиране на записи:
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 // проверка на съществуването на записа
|| !$this->facade->isEditAllowed(/*...*/) // проверка на правата за достъп
) {
$this->error(); // Грешка 404
}
$this->record = $record;
}
protected function createComponentRecordForm(): Form
{
// проверете дали е избрано действието "редактиране
if ($this->getAction() !== 'edit') {
$this->error();
}
$form = new Form;
// ... добавяне на полета за формуляри ...
$form->setDefaults($this->record); // задаване на настройки по подразбиране
$form->onSuccess[] = [$this, 'recordFormSucceeded'];
return $form;
}
public function recordFormSucceeded(Form $form, array $data): void
{
$this->facade->update($this->record->id, $data); // актуализиране на записа
$this->flashMessage('Успешно актуализирано');
$this->redirect('...');
}
}
В метода action, който се извиква в самото начало на жизнения цикъл на презентатора, се проверява съществуването на записа и разрешението на потребителя да го редактира.
Съхраняваме записа в свойството $record
, така че той да е достъпен
в метода createComponentRecordForm()
за задаване на стойности по
подразбиране и recordFormSucceeded()
за идентификатор. Алтернативно
решение би било да се зададат стойностите по подразбиране директно в
actionEdit()
и стойността на ID, която е част от URL адреса и се извлича с
getParameter('id')
:
public function actionEdit(int $id): void
{
$record = $this->facade->get($id);
if (
// проверка на съществуването и правата на достъп
) {
$this->error();
}
// задаване на стойности по подразбиране за полетата на формуляра
$this->getComponent('recordForm')
->setDefaults($record);
}
public function recordFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data);
// ...
}
}
Въпреки това, и това би трябвало да е най-важният извод от целия
код, трябва да се уверим, че действието наистина е edit
, когато
създаваме формата. Защото в противен случай валидирането в метода
actionEdit()
изобщо няма да се случи!
Една и съща форма за добавяне и редактиране
Сега ще обединим двамата водещи в един. Или можем да разграничим кое
действие е включено в метода createComponentRecordForm()
и да конфигурираме
формуляра по съответния начин, или можем да го оставим директно на
методите на действие и да се отървем от условието:
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 // проверка на съществуването на записа
|| !$this->facade->isEditAllowed(/*...*/) // проверка на правата за достъп
) {
$this->error(); // Грешка 404
}
$form = $this->getComponent('recordForm');
$form->setDefaults($record); // задаване на настройки по подразбиране
$form->onSuccess[] = [$this, 'editingFormSucceeded'];
}
protected function createComponentRecordForm(): Form
{
// проверява дали текущото действие е 'add' или 'edit'
if (!in_array($this->getAction(), ['add', 'edit'])) {
$this->error();
}
$form = new Form;
// ... добавяне на полета за формуляри ...
return $form;
}
public function addingFormSucceeded(Form $form, array $data): void
{
$this->facade->add($data); // добавете този запис в базата данни
$this->flashMessage('Successfully added');
$this->redirect('...');
}
public function editingFormSucceeded(Form $form, array $data): void
{
$id = (int) $this->getParameter('id');
$this->facade->update($id, $data); // актуализиране на записа
$this->flashMessage('Успешно актуализирано');
$this->redirect('...');
}
}