Nette Documentation Preview

syntax
Jak správně používat POST odkazy
********************************

.[perex]
Ve webových aplikacích, zejména v administrativních rozhraních, by mělo být základním pravidlem, že akce měnící stav serveru by neměly být prováděny prostřednictvím HTTP metody GET. Jak název metody napovídá, GET by měl sloužit pouze k získání dat, nikoli k jejich změně. Pro akce jako třeba mazání záznamů je vhodnější použít metodu POST. Ideální by sice byla metoda DELETE, ale tu nelze bez JavaScriptu vyvolat, proto se historicky používá POST.

Jak na to v praxi? Využijte tento jednoduchý trik. Na začátku šablony si vytvoříte pomocný formulář s identifikátorem `postForm`, který následně použijete pro mazací tlačítka:

```latte .{file:@layout.latte}
<form method="post" id="postForm"></form>
```

Díky tomuto formuláři můžete místo klasického odkazu `<a>` použít tlačítko `<button>`, které lze vizuálně upravit tak, aby vypadalo jako běžný odkaz. Například CSS framework Bootstrap nabízí třídy `btn btn-link`, se kterými dosáhnete toho, že tlačítko nebude vizuálně odlišné od ostatních odkazů. Pomocí atributu `form="postForm"` ho provážeme s předpřipraveným formulářem:

```latte .{file:admin.latte}
<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>
```

Při kliknutí na odkaz se nyní vyvolá akce `delete`. Pro zajištění, že požadavky budou přijímány pouze prostřednictvím metody POST a z téže domény (což je účinná obrana proti CSRF útokům), použijte atribut `#[Requires]`:

```php .{file:AdminPresenter.php}
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); // hypotetický kód mazající záznam
		$this->redirect('default');
	}
}
```

Atribut existuje od Nette Application 3.2 a více o jeho možnostech se dozvíte na stránce [Jak používat atribut #Requires |attribute-requires].

Pokud byste místo akce `actionDelete()` používali signál `handleDelete()`, není nutné uvádět `sameOrigin: true`, protože signály mají tuto ochranu nastavenou implicitně:

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

Tento přístup nejenže zlepšuje bezpečnost vaší aplikace, ale také přispívá k dodržování správných webových standardů a praxe. Využitím metod POST pro akce měnící stav dosáhnete robustnější a bezpečnější aplikace.

Jak správně používat POST odkazy

Ve webových aplikacích, zejména v administrativních rozhraních, by mělo být základním pravidlem, že akce měnící stav serveru by neměly být prováděny prostřednictvím HTTP metody GET. Jak název metody napovídá, GET by měl sloužit pouze k získání dat, nikoli k jejich změně. Pro akce jako třeba mazání záznamů je vhodnější použít metodu POST. Ideální by sice byla metoda DELETE, ale tu nelze bez JavaScriptu vyvolat, proto se historicky používá POST.

Jak na to v praxi? Využijte tento jednoduchý trik. Na začátku šablony si vytvoříte pomocný formulář s identifikátorem postForm, který následně použijete pro mazací tlačítka:

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

Díky tomuto formuláři můžete místo klasického odkazu <a> použít tlačítko <button>, které lze vizuálně upravit tak, aby vypadalo jako běžný odkaz. Například CSS framework Bootstrap nabízí třídy btn btn-link, se kterými dosáhnete toho, že tlačítko nebude vizuálně odlišné od ostatních odkazů. Pomocí atributu form="postForm" ho provážeme s předpřipraveným formulářem:

<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>

Při kliknutí na odkaz se nyní vyvolá akce delete. Pro zajištění, že požadavky budou přijímány pouze prostřednictvím metody POST a z téže domény (což je účinná obrana proti CSRF útokům), použijte atribut #[Requires]:

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); // hypotetický kód mazající záznam
		$this->redirect('default');
	}
}

Atribut existuje od Nette Application 3.2 a více o jeho možnostech se dozvíte na stránce Jak používat atribut #Requires.

Pokud byste místo akce actionDelete() používali signál handleDelete(), není nutné uvádět sameOrigin: true, protože signály mají tuto ochranu nastavenou implicitně:

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

Tento přístup nejenže zlepšuje bezpečnost vaší aplikace, ale také přispívá k dodržování správných webových standardů a praxe. Využitím metod POST pro akce měnící stav dosáhnete robustnější a bezpečnější aplikace.