Comment bien utiliser les liens POST
Dans les applications web, en particulier dans les interfaces d'administration, une règle fondamentale devrait être que les actions modifiant l'état du serveur ne sont pas effectuées par la méthode HTTP GET. Comme son nom l'indique, GET ne devrait servir qu'à récupérer des données, pas à les modifier. Pour des actions comme la suppression d'enregistrements, la méthode POST est plus appropriée. La méthode DELETE serait idéale, mais elle ne peut pas être invoquée sans JavaScript, c'est pourquoi POST est historiquement utilisée pour ce genre d'actions.
Comment mettre cela en pratique ? Utilisez cette astuce toute simple. Au début de votre template de layout, créez un
formulaire auxiliaire portant l'ID postForm. Vous utiliserez ensuite ce formulaire pour des actions comme les boutons
de suppression :
<form method="post" id="postForm"></form>
Grâce à ce formulaire, au lieu d'un lien <a> classique, vous pouvez utiliser un
<button>. Ce bouton peut être stylé pour ressembler à un lien ordinaire. Le framework CSS Bootstrap propose
par exemple les classes btn btn-link, qui rendent le bouton visuellement indiscernable des autres liens. À l'aide de
l'attribut form="postForm", reliez le bouton au formulaire auxiliaire préparé :
<table>
<tr n:foreach="$posts as $post">
<td>{$post->title}</td>
<td>
<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">supprimer</button>
<!-- au lieu de <a n:href="delete $post->id">supprimer</a> -->
</td>
</tr>
</table>
Un clic sur ce bouton invoque désormais l'action delete. Pour que les requêtes ne soient acceptées que par la
méthode POST et qu'elles proviennent du même domaine (une défense efficace contre les attaques CSRF), utilisez l'attribut
#[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); // code hypothétique de suppression d'un enregistrement
$this->redirect('default');
}
}
Cet attribut est disponible depuis Nette Application 3.2. Vous en apprendrez davantage sur ses possibilités sur la page Comment utiliser l'attribut #Requires.
Si vous utilisiez le signal handleDelete() au lieu de l'action actionDelete(), indiquer
sameOrigin: true est inutile, car les signaux ont cette protection activée par défaut :
#[Requires(methods: 'POST')]
public function handleDelete(int $id): void
{
$this->facade->deletePost($id);
$this->redirect('this');
}
Cette approche renforce non seulement la sécurité de votre application, mais encourage aussi le respect des standards et des bonnes pratiques du web. Utiliser la méthode POST pour les actions qui changent l'état donne une application plus robuste et plus sûre.