Presenters
Nous allons découvrir comment écrire des presenters et des templates en Nette. Après lecture, vous saurez :
- comment fonctionne un presenter
- ce que sont les paramètres persistants
- comment les templates sont rendus
Nous savons déjà qu'un presenter est une classe qui représente une page web spécifique d'une application, par ex. la page d'accueil ; un produit dans une boutique en ligne ; un formulaire de connexion ; un flux sitemap, etc. Une application peut avoir d'un à des milliers de presenters. Dans d'autres frameworks, on les appelle aussi controllers.
Habituellement, par le terme presenter, on entend un descendant de la classe Nette\Application\UI\Presenter, qui est adapté à la génération d'interfaces web et auquel nous nous consacrerons dans le reste de ce chapitre. Au sens général, un presenter est n'importe quel objet implémentant l'interface Nette\Application\IPresenter.
Cycle de vie du presenter
La tâche du presenter est de traiter une requête et de retourner une réponse (qui peut être une page HTML, une image, une redirection, etc.).
Donc, au début, une requête lui est transmise. Ce n'est pas directement une requête HTTP, mais un objet Nette\Application\Request, dans lequel la requête HTTP a été transformée à l'aide du routeur. Nous n'interagissons généralement pas directement avec cet objet, car le presenter délègue intelligemment le traitement de la requête à d'autres méthodes, que nous allons présenter maintenant.
L'image représente la liste des méthodes qui sont appelées successivement de haut en bas, si elles existent. Aucune d'elles n'est obligatoire, nous pouvons avoir un presenter complètement vide sans une seule méthode et construire un site web statique simple dessus.
__construct()
Le constructeur n'appartient pas tout à fait au cycle de vie du presenter, car il est appelé au moment de la création de l'objet. Mais nous le mentionnons en raison de son importance. Le constructeur (avec la méthode inject) sert à passer les dépendances.
Un presenter ne devrait pas gérer la logique métier de l'application, écrire et lire dans la base de données, effectuer des
calculs, etc. C'est le rôle des classes de la couche que nous appelons modèle. Par exemple, la classe
ArticleRepository peut être responsable du chargement et de la sauvegarde des articles. Pour que le presenter puisse
travailler avec elle, il la reçoit via l'injection
de dépendances :
class ArticlePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private ArticleRepository $articles,
) {
}
}
startup()
Immédiatement après réception de la requête, la méthode startup() est appelée. Vous pouvez l'utiliser pour
initialiser les propriétés, vérifier les permissions utilisateur, etc. Il est requis que la méthode appelle toujours le parent
parent::startup().
action<Action>(args...)
Analogue à la méthode render<View>(). Alors que render<View>() est destinée à
préparer les données pour un template spécifique qui sera ensuite rendu, action<Action>() traite la requête
sans lien avec le rendu du template. Par exemple, elle traite les données, connecte ou déconnecte l'utilisateur, etc., puis redirige ailleurs.
Il est important que action<Action>() soit appelée avant render<View>(). Cela
nous permet de modifier le cours de la requête dans la méthode d'action, par exemple en changeant le template qui sera rendu,
voire la méthode render<View>() qui sera appelée, à l'aide de setView('otherView').
Vous pouvez même basculer vers une action entièrement différente avec la méthode
switch('otherAction'). Elle interrompt la méthode courante et exécute à la place les méthodes
action<Action>() et render<View>() de la nouvelle action (et désactive la canonisation automatique). La requête elle-même se poursuit ; seule la méthode en cours
d'exécution est interrompue.
Les paramètres de la requête sont passés à la méthode. Il est possible et recommandé de préciser leurs types, par ex.
actionShow(int $id, ?string $slug = null). Si le paramètre id est absent ou n'est pas un entier, le
presenter retourne une erreur 404 et termine son activité.
handle<Signal>(args...)
La méthode traite les signaux, que nous découvrirons dans le chapitre consacré aux composants. Elle est en effet principalement destinée aux composants et au traitement des requêtes AJAX.
Les paramètres de la requête sont passés à la méthode, comme dans le cas de action<Action>(), y compris
la vérification de type.
beforeRender()
La méthode beforeRender, comme son nom l'indique, est appelée avant chaque méthode
render<View>(). Elle est utilisée pour la configuration commune du template, passer des variables au
layout, etc.
render<View>(args...)
L'endroit où nous préparons le template pour le rendu ultérieur, lui passons des données, etc.
Les paramètres de la requête sont passés à la méthode, comme dans le cas de action<Action>(), y compris
la vérification de type.
public function renderShow(int $id): void
{
// nous obtenons les données du modèle et les passons au template
$this->template->article = $this->articles->getById($id);
}
afterRender()
La méthode afterRender, comme son nom l'indique encore une fois, est appelée après chaque méthode
render<View>(). Elle est utilisée plutôt exceptionnellement.
shutdown()
Appelée à la fin du cycle de vie du presenter.
Événements
En plus des méthodes startup(), beforeRender() et shutdown(), qui sont appelées dans
le cadre du cycle de vie du presenter, il est possible de définir d'autres fonctions appelées automatiquement. Le presenter
définit ce qu'on appelle des événements, dont vous ajoutez les
gestionnaires aux tableaux $onStartup, $onRender et $onShutdown.
class ArticlePresenter extends Nette\Application\UI\Presenter
{
public function __construct()
{
$this->onStartup[] = function () {
// ...
};
}
}
Les gestionnaires du tableau $onStartup sont appelés juste avant la méthode startup(), ceux de
$onRender entre beforeRender() et render<View>(), et enfin ceux de
$onShutdown juste avant shutdown().
Un bon conseil avant de continuer : comme vous pouvez le voir, un presenter peut gérer plusieurs actions/vues,
c'est-à-dire avoir plusieurs méthodes render<View>(). Nous recommandons toutefois de concevoir des presenters
avec une seule action, ou le moins d'actions possible.
Envoi de la réponse
La réponse d'un presenter est généralement le rendu d'un template avec une page HTML, mais elle peut aussi être l'envoi d'un fichier, de JSON ou même une redirection vers une autre page.
À tout moment du cycle de vie, nous pouvons envoyer une réponse avec l'une des méthodes suivantes et ainsi terminer le presenter :
redirect(),redirectPermanent(),redirectUrl()etforward()redirigenterror()termine le presenter en raison d'une erreursendJson($data)termine le presenter et envoie les données au format JSONsendTemplate()termine le presenter et rend immédiatement le templatesendResponse($response)termine le presenter et envoie une réponse personnaliséeterminate()termine le presenter sans réponse
Chacune de ces méthodes met immédiatement fin au presenter en levant une exception de terminaison silencieuse
Nette\Application\AbortException.
Si vous n'appelez aucune de ces méthodes, le presenter procède automatiquement au rendu du template. Pourquoi ? Parce que dans 99 % des cas, nous voulons rendre un template : le presenter adopte donc ce comportement par défaut pour nous simplifier le travail.
Création de liens
Le presenter dispose de la méthode link(), à l'aide de laquelle il est possible de créer des liens URL vers
d'autres presenters. Le premier paramètre est le presenter & action cible, suivi des arguments passés, qui peuvent être
spécifiés sous forme de tableau :
$url = $this->link('Product:show', $id);
$url = $this->link('Product:show', [$id, 'lang' => 'cs']);
Dans le template, les liens vers d'autres presenters & actions sont créés de cette manière :
<a n:href="Product:show $id">détail du produit</a>
Au lieu d'une URL réelle, écrivez simplement la paire connue Presenter:action et spécifiez d'éventuels
paramètres. L'astuce réside dans n:href, qui indique que cet attribut sera traité par Latte et générera une URL
réelle. Dans Nette, vous n'avez donc pas du tout à penser aux URL, seulement aux presenters et aux actions.
Plus d'informations peuvent être trouvées dans le chapitre Création de liens URL.
Redirection
Pour passer à un autre presenter, les méthodes redirect() et forward() sont utilisées, qui ont une
syntaxe très similaire à la méthode link().
La méthode forward() passe immédiatement au nouveau presenter sans redirection HTTP :
$this->forward('Product:show');
Exemple de redirection dite temporaire avec le code HTTP 302 (ou 303 si la méthode de la requête actuelle est POST) :
$this->redirect('Product:show', $id);
Vous obtenez une redirection permanente avec le code HTTP 301 comme ceci :
$this->redirectPermanent('Product:show', $id);
Il est possible de rediriger vers une autre URL en dehors de l'application avec la méthode redirectUrl(). Le code
HTTP peut être spécifié comme deuxième paramètre, la valeur par défaut est 302 (ou 303 si la méthode de la requête
actuelle est POST) :
$this->redirectUrl('https://nette.org');
La redirection termine immédiatement l'activité du presenter en levant une exception de terminaison silencieuse appelée
Nette\Application\AbortException.
Avant la redirection, il est possible d'envoyer des Messages Flash, c'est-à-dire des messages qui seront affichés dans le template après la redirection.
Messages Flash
Ce sont des messages informant généralement du résultat d'une opération. Une caractéristique importante des messages flash est qu'ils sont disponibles dans le template même après une redirection. Même après affichage, ils restent actifs pendant 30 secondes supplémentaires – par exemple, au cas où l'utilisateur rafraîchirait la page en raison d'une erreur de transmission – le message ne disparaîtra donc pas immédiatement.
Il suffit d'appeler la méthode flashMessage() et le
presenter se chargera de la transmettre au template. Le premier paramètre est le texte du message et le deuxième paramètre
facultatif est son type (error, warning, info, etc.). La méthode flashMessage() retourne une instance du message
flash, à laquelle des informations supplémentaires peuvent être ajoutées.
$this->flashMessage('L\'élément a été supprimé.');
$this->redirect(/* ... */); // et nous redirigeons
Dans le template, ces messages sont disponibles dans la variable $flashes sous forme d'objets
stdClass, qui contiennent les propriétés message (texte du message), type (type de
message) et peuvent contenir les informations utilisateur mentionnées précédemment. Nous les rendons par exemple comme
ceci :
{foreach $flashes as $flash}
<div class="flash {$flash->type}">{$flash->message}</div>
{/foreach}
Erreur 404 et autres
Si la requête ne peut pas être satisfaite, par exemple parce que l'article que nous voulons afficher n'existe pas dans la
base de données, nous levons une erreur 404 avec la méthode
error(?string $message = null, int $httpCode = 404).
public function renderShow(int $id): void
{
$article = $this->articles->getById($id);
if (!$article) {
$this->error();
}
// ...
}
Le code d'erreur HTTP peut être passé comme deuxième paramètre, la valeur par défaut est 404. La méthode fonctionne en
levant une exception Nette\Application\BadRequestException, après quoi Application passe le contrôle
à l'error-presenter. C'est un presenter dont la tâche est d'afficher une page informant de l'erreur survenue. La configuration
de l'error-preseter se fait dans la configuration
application.
Envoi de JSON
La méthode sendJson($data) encode les données données en JSON, les envoie comme réponse HTTP et termine le
presenter. Exemple :
public function actionData(): void
{
$data = ['hello' => 'nette'];
$this->sendJson($data);
}
Paramètres de la requête
Le presenter ainsi que chaque composant obtiennent leurs paramètres de la requête HTTP. Vous pouvez connaître leur valeur
avec la méthode getParameter($name) ou getParameters(). Les valeurs sont des chaînes ou des tableaux
de chaînes, il s'agit essentiellement de données brutes obtenues directement de l'URL.
Pour plus de commodité, nous recommandons de rendre les paramètres accessibles via une propriété. Il suffit de les marquer
avec l'attribut #[Parameter] :
use Nette\Application\Attributes\Parameter; // cette ligne est importante
class HomePresenter extends Nette\Application\UI\Presenter
{
#[Parameter]
public string $theme; // doit être public
}
Nous recommandons d'indiquer également le type de données pour la propriété (par ex. string) et Nette
transtypera automatiquement la valeur en conséquence. Les valeurs des paramètres peuvent également être validées.
Lors de la création d'un lien, la valeur des paramètres peut être définie directement :
<a n:href="Home:default theme: dark">cliquer</a>
Paramètres persistants
Les paramètres persistants sont utilisés pour maintenir l'état entre différentes requêtes. Leur valeur reste la même
même après avoir cliqué sur un lien. Contrairement aux données de session, ils sont transmis dans l'URL. Et cela de manière
entièrement automatique, il n'est donc pas nécessaire de les spécifier explicitement dans link() ou
n:href.
Exemple d'utilisation ? Vous avez une application multilingue. La langue actuelle est un paramètre qui doit constamment faire
partie de l'URL. Mais il serait incroyablement fastidieux de l'indiquer dans chaque lien. Vous en faites donc un paramètre
persistant lang et il sera transmis automatiquement. Génial !
La création d'un paramètre persistant est extrêmement simple dans Nette. Il suffit de créer une propriété publique et de
la marquer avec un attribut : (auparavant, /** @persistent */ était utilisé)
use Nette\Application\Attributes\Persistent; // cette ligne est importante
class ProductPresenter extends Nette\Application\UI\Presenter
{
#[Persistent]
public string $lang; // doit être public
}
Si $this->lang a la valeur, par exemple, 'en', alors les liens créés à l'aide de
link() ou n:href contiendront également le paramètre lang=en. Et après avoir cliqué sur
le lien, $this->lang sera à nouveau 'en'.
Nous recommandons d'indiquer également le type de données pour la propriété (par ex. string) et vous pouvez
également spécifier une valeur par défaut. Les valeurs des paramètres peuvent être validées.
Les paramètres persistants sont transmis par défaut entre toutes les actions du presenter donné. Pour qu'ils soient également transmis entre plusieurs presenters, il faut les définir soit :
- dans un ancêtre commun dont les presenters héritent
- dans un trait que les presenters utilisent :
trait LanguageAware
{
#[Persistent]
public string $lang;
}
class ProductPresenter extends Nette\Application\UI\Presenter
{
use LanguageAware;
}
Lors de la création d'un lien, la valeur du paramètre persistant peut être modifiée :
<a n:href="Product:show $id, lang: cs">détail en tchèque</a>
Ou il peut être réinitialisé, c'est-à-dire supprimé de l'URL. Il prendra alors sa valeur par défaut :
<a n:href="Product:show $id, lang: null">cliquer</a>
Espace de paramètres partagé
Les paramètres de la requête, les paramètres persistants et les paramètres des
méthodes action, render et handle (signal) partagent un seul et même espace, où chacun
est identifié par son nom. Si le même nom apparaît dans plusieurs d'entre eux, il désigne une seule et même valeur.
On en tire souvent parti. Un paramètre persistant lang et l'argument $lang d'une méthode d'action
ou de signal ne font qu'un : vous pouvez lire la valeur courante d'un paramètre persistant simplement en le déclarant dans la
signature de la méthode :
#[Persistent]
public string $lang;
public function handleSearch(string $query, string $lang): void
{
// $lang contient la valeur courante du paramètre persistant lang
}
Comme cet espace est partagé, veillez à ce que les noms de paramètres soient uniques, sauf si vous voulez délibérément qu'ils partagent une valeur. Cela vaut aussi pour les signaux, qui lisent en outre les paramètres du corps POST de la requête, voyez Les signaux en profondeur.
Composants interactifs
Les presenters ont un système de composants intégré. Les composants sont des unités autonomes et réutilisables que nous insérons dans les presenters. Il peut s'agir de formulaires, de datagrids, de menus, en fait de tout ce qu'il est judicieux d'utiliser de manière répétée.
Comment les composants sont-ils insérés dans le presenter et ensuite utilisés ? Vous l'apprendrez dans le chapitre Composants. Vous découvrirez même ce qu'ils ont en commun avec Hollywood.
Et où puis-je obtenir des composants ? Sur la page Componette, vous trouverez des composants open-source ainsi que de nombreux autres add-ons pour Nette, placés ici par des bénévoles de la communauté autour du framework.
Allons plus en profondeur
Ce que nous avons montré jusqu'à présent dans ce chapitre vous suffira probablement amplement. Les lignes suivantes sont destinées à ceux qui s'intéressent aux presenters en profondeur et veulent tout savoir.
Validation des paramètres
Les valeurs des Paramètres de la requête et des Paramètres persistants reçues de l'URL sont écrites dans les propriétés par la
méthode loadState(). Celle-ci vérifie également si le type de données indiqué pour la propriété correspond,
sinon elle répond par une erreur 404 et la page ne s'affiche pas.
Ne faites jamais confiance aveuglément aux paramètres, car ils peuvent être facilement modifiés par l'utilisateur dans
l'URL. Voici comment nous vérifions, par exemple, si la langue $this->lang fait partie des langues prises en
charge. Une bonne approche consiste à redéfinir la méthode loadState() mentionnée :
class ProductPresenter extends Nette\Application\UI\Presenter
{
#[Persistent]
public string $lang;
public function loadState(array $params): void
{
parent::loadState($params); // ici $this->lang est défini
// suit la vérification personnalisée de la valeur :
if (!in_array($this->lang, ['en', 'cs'])) {
$this->error();
}
}
}
Sauvegarde et restauration de la requête
La requête traitée par le presenter est un objet Nette\Application\Request et est retournée par
la méthode du presenter getRequest().
La requête actuelle peut être sauvegardée dans la session ou au contraire restaurée à partir de celle-ci et laisser le
presenter l'exécuter à nouveau. C'est utile par exemple dans une situation où l'utilisateur remplit un formulaire et sa
connexion expire. Pour ne pas perdre les données, avant de rediriger vers la page de connexion, nous sauvegardons la requête
actuelle dans la session à l'aide de $reqId = $this->storeRequest(), qui retourne son identifiant sous forme de
chaîne courte, et nous le passons comme paramètre au presenter de connexion.
Après la connexion, nous appelons la méthode $this->restoreRequest($reqId), qui récupère la requête de la
session et la transmet (forward). La méthode vérifie en même temps que la requête a été créée par le même utilisateur que
celui qui vient de se connecter. Si un autre utilisateur se connecte ou si la clé est invalide, elle ne fait rien et le programme
continue.
Consultez le guide Comment revenir à une page précédente.
Canonisation
Les presenters ont une fonctionnalité vraiment géniale qui contribue à un meilleur SEO (optimisation pour les moteurs de
recherche). Ils empêchent automatiquement l'existence de contenu dupliqué sur différentes URL. Si plusieurs adresses URL
mènent à une certaine cible, par ex. /index et /index?page=1, le framework détermine l'une d'elles
comme étant la principale (canonique) et redirige les autres vers elle à l'aide du code HTTP 301. Grâce à cela, les moteurs
de recherche n'indexent pas vos pages deux fois et ne diluent pas leur page rank.
Ce processus est appelé canonisation. L'URL canonique est celle générée par le routeur, généralement la première route correspondante dans la collection.
La canonisation est activée par défaut et peut être désactivée via $this->autoCanonicalize = false.
La redirection ne se produit pas lors d'une requête AJAX ou POST, car cela entraînerait une perte de données ou n'aurait aucune valeur ajoutée du point de vue du SEO.
Vous pouvez également déclencher la canonisation manuellement à l'aide de la méthode canonicalize(), à
laquelle, comme à la méthode link(), sont passés le presenter, l'action et les paramètres. Elle crée un lien et
le compare à l'URL actuelle. S'ils diffèrent, elle redirige vers le lien généré.
public function actionShow(int $id, ?string $slug = null): void
{
$realSlug = $this->facade->getSlugForId($id);
// redirige si $slug diffère de $realSlug
$this->canonicalize('Product:show', [$id, $realSlug]);
}
Pour un motif complet combinant les filtres de route et canonicalize() afin de produire des URL favorables au
référencement, voyez URL propres avec slugs.
Réponses
La réponse retournée par le presenter est un objet implémentant l'interface Nette\Application\Response. Il existe un certain nombre de réponses prêtes à l'emploi :
- Nette\Application\Responses\CallbackResponse – envoie un callback
- Nette\Application\Responses\FileResponse – envoie un fichier
- Nette\Application\Responses\ForwardResponse – forward()
- Nette\Application\Responses\JsonResponse – envoie du JSON
- Nette\Application\Responses\RedirectResponse – redirection
- Nette\Application\Responses\TextResponse – envoie du texte
- Nette\Application\Responses\VoidResponse – réponse vide
Les réponses sont envoyées avec la méthode sendResponse() :
use Nette\Application\Responses;
// Texte simple
$this->sendResponse(new Responses\TextResponse('Hello Nette!'));
// Envoie un fichier
$this->sendResponse(new Responses\FileResponse(__DIR__ . '/invoice.pdf', 'Invoice13.pdf'));
// La réponse sera un callback
$callback = function (Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) {
if ($httpResponse->getHeader('Content-Type') === 'text/html') {
echo '<h1>Hello</h1>';
}
};
$this->sendResponse(new Responses\CallbackResponse($callback));
Vous pouvez aussi écrire votre propre réponse. Il suffit d'implémenter l'interface Nette\Application\Response,
qui n'a qu'une méthode send() recevant la requête et la réponse HTTP. C'est utile, par exemple, pour diffuser des
données que vous ne voulez pas garder en mémoire :
class CsvResponse implements Nette\Application\Response
{
public function __construct(
private string $fileName,
private iterable $rows,
) {
}
public function send(Nette\Http\IRequest $request, Nette\Http\IResponse $response): void
{
$response->setContentType('text/csv', 'utf-8');
$response->sendAsFile($this->fileName);
$handle = fopen('php://output', 'w');
foreach ($this->rows as $row) {
fputcsv($handle, $row);
}
fclose($handle);
}
}
Vous l'envoyez ensuite dans le presenter comme d'habitude
: $this->sendResponse(new CsvResponse('export.csv', $rows));
Cache HTTP
La méthode lastModified() permet de tirer facilement parti du cache HTTP. Vous lui passez la date et l'heure de
dernière modification du contenu (sous forme de timestamp, de chaîne ou d'objet DateTimeInterface) et,
éventuellement, un validateur ETag (une courte chaîne identifiant la version courante du contenu, comme son hachage) et une
durée d'expiration. Si le navigateur détient déjà une version correspondante, le presenter envoie une réponse
304 Not Modified et termine : la page n'est donc ni rendue ni transférée inutilement :
public function renderArticle(int $id): void
{
$article = $this->articles->getById($id);
$this->lastModified($article->updatedAt);
// ...
}
Finalisation du template
Quand le presenter rend un template, la méthode sendTemplate() appelle completeTemplate() juste
avant le rendu. Cette méthode remplit les variables marquées de l'attribut #[TemplateVariable] et localise le
fichier de template (les variables par défaut sont déjà définies par la TemplateFactory lors de la création du
template). Vous pouvez redéfinir cette méthode protégée pour ajouter des variables partagées par toutes les vues ou pour
indiquer un autre fichier :
protected function completeTemplate(Nette\Application\UI\Template $template): void
{
parent::completeTemplate($template);
$template->siteName = 'My App';
}
Restriction d'accès avec #[Requires]
L'attribut #[Requires] offre des options avancées pour restreindre l'accès aux presenters et à leurs méthodes.
Il peut être utilisé pour spécifier les méthodes HTTP, exiger une requête AJAX, limiter à la même origine (same origin), et
l'accès uniquement via le forwarding. L'attribut peut être appliqué à la fois aux classes de presenter et aux méthodes
individuelles action<Action>(), render<View>(), handle<Signal>() et
createComponent<Name>().
Vous pouvez spécifier ces restrictions :
- sur les méthodes HTTP :
#[Requires(methods: ['GET', 'POST'])] - exiger une requête AJAX :
#[Requires(ajax: true)] - accès uniquement depuis la même origine :
#[Requires(sameOrigin: true)] - accès uniquement via forward :
#[Requires(forward: true)] - restriction à des actions spécifiques :
#[Requires(actions: 'default')]
Depuis la version 3.3, la correspondance de même origine est vérifiée à l'aide de l'en-tête
Sec-Fetch-Site du navigateur (auparavant via un cookie SameSite), ce qui est plus fiable et contrôle la
correspondance exacte du schéma, du domaine et du port.
Les détails se trouvent dans le guide Comment utiliser l'attribut Requires.
Vérification de la méthode HTTP
Les presenters dans Nette vérifient automatiquement la méthode HTTP de chaque requête entrante. La raison de cette
vérification est principalement la sécurité. Par défaut, les méthodes GET, POST, HEAD,
PUT, DELETE, PATCH sont autorisées.
Si vous souhaitez autoriser en plus, par exemple, la méthode OPTIONS, utilisez l'attribut
#[Requires] (depuis Nette Application v3.2) :
#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
class MyPresenter extends Nette\Application\UI\Presenter
{
}
Depuis la version 3.1.13, la vérification est effectuée dans checkHttpMethod(), qui contrôle si la méthode
indiquée dans la requête figure dans le tableau $presenter->allowedMethods. Depuis la version 3.2.3, cette
approche est dépréciée au profit de #[Requires]. Vous pouvez redéfinir la méthode ainsi :
class MyPresenter extends Nette\Application\UI\Presenter
{
protected function checkHttpMethod(): void
{
$this->allowedMethods[] = 'OPTIONS';
parent::checkHttpMethod();
}
}
Il est important de souligner que si vous autorisez la méthode OPTIONS, vous devez ensuite la gérer correctement
dans votre presenter. La méthode est souvent utilisée comme une requête dite preflight, que le navigateur envoie
automatiquement avant la requête réelle lorsqu'il est nécessaire de déterminer si la requête est autorisée du point de vue
de la politique CORS (Cross-Origin Resource Sharing). Si vous autorisez la méthode mais n'implémentez pas la réponse correcte,
cela peut entraîner des incohérences et des problèmes de sécurité potentiels.
Marquer les actions obsolètes
L'attribut #[Deprecated] marque des actions, des signaux ou des presenters entiers comme obsolètes et voués à
disparaître. Lors de la génération de liens vers ces parties obsolètes de l'application, Nette lève un avertissement pour
alerter les développeurs.
Vous pouvez appliquer l'attribut à toute la classe du presenter ou à chaque méthode action<Action>(),
render<View>() et handle<Signal>().