Φόρμα για τη δημιουργία και την επεξεργασία εγγραφών
Πώς να υλοποιήσετε σωστά την προσθήκη και την επεξεργασία εγγραφών στο Nette, χρησιμοποιώντας την ίδια φόρμα και για τις δύο λειτουργίες;
Σε πολλές περιπτώσεις, οι φόρμες για την προσθήκη και την επεξεργασία εγγραφών είναι ίδιες, διαφέροντας ίσως μόνο στην ετικέτα του κουμπιού. Θα δείξουμε παραδείγματα απλών presenters, όπου θα χρησιμοποιήσουμε τη φόρμα πρώτα για την προσθήκη εγγραφής, μετά για την επεξεργασία και τέλος θα συνδυάσουμε τις δύο λύσεις.
Προσθήκη εγγραφής
Παράδειγμα presenter που χρησιμεύει για την προσθήκη εγγραφής. Την
πραγματική εργασία με τη βάση δεδομένων θα την αφήσουμε στην κλάση
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('Successfully added');
$this->redirect('...');
}
public function renderAdd(): void
{
// ...
}
}
Επεξεργασία εγγραφής
Τώρα θα δείξουμε πώς θα έμοιαζε ο presenter που χρησιμεύει για την επεξεργασία εγγραφής:
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
{
// ελέγχουμε ότι η action είναι 'edit'
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('Successfully updated');
$this->redirect('...');
}
}
Στη μέθοδο action, η οποία εκτελείται αμέσως στην αρχή του κύκλου ζωής του presenter, ελέγχουμε την ύπαρξη της εγγραφής και τα δικαιώματα του χρήστη να την επεξεργαστεί.
Αποθηκεύουμε την εγγραφή στην ιδιότητα $record
, ώστε να την
έχουμε διαθέσιμη στη μέθοδο createComponentRecordForm()
για τον ορισμό των
προεπιλεγμένων τιμών, και στη recordFormSucceeded()
για το ID. Μια
εναλλακτική λύση θα ήταν να ορίσουμε τις προεπιλεγμένες τιμές
απευθείας στην 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);
// ...
}
}
Ωστόσο, και αυτό θα έπρεπε να είναι το πιο σημαντικό συμπέρασμα όλου
του κώδικα, πρέπει κατά τη δημιουργία της φόρμας να βεβαιωθούμε ότι η
action είναι όντως edit
. Διότι διαφορετικά, ο έλεγχος στη μέθοδο
actionEdit()
δεν θα είχε πραγματοποιηθεί καθόλου!
Ίδια φόρμα για προσθήκη και επεξεργασία
Και τώρα συνδυάζουμε τους δύο presenters σε έναν. Είτε θα μπορούσαμε στη
μέθοδο createComponentRecordForm()
να διακρίνουμε ποια action είναι και ανάλογα
να διαμορφώσουμε τη φόρμα, είτε μπορούμε να το αφήσουμε απευθείας στις
action-μεθόδους και να απαλλαγούμε από τη συνθήκη:
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
{
// ελέγχουμε ότι η action είναι '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('Successfully updated');
$this->redirect('...');
}
}