Cum să folosiți corect legăturile POST

În aplicațiile web, în special în interfețele administrative, ar trebui să fie o regulă de bază ca acțiunile care modifică starea serverului să nu fie efectuate prin metoda HTTP GET. După cum sugerează și numele metodei, GET ar trebui să fie utilizată numai pentru a prelua date, nu pentru a le modifica. Pentru acțiuni precum ștergerea înregistrărilor, este mai indicat să se utilizeze metoda POST. Deși ideal ar fi să se folosească metoda DELETE, aceasta nu poate fi invocată fără JavaScript, de aceea se folosește în mod obișnuit metoda POST.

Cum se procedează în practică? Folosiți acest truc simplu. La începutul șablonului dumneavoastră, creați un formular ajutător cu identificatorul postForm, pe care îl veți folosi apoi pentru butoanele de ștergere:

<form method="post" id="postForm"></form>

Cu acest formular, puteți utiliza un <button> în loc de clasicul <a> care poate fi modificat vizual pentru a arăta ca un link obișnuit. De exemplu, cadrul CSS Bootstrap oferă clasele btn btn-link care permit ca butonul să nu se distingă vizual de alte linkuri. Folosind atributul form="postForm", îl legăm la formularul pregătit în prealabil:

<table>
	<tr n:foreach="$posts as $post">
		<td>{$post->title}</td>
		<td>
			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
			<!-- instead of <a n:href="delete $post->id">delete</a> -->
		</td>
	</tr>
</table>

Atunci când se face clic pe link, acțiunea delete este acum invocată. Pentru a vă asigura că cererile sunt acceptate numai prin metoda POST și din același domeniu (ceea ce reprezintă o apărare eficientă împotriva atacurilor CSRF), utilizați atributul #[Requires] attribute:

use Nette\Application\Attributes\Requires;

class AdminPresenter extends Nette\Application\UI\Presenter
{
	#[Requires(methods: 'POST', sameOrigin: true)]
	public function actionDelete(int $id): void
	{
		$this->facade->deletePost($id); // hypothetical code for deleting a record
		$this->redirect('default');
	}
}

Atributul este disponibil de la Nette Application 3.2 și puteți afla mai multe despre capacitățile sale pe pagina Cum se utilizează atributul #Requires.

Dacă foloseați semnalul handleDelete() în loc de acțiunea actionDelete(), nu este necesar să specificați sameOrigin: true, deoarece semnalele au această protecție setată implicit:

#[Requires(methods: 'POST')]
public function handleDelete(int $id): void
{
	$this->facade->deletePost($id);
	$this->redirect('this');
}

Această abordare nu numai că îmbunătățește securitatea aplicației dumneavoastră, dar contribuie, de asemenea, la respectarea standardelor și practicilor web adecvate. Prin utilizarea metodelor POST pentru acțiunile de schimbare a stării, obțineți o aplicație mai robustă și mai sigură.