Exemple hypothétique mais applicabilité dans le monde réel (pour quelqu'un qui apprend, comme moi).
Compte tenu de ce code:
<?php
function send_money_to_grandma() {
internetofThings("send grandma","$1");
}
add_action('init','send_money_to_grandma');
add_action('init','send_money_to_grandma');
ok, maintenant je fais apparaître mon site WP et me connecte. Je traverse quelques pages dans Admin. L'action «init» se déclenche 100 fois au total avant que la batterie de mon ordinateur portable ne meure.
Premières questions: combien d'argent avons-nous envoyé à grand-mère? Est-ce 1 $, 2 $, 100 $ ou 200 $ (ou autre chose?)
Si vous pouviez également expliquer votre réponse, ce serait génial.
Deuxième question: si nous voulons nous assurer de n'envoyer que 1 $ à grand-mère, quelle est la meilleure façon de procéder? Variable globale (sémaphore) qui est définie sur "true" la première fois que nous envoyons $ 1? Ou existe-t-il un autre test pour voir si une action s'est déjà produite et l'empêcher de se déclencher plusieurs fois?
Troisième question: est-ce quelque chose qui inquiète les développeurs de plugins? Je me rends compte que mon exemple est stupide mais je pensais à la fois à des problèmes de performances et à d'autres effets secondaires inattendus (par exemple, si la fonction se met à jour / s'insère dans la base de données).
Réponses:
Voici quelques réflexions aléatoires à ce sujet:
Question 1
Pour 100 chargements de page, nous lui avons envoyé 100 x 1 $ = 100 $.
Ici, nous entendons en fait des
100 x do_action( 'init' )
appels.Peu importe que nous l'ajoutions deux fois avec:
car les rappels et les priorités (par défaut 10) sont identiques .
Nous pouvons vérifier comment le
add_action
est juste un wrapper pouradd_filter
construire le$wp_filter
tableau global :Si toutefois nous modifions la priorité:
alors nous lui enverrions 2 x 1 $ par chargement de page ou 200 $ pour 100 chargements de page.
Même si les rappels sont différents:
Question 2
Si nous ne voulons l'envoyer qu'une fois par chargement de page , alors cela devrait le faire:
parce que le
init
crochet n'est tiré qu'une seule fois. Nous pouvons avoir d'autres crochets qui se déclenchent plusieurs fois par chargement de page.Appelons:
mais que se passe-t-il si
someaction
10 fois par chargement de page se déclenche?Nous pourrions ajuster la
send_money_to_grandma()
fonction avecou utilisez une variable statique comme compteur:
Si nous ne voulons l'exécuter qu'une seule fois (jamais!), Nous pouvons alors enregistrer une option dans le
wp_options
tableau via l' API Options :Si nous voulons lui envoyer de l'argent une fois par jour, nous pouvons utiliser l' API transitoire
ou même utiliser le wp-cron.
Notez que vous pourriez avoir des appels ajax. ainsi que.
Il existe des moyens de les vérifier, par exemple avec
DOING_AJAX
Il peut également y avoir des redirections qui pourraient interrompre le flux.
Ensuite , nous pourrions vouloir limiter au back - end uniquement,
is_admin()
ou non:! is_admin()
.Question 3
oui c'est important.
Si nous voulons rendre notre grand-mère très heureuse, nous ferions:
mais ce serait très mauvais pour les performances ... et notre portefeuille ;-)
la source
C'est plus un commentaire à la très bonne réponse de Birgire qu'une réponse complète, mais devant écrire du code, les commentaires ne conviennent pas.
D'après la réponse, il peut sembler que la seule raison pour laquelle une action est ajoutée une fois dans l'exemple de code OP, même si elle
add_action()
est appelée deux fois, est le fait que la même priorité est utilisée. Ce n'est pas vrai.Dans le code d'
add_filter
une partie importante se trouve_wp_filter_build_unique_id()
l'appel de fonction, qui crée un identifiant unique par rappel .Si vous utilisez une variable simple, comme une chaîne qui contient un nom de fonction, par exemple
"send_money_to_grandma"
, alors l'id sera égal à la chaîne elle-même, donc si la priorité est la même, étant également la même id, le rappel est ajouté une fois.Cependant, les choses ne sont pas toujours aussi simples comme ça. Les rappels peuvent être tout ce qui est
callable
en PHP:Les deux premiers sont représentés, respectivement, par une chaîne et un tableau de 2 chaînes (
'send_money_to_grandma'
etarray('MoneySender', 'send_to_grandma')
) de sorte que l'id est toujours le même, et vous pouvez être sûr que le rappel est ajouté une fois si la priorité est la même.Dans tous les 3 autres cas, l'id dépend des instances d'objet (une fonction anonyme est un objet en PHP) donc le rappel n'est ajouté qu'une seule fois si l'objet est la même instance , et il est important de noter cette même instance et la même classe sont deux choses différentes.
Prenez cet exemple:
Combien de dollars envoyons-nous par chargement de page?
La réponse est 2, car l'ID que WordPress génère
$sender1
et$sender2
est différent.La même chose se produit dans ce cas:
Ci-dessus, j'ai utilisé la fonction à l'
sent_to_grandma
intérieur des fermetures, et même si le code est identique, les 2 fermetures sont 2 instances d'\Closure
objet différentes, donc WP créera 2 identifiants différents, ce qui entraînera l'ajout de l'action deux fois, même si la priorité est la même.la source
Vous ne pouvez pas ajouter la même action au même hook d'action , avec la même priorité .
Cela est fait pour éviter que plusieurs plugins s'appuyant sur une action de plugins tiers ne se produisent plus d'une fois (pensez au woocommerce et à tous ses plugins tiers, comme les intégrations de paiement de passerelle, etc.). Donc sans préciser de priorité, grand-mère reste pauvre:
Cependant, si vous ajoutez la priorité à ces actions:
Grand-mère meurt maintenant avec 4 $ dans sa poche (1, 2, 3 et la valeur par défaut: 10).
la source