Nette Documentation Preview

syntax
Δημιουργία και επεξεργασία αναρτήσεων
*************************************

Τι ωραία στιγμή! Έχουμε ένα σούπερ γαμάτο νέο blog, οι άνθρωποι διαφωνούν στα σχόλια και έχουμε επιτέλους λίγο χρόνο για περισσότερο προγραμματισμό. Αν και μας αρέσει το Adminer, δεν είναι τόσο άνετο να γράφουμε αναρτήσεις στο blog σε αυτό. Ίσως είναι η κατάλληλη στιγμή να προσθέσουμε μια απλή φόρμα για την προσθήκη νέων αναρτήσεων απευθείας από την εφαρμογή μας. Ας το κάνουμε.

Ας ξεκινήσουμε με το σχεδιασμό του UI:

1. Στην αρχική σελίδα, ας προσθέσουμε έναν σύνδεσμο "Γράψτε νέα δημοσίευση".
2. Θα εμφανίζεται μια φόρμα με τίτλο και textarea για το περιεχόμενο.
3. Όταν κάνετε κλικ σε ένα κουμπί Αποθήκευση, θα αποθηκεύσει την ανάρτηση του ιστολογίου.

Αργότερα θα προσθέσουμε επίσης έλεγχο ταυτότητας και θα επιτρέπουμε μόνο στους συνδεδεμένους χρήστες να προσθέτουν νέες αναρτήσεις. Αλλά ας το κάνουμε αυτό αργότερα. Τι κώδικα θα πρέπει να γράψουμε για να το κάνουμε να λειτουργήσει;

1. Δημιουργήστε έναν νέο παρουσιαστή με μια φόρμα για την προσθήκη αναρτήσεων.
2. Ορίστε ένα callback που θα ενεργοποιείται μετά την επιτυχή υποβολή της φόρμας και που θα αποθηκεύει τη νέα ανάρτηση στη βάση δεδομένων.
3. Δημιουργήστε ένα νέο πρότυπο για τη φόρμα.
4. Προσθέστε έναν σύνδεσμο προς τη φόρμα στο πρότυπο της κύριας σελίδας.


Νέος παρουσιαστής .[#toc-new-presenter]
=======================================

Ονομάστε τον νέο παρουσιαστή `EditPresenter` και αποθηκεύστε τον στο `app/UI/Edit/`. Πρέπει επίσης να συνδεθεί με τη βάση δεδομένων, οπότε και εδώ γράφουμε έναν κατασκευαστή που θα απαιτεί σύνδεση με τη βάση δεδομένων:

```php .{file:app/UI/Edit/EditPresenter.php}
<?php
namespace App\UI\Edit;

use Nette;
use Nette\Application\UI\Form;

final class EditPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}
}
```


Φόρμα για την αποθήκευση δημοσιεύσεων .[#toc-form-for-saving-posts]
===================================================================

Οι φόρμες και τα στοιχεία έχουν ήδη καλυφθεί όταν προσθέταμε υποστήριξη για σχόλια. Αν έχετε μπερδευτεί με το θέμα, πηγαίνετε να δείτε ξανά [πώς λειτουργούν οι φόρμες και τα συστατικά |comments#form-for-commenting], εμείς θα περιμένουμε εδώ ;)

Τώρα προσθέστε αυτή τη μέθοδο στο `EditPresenter`:

```php .{file:app/UI/Edit/EditPresenter.php}
protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Title:')
		->setRequired();
	$form->addTextArea('content', 'Content:')
		->setRequired();

	$form->addSubmit('send', 'Save and publish');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}
```


Αποθήκευση νέας δημοσίευσης από φόρμα .[#toc-saving-new-post-from-form]
=======================================================================

Συνεχίστε με την προσθήκη μιας μεθόδου χειρισμού.

```php .{file:app/UI/Edit/EditPresenter.php}
private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Μια γρήγορη εξήγηση: παίρνει τις τιμές από τη φόρμα, τις εισάγει στη βάση δεδομένων, δημιουργεί ένα μήνυμα για τον χρήστη ότι η δημοσίευση αποθηκεύτηκε με επιτυχία και ανακατευθύνει στη σελίδα όπου δημοσιεύεται η συγκεκριμένη δημοσίευση, ώστε να μπορείτε να δείτε πώς είναι.


Σελίδα για τη δημιουργία μιας νέας δημοσίευσης .[#toc-page-for-creating-a-new-post]
===================================================================================

Ας δημιουργήσουμε απλά το πρότυπο `Edit/create.latte`:

```latte .{file:app/UI/Edit/create.latte}
{block content}
<h1>New post</h1>

{control postForm}
```

Όλα θα πρέπει να είναι ξεκάθαρα τώρα. Η τελευταία γραμμή δείχνει τη φόρμα που πρόκειται να δημιουργήσουμε.

Θα μπορούσαμε επίσης να δημιουργήσουμε μια αντίστοιχη μέθοδο `renderCreate`, αλλά δεν είναι απαραίτητο. Δεν χρειάζεται να πάρουμε δεδομένα από τη βάση δεδομένων και να τα περάσουμε στο πρότυπο, οπότε η μέθοδος αυτή θα είναι κενή. Σε τέτοιες περιπτώσεις, η μέθοδος μπορεί να μην υπάρχει καθόλου.


Σύνδεσμος για τη δημιουργία αναρτήσεων .[#toc-link-for-creating-posts]
======================================================================

Πιθανώς γνωρίζετε ήδη πώς να προσθέσετε έναν σύνδεσμο στο `EditPresenter` και την ενέργεια `create`. Δοκιμάστε το.

Απλά προσθέστε στο αρχείο `app/UI/Home/default.latte`:

```latte
<a n:href="Edit:create">Write new post</a>
```


Επεξεργασία αναρτήσεων .[#toc-editing-posts]
============================================

Ας προσθέσουμε επίσης τη δυνατότητα επεξεργασίας υφιστάμενων αναρτήσεων. Θα είναι πολύ απλό - έχουμε ήδη το `postForm` και μπορούμε να το χρησιμοποιήσουμε και για την επεξεργασία.

Θα προσθέσουμε μια νέα σελίδα `edit` στο `EditPresenter`:

```php .{file:app/UI/Edit/EditPresenter.php}
public function renderEdit(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);

	if (!$post) {
		$this->error('Post not found');
	}

	$this->getComponent('postForm')
		->setDefaults($post->toArray());
}
```

Και θα δημιουργήσουμε το πρότυπο `Edit/edit.latte`:

```latte .{file:app/UI/Edit/edit.latte}
{block content}
<h1>Edit post</h1>

{control postForm}
```

Και ενημερώστε τη μέθοδο `postFormSucceeded`, η οποία θα μπορεί είτε να προσθέτει μια νέα ανάρτηση (όπως κάνει τώρα), είτε να επεξεργάζεται τις υπάρχουσες:

```php .{file:app/UI/Edit/EditPresenter.php}
private function postFormSucceeded(array $data): void
{
	$id = $this->getParameter('id');

	if ($id) {
		$post = $this->database
			->table('posts')
			->get($id);
		$post->update($data);

	} else {
		$post = $this->database
			->table('posts')
			->insert($data);
	}

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Όταν παρέχεται η παράμετρος `id`, σημαίνει ότι γίνεται επεξεργασία μιας ανάρτησης. Σε μια τέτοια περίπτωση, θα ελέγξουμε ότι η ανάρτηση υπάρχει πραγματικά και αν ναι, θα την ενημερώσουμε στη βάση δεδομένων. Εάν δεν παρέχεται η παράμετρος `id`, σημαίνει ότι θα προστεθεί μια νέα ανάρτηση.

Αλλά από πού προέρχεται το `id`; Είναι η παράμετρος που δίνεται στη μέθοδο `renderEdit`.

Μπορείτε τώρα να προσθέσετε έναν σύνδεσμο στο πρότυπο `app/UI/Post/show.latte`:

```latte
<a n:href="Edit:edit $post->id">Edit this post</a>
```


Περίληψη .[#toc-summary]
========================

Το ιστολόγιο λειτουργεί, ο κόσμος σχολιάζει γρήγορα και δεν βασιζόμαστε πλέον στον Adminer για την προσθήκη νέων αναρτήσεων. Είναι πλήρως ανεξάρτητο και ακόμη και κανονικοί άνθρωποι μπορούν να δημοσιεύουν εκεί. Αλλά περιμένετε, αυτό μάλλον δεν είναι εντάξει, ότι ο οποιοσδήποτε, εννοώ πραγματικά ο οποιοσδήποτε στο Διαδίκτυο, μπορεί να δημοσιεύσει στο ιστολόγιό μας. Απαιτείται κάποια μορφή ελέγχου ταυτότητας, ώστε μόνο οι συνδεδεμένοι χρήστες να μπορούν να δημοσιεύουν. Αυτό θα το προσθέσουμε στο επόμενο κεφάλαιο.

{{priority: -1}}
{{sitename: Nette Quickstart}}

Δημιουργία και επεξεργασία αναρτήσεων

Τι ωραία στιγμή! Έχουμε ένα σούπερ γαμάτο νέο blog, οι άνθρωποι διαφωνούν στα σχόλια και έχουμε επιτέλους λίγο χρόνο για περισσότερο προγραμματισμό. Αν και μας αρέσει το Adminer, δεν είναι τόσο άνετο να γράφουμε αναρτήσεις στο blog σε αυτό. Ίσως είναι η κατάλληλη στιγμή να προσθέσουμε μια απλή φόρμα για την προσθήκη νέων αναρτήσεων απευθείας από την εφαρμογή μας. Ας το κάνουμε.

Ας ξεκινήσουμε με το σχεδιασμό του UI:

  1. Στην αρχική σελίδα, ας προσθέσουμε έναν σύνδεσμο „Γράψτε νέα δημοσίευση“.
  2. Θα εμφανίζεται μια φόρμα με τίτλο και textarea για το περιεχόμενο.
  3. Όταν κάνετε κλικ σε ένα κουμπί Αποθήκευση, θα αποθηκεύσει την ανάρτηση του ιστολογίου.

Αργότερα θα προσθέσουμε επίσης έλεγχο ταυτότητας και θα επιτρέπουμε μόνο στους συνδεδεμένους χρήστες να προσθέτουν νέες αναρτήσεις. Αλλά ας το κάνουμε αυτό αργότερα. Τι κώδικα θα πρέπει να γράψουμε για να το κάνουμε να λειτουργήσει;

  1. Δημιουργήστε έναν νέο παρουσιαστή με μια φόρμα για την προσθήκη αναρτήσεων.
  2. Ορίστε ένα callback που θα ενεργοποιείται μετά την επιτυχή υποβολή της φόρμας και που θα αποθηκεύει τη νέα ανάρτηση στη βάση δεδομένων.
  3. Δημιουργήστε ένα νέο πρότυπο για τη φόρμα.
  4. Προσθέστε έναν σύνδεσμο προς τη φόρμα στο πρότυπο της κύριας σελίδας.

Νέος παρουσιαστής

Ονομάστε τον νέο παρουσιαστή EditPresenter και αποθηκεύστε τον στο app/UI/Edit/. Πρέπει επίσης να συνδεθεί με τη βάση δεδομένων, οπότε και εδώ γράφουμε έναν κατασκευαστή που θα απαιτεί σύνδεση με τη βάση δεδομένων:

<?php
namespace App\UI\Edit;

use Nette;
use Nette\Application\UI\Form;

final class EditPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}
}

Φόρμα για την αποθήκευση δημοσιεύσεων

Οι φόρμες και τα στοιχεία έχουν ήδη καλυφθεί όταν προσθέταμε υποστήριξη για σχόλια. Αν έχετε μπερδευτεί με το θέμα, πηγαίνετε να δείτε ξανά πώς λειτουργούν οι φόρμες και τα συστατικά, εμείς θα περιμένουμε εδώ ;)

Τώρα προσθέστε αυτή τη μέθοδο στο EditPresenter:

protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Title:')
		->setRequired();
	$form->addTextArea('content', 'Content:')
		->setRequired();

	$form->addSubmit('send', 'Save and publish');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

Αποθήκευση νέας δημοσίευσης από φόρμα

Συνεχίστε με την προσθήκη μιας μεθόδου χειρισμού.

private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}

Μια γρήγορη εξήγηση: παίρνει τις τιμές από τη φόρμα, τις εισάγει στη βάση δεδομένων, δημιουργεί ένα μήνυμα για τον χρήστη ότι η δημοσίευση αποθηκεύτηκε με επιτυχία και ανακατευθύνει στη σελίδα όπου δημοσιεύεται η συγκεκριμένη δημοσίευση, ώστε να μπορείτε να δείτε πώς είναι.

Σελίδα για τη δημιουργία μιας νέας δημοσίευσης

Ας δημιουργήσουμε απλά το πρότυπο Edit/create.latte:

{block content}
<h1>New post</h1>

{control postForm}

Όλα θα πρέπει να είναι ξεκάθαρα τώρα. Η τελευταία γραμμή δείχνει τη φόρμα που πρόκειται να δημιουργήσουμε.

Θα μπορούσαμε επίσης να δημιουργήσουμε μια αντίστοιχη μέθοδο renderCreate, αλλά δεν είναι απαραίτητο. Δεν χρειάζεται να πάρουμε δεδομένα από τη βάση δεδομένων και να τα περάσουμε στο πρότυπο, οπότε η μέθοδος αυτή θα είναι κενή. Σε τέτοιες περιπτώσεις, η μέθοδος μπορεί να μην υπάρχει καθόλου.

Πιθανώς γνωρίζετε ήδη πώς να προσθέσετε έναν σύνδεσμο στο EditPresenter και την ενέργεια create. Δοκιμάστε το.

Απλά προσθέστε στο αρχείο app/UI/Home/default.latte:

<a n:href="Edit:create">Write new post</a>

Επεξεργασία αναρτήσεων

Ας προσθέσουμε επίσης τη δυνατότητα επεξεργασίας υφιστάμενων αναρτήσεων. Θα είναι πολύ απλό – έχουμε ήδη το postForm και μπορούμε να το χρησιμοποιήσουμε και για την επεξεργασία.

Θα προσθέσουμε μια νέα σελίδα edit στο EditPresenter:

public function renderEdit(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);

	if (!$post) {
		$this->error('Post not found');
	}

	$this->getComponent('postForm')
		->setDefaults($post->toArray());
}

Και θα δημιουργήσουμε το πρότυπο Edit/edit.latte:

{block content}
<h1>Edit post</h1>

{control postForm}

Και ενημερώστε τη μέθοδο postFormSucceeded, η οποία θα μπορεί είτε να προσθέτει μια νέα ανάρτηση (όπως κάνει τώρα), είτε να επεξεργάζεται τις υπάρχουσες:

private function postFormSucceeded(array $data): void
{
	$id = $this->getParameter('id');

	if ($id) {
		$post = $this->database
			->table('posts')
			->get($id);
		$post->update($data);

	} else {
		$post = $this->database
			->table('posts')
			->insert($data);
	}

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}

Όταν παρέχεται η παράμετρος id, σημαίνει ότι γίνεται επεξεργασία μιας ανάρτησης. Σε μια τέτοια περίπτωση, θα ελέγξουμε ότι η ανάρτηση υπάρχει πραγματικά και αν ναι, θα την ενημερώσουμε στη βάση δεδομένων. Εάν δεν παρέχεται η παράμετρος id, σημαίνει ότι θα προστεθεί μια νέα ανάρτηση.

Αλλά από πού προέρχεται το id; Είναι η παράμετρος που δίνεται στη μέθοδο renderEdit.

Μπορείτε τώρα να προσθέσετε έναν σύνδεσμο στο πρότυπο app/UI/Post/show.latte:

<a n:href="Edit:edit $post->id">Edit this post</a>

Περίληψη

Το ιστολόγιο λειτουργεί, ο κόσμος σχολιάζει γρήγορα και δεν βασιζόμαστε πλέον στον Adminer για την προσθήκη νέων αναρτήσεων. Είναι πλήρως ανεξάρτητο και ακόμη και κανονικοί άνθρωποι μπορούν να δημοσιεύουν εκεί. Αλλά περιμένετε, αυτό μάλλον δεν είναι εντάξει, ότι ο οποιοσδήποτε, εννοώ πραγματικά ο οποιοσδήποτε στο Διαδίκτυο, μπορεί να δημοσιεύσει στο ιστολόγιό μας. Απαιτείται κάποια μορφή ελέγχου ταυτότητας, ώστε μόνο οι συνδεδεμένοι χρήστες να μπορούν να δημοσιεύουν. Αυτό θα το προσθέσουμε στο επόμενο κεφάλαιο.