Hipotetyczny przykład, ale zastosowanie w prawdziwym świecie (dla kogoś uczącego się, takiego jak ja).
Biorąc pod uwagę ten kod:
<?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, teraz otwieram swoją stronę WP i loguję się. Przechodzę przez kilka stron w Administratorze. Akcja „init” strzela łącznie 100 razy, zanim wyczerpie się bateria mojego laptopa.
Pierwsze pytania: ile pieniędzy wysłaliśmy babci? Czy to 1 USD, 2 USD, 100 USD lub 200 USD (czy coś innego?)
Gdybyś mógł także wyjaśnić swoją odpowiedź, byłoby wspaniale.
Drugie pytania: jeśli chcemy mieć pewność, że wysyłamy babci tylko 1 USD, jaki jest najlepszy sposób? Zmienna globalna (semafor), która zostaje ustawiona na „prawda” przy pierwszym wysłaniu 1 $? A może jest jakiś inny test, aby sprawdzić, czy akcja już się wydarzyła i zapobiec wielokrotnemu uruchomieniu?
Trzecie pytanie: czy jest to coś, o co martwią się twórcy wtyczek? Zdaję sobie sprawę, że mój przykład jest głupi, ale myślałem o problemach z wydajnością i innych nieoczekiwanych skutkach ubocznych (np. Czy funkcja aktualizuje / wstawia do bazy danych).
Odpowiedzi:
Oto kilka przypadkowych przemyśleń na ten temat:
Pytanie 1
Przy 100 ładowaniach stron wysłaliśmy jej 100 x 1 USD = 100 USD.
Tutaj mamy na myśli
100 x do_action( 'init' )
połączenia.Nie miało znaczenia, że dodaliśmy go dwa razy z:
ponieważ wywołania zwrotne i priorytety (domyślnie 10) są identyczne .
Możemy sprawdzić, w jaki sposób
add_action
jest to tylko opakowanie,add_filter
które tworzy globalną$wp_filter
tablicę:Gdybyśmy jednak zmienili priorytet:
wtedy wysyłalibyśmy jej 2 x 1 USD za ładowanie strony lub 200 USD za 100 ładowań strony.
To samo, jeśli wywołania zwrotne są różne:
Pytanie 2
Jeśli chcemy wysłać go tylko raz przy ładowaniu strony , należy to zrobić:
ponieważ
init
hak wystrzeliwuje się tylko raz. Możemy mieć inne zaczepy, które uruchamiają się wielokrotnie podczas ładowania strony.Zadzwońmy:
ale co się stanie, jeśli
someaction
uruchomi się 10 razy na ładowanie strony?Możemy dostosować
send_money_to_grandma()
funkcję za pomocąlub użyj zmiennej statycznej jako licznika:
Jeśli chcemy uruchomić go tylko raz (kiedykolwiek!), Możemy zarejestrować opcję w
wp_options
tabeli za pośrednictwem interfejsu API opcji :Jeśli chcemy wysyłać jej pieniądze raz dziennie, możemy skorzystać z Transient API
lub nawet użyj wp-cron.
Pamiętaj, że możesz mieć wywołania ajax. także.
Istnieją sposoby, aby je sprawdzić, np. Za pomocą
DOING_AJAX
Mogą również istnieć przekierowania, które mogą zakłócić przepływ.
Wtedy może chcemy ograniczać tylko do backend
is_admin()
lub nie:! is_admin()
.Pytanie 3
tak, to ważne.
Jeśli chcemy uszczęśliwić naszą babcię, zrobilibyśmy:
ale byłoby to bardzo złe dla wydajności ... i naszego portfela ;-)
źródło
Jest to bardziej komentarz do bardzo dobrej odpowiedzi Birgire niż pełna odpowiedź, ale ponieważ trzeba napisać kod, komentarze nie pasują.
Z odpowiedzi może się wydawać, że jedynym powodem, dla którego akcja jest dodawana raz w przykładowym kodzie OP, nawet jeśli
add_action()
jest wywoływana dwukrotnie, jest fakt, że zastosowano ten sam priorytet. To nieprawda.W kodzie
add_filter
ważnej części znajduje się_wp_filter_build_unique_id()
wywołanie funkcji, które tworzy unikalny identyfikator dla każdego wywołania zwrotnego .Jeśli użyjesz prostej zmiennej, takiej jak ciąg znaków, który zawiera nazwę funkcji, np
"send_money_to_grandma"
. Identyfikator będzie równy samemu ciągowi, więc jeśli priorytet jest taki sam, a także identyczny, wywołanie zwrotne jest dodawane raz.Jednak rzeczy nie zawsze są takie proste. Callbacki mogą być dowolnymi
callable
elementami PHP:Pierwsze dwa są reprezentowane odpowiednio przez ciąg i tablicę 2 ciągów (
'send_money_to_grandma'
iarray('MoneySender', 'send_to_grandma')
), więc identyfikator jest zawsze taki sam i możesz być pewien, że wywołanie zwrotne zostanie dodane raz, jeśli priorytet jest taki sam.We wszystkich pozostałych 3 przypadkach identyfikator zależy od instancji obiektu (anonimowa funkcja jest obiektem w PHP), więc wywołanie zwrotne jest dodawane tylko raz, jeśli obiekt jest tą samą instancją , i należy zauważyć, że ta sama instancja i ta sama klasa są dwie różne rzeczy.
Weź ten przykład:
Ile dolarów wysyłamy na ładowanie strony?
Odpowiedź to 2, ponieważ identyfikator WordPress generuje
$sender1
i$sender2
jest inny.To samo dzieje się w tym przypadku:
Powyżej użyłem funkcji
sent_to_grandma
wewnątrz zamknięć i nawet jeśli kod jest identyczny, 2 zamknięcia są 2 różnymi instancjami\Closure
obiektu, więc WP utworzy 2 różne identyfikatory, co spowoduje, że akcja zostanie dodana dwukrotnie, nawet jeśli priorytet jest taki sam.źródło
Nie możesz dodać tej samej akcji do tego samego haka akcji , z takim samym priorytetem .
Ma to na celu zapobieżenie wielokrotnemu wtyczkom polegającym na działaniu wtyczek innych firm więcej niż raz (pomyśl woocommerce i wszystkie wtyczki innych firm, takie jak integracja płatności z bramą itp.). Bez określenia priorytetu babcia pozostaje biedna:
Jeśli jednak dodasz priorytet do tych działań:
Babcia umiera teraz z 4 $ w kieszeni (1, 2, 3 i domyślnie: 10).
źródło