Stworzyłem wtyczkę i oczywiście będąc sobą, chciałem iść z przyjemnym podejściem OO. Teraz tworzę tę klasę, a następnie tuż poniżej stwórz instancję tej klasy:
class ClassName {
public function __construct(){
}
}
$class_instance = new ClassName();
Zakładam, że istnieje więcej sposobów WP na zainicjowanie tej klasy, a potem natknąłem się na ludzi, którzy twierdzą, że wolą mieć init()
funkcję niż __construct()
jedną. I podobnie znalazłem kilka osób korzystających z następującego haka:
class ClassName {
public function init(){
}
}
add_action( 'load-plugins.php', array( 'ClassName', 'init' ) );
Jaki jest ogólnie uważany za najlepszy sposób na utworzenie instancji klasy WP podczas ładowania i ustawienie jej jako globalnie dostępnej zmiennej?
UWAGA: Jako interesujący punkt dodatkowy zauważyłem, że chociaż register_activation_hook()
można go wywoływać z wewnątrz __construct
, nie można go wywoływać z init()
drugiego przykładu. Być może ktoś mógłby mnie oświecić w tej kwestii.
Edycja: Dzięki za wszystkie odpowiedzi, wyraźnie toczą się dyskusje na temat tego, jak poradzić sobie z inicjalizacją w samej klasie, ale myślę, że ogólnie istnieje całkiem dobry konsensus, który add_action( 'plugins_loaded', ...);
jest najlepszym sposobem na rozpoczęcie go ...
Edycja: Żeby pomylić sprawy, widziałem również, że ta metoda jest używana (chociaż sam nie użyłbym tej metody, ponieważ przekształcenie ładnej klasy OO w funkcję wydaje się być w stanie ją pokonać):
// Start up this plugin
add_action( 'init', 'ClassName' );
function ClassName() {
global $class_name;
$class_name = new ClassName();
}
źródło
Odpowiedzi:
Dobre pytanie, istnieje wiele podejść i zależy to od tego, co chcesz osiągnąć.
Często tak robię;
Bardziej dokładny i dokładny przykład, który powstał w wyniku niektórych niedawnych dyskusji na ten temat na czacie, można zobaczyć w tej treści przez członka WPSE toscho .
Podejście pustego konstruktora.
Oto fragment zalet / wad wziętych z powyższej treści, który w pełni ilustruje podejście pustego konstruktora.
Moim zdaniem wada jest słaba, dlatego musiałoby to być moje ulubione podejście, jednak nie jedyne, z którego korzystam. W rzeczywistości kilka innych dużych ciężarów bez wątpienia weźmie udział w tym temacie wraz ze swoim podejściem do tego tematu wkrótce, ponieważ istnieją pewne dobre opinie dotyczące tego tematu, które należy wypowiedzieć.
uwaga: muszę znaleźć główny przykład z toscho, który przejrzał 3 lub 4 porównania tego, jak utworzyć instancję klasy we wtyczce, która analizowała zalety i wady każdego z nich, które to łącze było preferowanym sposobem, aby to zrobić, ale inne przykłady stanowią dobry kontrast do tego tematu. Mam nadzieję, że toscho nadal ma to w aktach.Uwaga: The WPSE odpowiedzi do tego tematu z odpowiednich przykładów i porównań. Również najlepsze rozwiązanie, na przykład klasa w WordPress.
źródło
update.php
plikiem podstawowym i nie jest częścią zwykłych domyślnych działań, na których należy się opierać, jeśli chodzi o sekwencję zdarzeń, które uruchamiają się podczas inicjalizacji i dlatego wolę w tym przypadku użyć haków, które mają zastosowanieplugins_loaded
. To często nazywam szybką migawką tego, co dzieje się, gdy Action Reference . Moje wyjaśnienie nie jest kompletne.register_activation_hook()
, musisz wywołać tę funkcję przed uruchomieniemplugins_loaded
akcji.Przybywając tutaj dokładnie 2 lata po zadaniu pierwotnego pytania, chciałbym wskazać kilka rzeczy . (Nigdy nie proś mnie o wskazanie wielu rzeczy ).
Właściwy hak
Aby utworzyć instancję klasy wtyczki, należy użyć odpowiedniego haka. Nie ma ogólnej zasady, dla której jest, ponieważ zależy to od tego, co robi klasa.
Używanie bardzo wczesnego haka, jak
"plugins_loaded"
często, nie ma sensu, ponieważ taki hak jest uruchamiany dla żądań administratora, interfejsu użytkownika i AJAX, ale bardzo często późniejszy hak jest znacznie lepszy, ponieważ pozwala na tworzenie klas wtyczek tylko w razie potrzeby.Na przykład można utworzyć instancję klasy wykonującej różne czynności dla szablonów
"template_redirect"
.Ogólnie rzecz biorąc, bardzo rzadko zdarza się, że klasa musi zostać utworzona, zanim
"wp_loaded"
zostanie zwolniona.Bez klasy Boga
Większość wszystkich klas użytych jako przykłady w starszych odpowiedziach używa klasy o nazwie like
"Prefix_Example_Plugin"
lub"My_Plugin"
... Oznacza to, że prawdopodobnie istnieje główna klasa wtyczki.Cóż, chyba że wtyczka jest utworzona przez jedną klasę (w takim przypadku nadanie jej nazwy po nazwie wtyczki jest absolutnie uzasadnione), aby utworzyć klasę, która zarządza całą wtyczką (np. Dodając wszystkie zaczepy, których potrzebuje wtyczka lub tworząc instancję wszystkich pozostałych klas wtyczek) ) można uznać za złą praktykę, jako przykład boskiego przedmiotu .
W obiektowym programowaniu kod powinien być SOLIDNY, gdy „S” oznacza „zasadę pojedynczej odpowiedzialności” .
Oznacza to, że każda klasa powinna zrobić jedną rzecz. W rozwoju wtyczek WordPress oznacza to, że programiści powinni unikać używania pojedynczego haka do tworzenia głównej klasy wtyczki, ale należy używać różnych haków do tworzenia różnych klas, zgodnie z odpowiedzialnością klasy.
Unikaj haków w konstruktorze
Ten argument został wprowadzony w innych odpowiedziach tutaj, jednak chciałbym zwrócić uwagę na tę koncepcję i połączyć tę inną odpowiedź tam, gdzie została dość szeroko wyjaśniona w zakresie testów jednostkowych.
Prawie 2015: PHP 5.2 jest dla zombie
Od 14 sierpnia 2014 r. PHP 5.3 dobiegł końca . To zdecydowanie nie żyje. PHP 5.4 będzie obsługiwane przez cały 2015 rok, co oznacza, że będę pisać przez kolejny rok.
Jednak WordPress nadal obsługuje PHP 5.2, ale nikt nie powinien pisać ani jednego wiersza kodu obsługującego tę wersję, szczególnie jeśli kod jest OOP.
Istnieją różne powody:
Jeśli nie chcesz używać kodu PHP 5.4+, użyj co najmniej 5.3+
Przykład
W tym momencie nadszedł czas, aby przejrzeć starsze odpowiedzi w oparciu o to, co powiedziałem do tego momentu.
Kiedy już nie będziemy musieli przejmować się 5.2, możemy i powinniśmy używać przestrzeni nazw.
Dla lepszego wyjaśnienia zasady pojedynczej odpowiedzialności, mój przykład użyje 3 klas, jednej, która robi coś na frontendie, jednej na backendie i trzeciej używanej w obu przypadkach.
Klasa administracyjna:
Klasa frontonu:
Interfejs narzędzi:
I klasa Narzędzia, używana przez pozostałe dwa:
Po tych zajęciach mogę utworzyć ich instancję za pomocą odpowiednich haków. Coś jak:
Odwrócenie zależności i wstrzyknięcie zależności
W powyższym przykładzie użyłem przestrzeni nazw i funkcji anonimowych, aby utworzyć instancję różnych klas w różnych punktach zaczepienia, stosując w praktyce to, co powiedziałem powyżej.
Zwróć uwagę, jak przestrzenie nazw pozwalają na tworzenie klas nazwanych bez żadnego prefiksu.
Zastosowałem inną koncepcję, która została wspomniana pośrednio powyżej: Wstrzykiwanie zależności , jest to jedna metoda zastosowania zasady odwrócenia zależności , „D” w akronimie SOLID.
Tools
Klasa jest „wstrzykiwany” w pozostałych dwóch klas, gdy są one instancja, więc w ten sposób możliwe jest oddzielenie odpowiedzialności.Ponadto
AdminStuff
iFrontStuff
klas używać typów parametrów zadeklarować potrzebują klasy, która implementujeToolsInterface
.W ten sposób my lub użytkownicy korzystający z naszego kodu mogą korzystać z różnych implementacji tego samego interfejsu, dzięki czemu nasz kod nie jest sprzężony z konkretną klasą, ale z abstrakcją: na tym właśnie polega zasada odwrócenia zależności.
Powyższy przykład można jednak ulepszyć. Zobaczmy jak.
Autoloader
Dobrym sposobem na napisanie lepiej czytelnego kodu OOP nie jest mieszanie definicji typów (interfejsów, klas) z innym kodem i umieszczanie każdego typu we własnym pliku.
Zasada ta jest również jednym ze standardów kodowania PSR-1 1 .
Jednak w ten sposób, zanim będzie można skorzystać z klasy, trzeba wymagać pliku, który ją zawiera.
Może to być przytłaczające, ale PHP udostępnia funkcje narzędziowe do automatycznego ładowania klasy, gdy jest to wymagane, za pomocą wywołania zwrotnego, które ładuje plik na podstawie jego nazwy.
Korzystanie z przestrzeni nazw staje się bardzo łatwe, ponieważ teraz można dopasować strukturę folderów do struktury przestrzeni nazw.
Jest to nie tylko możliwe, ale jest to także kolejny standard PSR (lub lepiej 2: PSR-0 jest przestarzałe i PSR-4 ).
Zgodnie z tymi standardami można korzystać z różnych narzędzi obsługujących automatyczne ładowanie, bez konieczności kodowania niestandardowego automatycznego ładowania.
Muszę powiedzieć, że standardy kodowania WordPress mają różne zasady nazywania plików.
Więc pisząc kod dla rdzenia WordPress, programiści muszą przestrzegać zasad WP, ale podczas pisania niestandardowego kodu jest to wybór programisty, ale korzystanie ze standardu PSR jest łatwiejsze w użyciu już napisanych narzędzi 2 .
Wzorce globalnego dostępu, rejestru i lokalizatora usług.
Jednym z największych problemów podczas tworzenia instancji klas wtyczek w WordPress jest sposób dostępu do nich z różnych części kodu.
Sam WordPress stosuje podejście globalne : zmienne są zapisywane w zakresie globalnym, dzięki czemu są dostępne wszędzie. Każdy programista WP wpisuje to słowo
global
tysiące razy w swojej karierze.Takie podejście zastosowałem w powyższym przykładzie, ale jest złe .
Ta odpowiedź jest już o wiele za długa, aby pozwolić mi wyjaśnić, dlaczego, ale przeczytanie pierwszych wyników w SERP dla „zmiennych globalnych zło” jest dobrym punktem wyjścia.
Ale jak można uniknąć zmiennych globalnych?
Istnieją różne sposoby.
Niektóre starsze odpowiedzi tutaj wykorzystują podejście do wystąpienia statycznego .
Jest to łatwe i całkiem w porządku, ale wymusza wdrożenie wzorca dla każdej klasy, do której chcemy uzyskać dostęp.
Co więcej, wiele razy takie podejście stawia drogę do wpadnięcia w kwestię klasy boga, ponieważ programiści udostępniają klasę główną za pomocą tej metody, a następnie używają jej do uzyskania dostępu do wszystkich innych klas.
Wyjaśniłem już, jak zła jest klasa boga, więc podejście do instancji statycznych jest dobrym sposobem, gdy wtyczka musi tylko udostępnić jedną lub dwie klasy.
Nie oznacza to, że można go używać tylko do wtyczek posiadających tylko kilka klas. W rzeczywistości, gdy zasada wstrzykiwania zależności jest właściwie stosowana, możliwe jest tworzenie dość złożonych aplikacji bez konieczności udostępniania dużej liczby osób na całym świecie przedmiotów.
Jednak czasami wtyczki muszą udostępnić niektóre klasy, w takim przypadku podejście do instancji statycznej jest przytłaczające.
Innym możliwym podejściem jest użycie wzorca rejestru .
Jest to bardzo prosta implementacja:
Za pomocą tej klasy możliwe jest przechowywanie obiektów w obiekcie rejestru według identyfikatora, więc mając dostęp do rejestru, można mieć dostęp do wszystkich obiektów. Oczywiście, kiedy obiekt jest tworzony po raz pierwszy, należy go dodać do rejestru.
Przykład:
Powyższy przykład wyjaśnia, że rejestr, aby był użyteczny, musi być globalnie dostępny. Zmienna globalna dla jedynego rejestru nie jest bardzo zła, jednak dla nie-globalnych purystów możliwe jest wdrożenie metody statycznej instancji dla rejestru, a może funkcja ze zmienną statyczną:
Przy pierwszym wywołaniu funkcja utworzy instancję rejestru, a przy kolejnych wywołaniach po prostu ją zwróci.
Inną specyficzną dla WordPress metodą globalnej dostępności klasy jest zwracanie instancji obiektu z filtra. Coś takiego:
Po tym wszystkim potrzebny jest rejestr:
Innym wzorem, który można zastosować, jest wzorzec lokalizatora usług . Jest podobny do wzorca rejestru, ale lokalizatory usług są przekazywane do różnych klas za pomocą wstrzykiwania zależności.
Główny problem z tym wzorcem polega na tym, że ukrywa on zależności klas, co utrudnia utrzymanie i odczytanie kodu.
Pojemniki DI
Bez względu na metodę globalnego dostępu do rejestru lub lokalizatora usług, obiekty muszą być tam przechowywane, a przed ich zapisaniem muszą zostać utworzone.
W złożonych aplikacjach, w których jest dość dużo klas, a wiele z nich ma kilka zależności, tworzenie instancji klas wymaga dużej ilości kodu, więc zwiększa się możliwość błędów: w kodzie, który nie istnieje, nie może być błędów.
W ostatnich latach pojawiły się biblioteki PHP, które pomagają programistom PHP w łatwym tworzeniu instancji i przechowywaniu instancji obiektów, automatycznie rozwiązując ich zależności.
Biblioteki te znane są jako kontenery wstrzykiwania zależności, ponieważ są one w stanie tworzyć instancje klasy rozwiązujące zależności, a także przechowywać obiekty i zwracać je w razie potrzeby, działając podobnie do obiektu rejestru.
Zwykle podczas korzystania z kontenerów DI programiści muszą konfigurować zależności dla każdej klasy aplikacji, a następnie, gdy klasa jest potrzebna w kodzie, jest tworzona instancja z odpowiednimi zależnościami, a ta sama instancja jest zwracana wielokrotnie na kolejne żądania .
Niektóre kontenery DI są również w stanie automatycznie wykrywać zależności bez konfiguracji, ale przy użyciu odbicie PHP .
Niektóre dobrze znane kontenery DI to:
i wiele innych.
Chcę zauważyć, że w przypadku prostych wtyczek, które obejmują tylko kilka klas, a klasy nie mają wielu zależności, prawdopodobnie nie warto używać kontenerów DI: metoda wystąpienia statycznego lub rejestr dostępny globalnie są dobrym rozwiązaniem, ale w przypadku złożonych wtyczek korzyści z pojemnika DI stają się oczywiste.
Oczywiście nawet obiekty kontenera DI muszą być dostępne, aby mogły być używane w aplikacji, w tym celu można zastosować jedną z metod opisanych powyżej, zmienną globalną, zmienną instancji statycznej, zwracający obiekt przez filtr i tak dalej.
Kompozytor
Korzystanie z kontenera DI często oznacza używanie kodu innej firmy. W dzisiejszych czasach, w PHP, kiedy musimy użyć zewnętrznej biblioteki lib (czyli nie tylko kontenerów DI, ale dowolnego kodu, który nie jest częścią aplikacji), po prostu pobranie go i umieszczenie w naszym folderze aplikacji nie jest uważane za dobrą praktykę. Nawet jeśli jesteśmy autorami tego innego fragmentu kodu.
Oddzielenie kodu aplikacji od zewnętrznych zależności jest oznaką lepszej organizacji, lepszej niezawodności i lepszego rozsądku kodu.
Kompozytor jest de facto standardem w społeczności PHP do zarządzania zależnościami PHP. Będąc daleko w głównym nurcie również w społeczności WP, jest to narzędzie, które każdy programista PHP i WordPress powinien przynajmniej wiedzieć, jeśli nie używać.
Ta odpowiedź ma już rozmiar książki, aby umożliwić dalszą dyskusję, a także omawianie tutaj Kompozytora prawdopodobnie nie jest tematem, zostało wspomniane tylko ze względu na kompletność.
Aby uzyskać więcej informacji, odwiedź witrynę kompozytor i warto też daje się czytać do tego minisite kurator @Rarst .
1 PSR to reguły standardów PHP wydane przez PHP Framework Interop Group
2 Kompozytor (biblioteka, która zostanie wymieniona w tej odpowiedzi) zawiera między innymi także narzędzie autoloadera.
źródło
Używam następującej struktury:
Uwagi:
init
metodę)Oświadczenie Nie korzystam jeszcze z testów jednostkowych ( tyle rzeczy na moim talerzu ) i słyszę, że statyczny może być dla nich mniej preferowany. Wykonaj swoje badania, jeśli chcesz to przetestować jednostkowo.
źródło
Wszystko zależy od funkcjonalności.
Kiedyś stworzyłem wtyczkę, która rejestrowała skrypty, gdy wywoływano konstruktora, więc musiałem podpiąć go na
wp_enqueue_scripts
haku.Jeśli chcesz zadzwonić po
functions.php
załadowaniu pliku, równie dobrze możesz utworzyć instancję,$class_instance = new ClassName();
jak wspomniałeś.Możesz rozważyć szybkość i zużycie pamięci. Nic mi nie wiadomo, ale mogę sobie wyobrazić, że w niektórych przypadkach istnieją niesprawdzone haki. Tworząc instancję w tym punkcie zaczepienia, możesz zaoszczędzić trochę zasobów serwera.
źródło
init()
metodę statyczną , więc instancja klasy jest wywoływana w zakresie klasy zamiast w innym zakresie, w którym można ewentualnie zastąpić istniejące zmienne.Wiem, że to ma kilka lat, ale tymczasem php 5.3 obsługuje anonimowe metody , więc wymyśliłem:
i jakoś najbardziej to lubię. Mogę używać zwykłych konstruktorów i nie muszę definiować żadnych metod „init” ani „on_load”, które psują moje struktury OOP.
źródło