Najlepszy sposób na zainicjowanie zajęć we wtyczce WP?


89

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();
}

1
Jeśli chodzi o ostatnią edycję, jeśli jest zawarta w tym samym pliku wtyczki co klasa, staje się ona nieco bezużyteczna. Równie dobrze możesz utworzyć instancję klasy zgodnie z metodą, którą opisuję. Nawet jeśli znajduje się w osobnym pliku, jest nadal nieco bezcelowy. Widzę tylko przypadek użycia, jeśli chcesz utworzyć funkcję otoki, która umożliwia tworzenie instancji klasy poza plikami wtyczek, w ramach motywów i tak dalej. Mimo to musiałbym zapytać, jaka to logika, ponieważ prawidłowe użycie warunkowych i haczyków powinno pozwolić na dokładną kontrolę ziarna nad instancjami, umożliwiając skupienie się na użyciu wtyczki.
Adam

Trochę się z tym zgadzam, ale pomyślałem, że warto go umieścić, ponieważ znalazłem go w kilku wtyczkach WP.
kalpaitch

Odpowiedzi:


60

Dobre pytanie, istnieje wiele podejść i zależy to od tego, co chcesz osiągnąć.

Często tak robię;

add_action( 'plugins_loaded', array( 'someClassy', 'init' ));

class someClassy {

    public static function init() {
        $class = __CLASS__;
        new $class;
    }

    public function __construct() {
           //construct what you see fit here...
    }

    //etc...
}

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.

  • Zalety:

    • Testy jednostkowe mogą tworzyć nowe instancje bez automatycznej aktywacji żadnych zaczepów. Bez singletonu.

    • Nie jest wymagana zmienna globalna.

    • Ktokolwiek chce pracować z instancją wtyczki, może po prostu wywołać T5_Plugin_Class_Demo :: get_instance ().

    • Łatwy do dezaktywacji.

    • Nadal prawdziwe OOP: żadne metody pracy nie są statyczne.

  • Niekorzyść:

    • Może trudniej czytać?

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.

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
class My_Plugin {

    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance() {

        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo() {

        return $this->var; // never echo or print in a shortcode!
    }
}

jaka byłaby różnica między add działań ('plugins_loaded', ...); i dodatek działań („load-plugins.php”, ...); Użyłem tego drugiego przykładu
kalpaitch

1
Z tego, co rozumiem, load-plugins.php, chociaż działa, jest powiązane z update.phpplikiem 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ą zastosowanie plugins_loaded. To często nazywam szybką migawką tego, co dzieje się, gdy Action Reference . Moje wyjaśnienie nie jest kompletne.
Adam

4
Podoba mi się to podejście singletonowe. Jednak pytam o użycie plugins_loaded jako haka inicjującego. Ten hak powinien być uruchamiany po załadowaniu wszystkich wtyczek. Podłączając się do niego, możesz w pewnym sensie przejąć kontrolę nad tym zaczepem i możesz bawić się w konflikty lub problemy z sekwencją uruchamiania z innymi wtyczkami lub motywami, które zaczepiają się w plugins_loaded. Nie podjąłbym żadnej akcji, aby uruchomić twoją metodę inicjalizacji. Architektura wtyczki została zaprojektowana tak, aby działała w trybie inline, a nie w przypadku akcji.
Tom Auger

2
Zauważ, że jeśli używasz register_activation_hook(), musisz wywołać tę funkcję przed uruchomieniem plugins_loadedakcji.
Geert

1
Jako dodatkowe informacje zobacz ten post z @mikeschinkel i dyskusję w komentarzach. hardcorewp.com/2012/…
bueltge

78

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:

  • PHP 5.2 nie żyje dawno temu, nie wydano dla niego żadnych poprawek bezpieczeństwa, co oznacza, że ​​nie jest bezpieczny
  • PHP 5.3 dodał wiele funkcji do PHP, anonimowych funkcji i przestrzeni nazw über alles
  • nowsze wersje PHP są znacznie szybsze . PHP jest darmowe. Aktualizacja jest bezpłatna. Po co używać wolniejszej, niepewnej wersji, jeśli można użyć szybszej, bezpieczniejszej wersji za darmo?

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:

namespace GM\WPSE\Example;

class AdminStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Klasa frontonu:

namespace GM\WPSE\Example;

class FrontStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Interfejs narzędzi:

namespace GM\WPSE\Example;

interface ToolsInterface {

   function doSomething();

}

I klasa Narzędzia, używana przez pozostałe dwa:

namespace GM\WPSE\Example;

class Tools implements ToolsInterface {

   function doSomething() {
      return 'done';
   }

}

Po tych zajęciach mogę utworzyć ich instancję za pomocą odpowiednich haków. Coś jak:

require_once plugin_dir_path( __FILE__ ) . 'src/ToolsInterface.php';
require_once plugin_dir_path( __FILE__ ) . 'src/Tools.php';

add_action( 'admin_init', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/AdminStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $admin_stuff; // this is not ideal, reason is explained below
   $admin_stuff = new GM\WPSE\Example\AdminStuff( $tools ); 
} );

add_action( 'template_redirect', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/FrontStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $front_stuff; // this is not ideal, reason is explained below
   $front_stuff = new GM\WPSE\Example\FrontStuff( $tools );    
} );

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.

ToolsKlasa 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 AdminStuffi FrontStuffklas używać typów parametrów zadeklarować potrzebują klasy, która implementuje ToolsInterface.

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 globaltysią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 .

public static function instance() {

  if ( is_null( self::$instance ) ) {
    self::$instance = new self;
  }

  return self::$instance;
}

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:

namespace GM\WPSE\Example;

class Registry {

   private $storage = array();

   function add( $id, $class ) {
     $this->storage[$id] = $class;
   }

   function get( $id ) {
      return array_key_exists( $id, $this->storage ) ? $this->storage[$id] : NULL;
   }

}

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:

global $registry;

if ( is_null( $registry->get( 'tools' ) ) ) {
  $tools = new GM\WPSE\Example\Tools;
  $registry->add( 'tools', $tools );
}

if ( is_null( $registry->get( 'front' ) ) ) {
  $front_stuff = new GM\WPSE\Example\FrontStuff( $registry->get( 'tools' ) );    
  $registry->add( 'front', front_stuff );
}

add_action( 'wp', array( $registry->get( 'front' ), 'wp' ) );

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ą:

function gm_wpse_example_registry() {
  static $registry = NULL;
  if ( is_null( $registry ) ) {
    $registry = new GM\WPSE\Example\Registry;
  }
  return $registry;
}

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:

$registry = new GM\WPSE\Example\Registry;

add_filter( 'gm_wpse_example_registry', function() use( $registry ) {
  return $registry;
} );

Po tym wszystkim potrzebny jest rejestr:

$registry = apply_filters( 'gm_wpse_example_registry', NULL );

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.


1
Dodatkowa uwaga, że ​​PHP 5.3 to także koniec życia. Odpowiedzialny gospodarz zaoferuje co najmniej 5,4 jako opcję, jeśli nie domyślną
Tom J Nowell

2
„Od 14 sierpnia 2014 r. PHP 5.3 dobiegł końca. Na pewno jest martwy”. Czy pierwszy wiersz w „PHP 5.2 jest dla zombie” @TomJNowell
gmazzap

3
Zastanawiam się, jak wyglądałoby wskazanie „wielu rzeczy” ? ;-)
MikeSchinkel,

Starając się unikać zmiennych globalnych, podoba mi się wzorzec rejestru z funkcją i zmienną statyczną. Przy pierwszym wywołaniu funkcja utworzy instancję rejestru, a przy kolejnych wywołaniach po prostu ją zwróci.
Michael Ecklund,

10

Używam następującej struktury:

Prefix_Example_Plugin::on_load();

/**
 * Example of initial class-based plugin load.
 */
class Prefix_Example_Plugin {

    /**
     * Hooks init (nothing else) and calls things that need to run right away.
     */
    static function on_load() {

        // if needed kill switch goes here (if disable constant defined then return)

        add_action( 'init', array( __CLASS__, 'init' ) );
    }

    /**
     * Further hooks setup, loading files, etc.
     *
     * Note that for hooked methods name equals hook (when possible).
     */
    static function init(  ) {


    }
}

Uwagi:

  • określił miejsce dla rzeczy, które muszą od razu uciec
  • wyłączanie / zastępowanie poprawek jest łatwe (odblokuj jedną initmetodę)
  • Nie sądzę, że kiedykolwiek użyłem / potrzebowałem obiektu klasy wtyczek - wymaga śledzenia, itp .; to jest naprawdę fałszywa przestrzeń nazw według celu, a nie OOP (przez większość czasu)

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.


3
Wiem, że ludzie znający się na testowaniu jednostkowym naprawdę nie lubią rozwiązań statycznych / singletonowych. Myślę, że jeśli w pełni rozumiesz, co próbujesz osiągnąć za pomocą metody statycznej i przynajmniej wiesz, jakie są tego konsekwencje, to w zupełności możesz zastosować takie metody. Dobre tematy na ten temat na Stack Overflow
Adam

To sprawiło, że naprawdę pomyślałem. Po co więc korzystać z klas, a nie wracać do prostych funkcji z prefiksem. Czy robimy to tylko po to, aby mieć czystsze nazwy funkcji / metod? Mam na myśli ich zagnieżdżenie za pomocą „statycznego” b4, czy jest to o wiele bardziej czytelne? Szansa na konflikt nazw jest mniej więcej taka sama jak w przypadku nazwy pojedynczej klasy, jeśli używasz prefiksów propperów, czy czegoś mi brakuje?
James Mitch

1
@JamesMitch tak, metody całkowicie statyczne to w większości tylko funkcje z fałszywą przestrzenią nazw stosowaną w WP. Jednak nawet w tym przypadku klasy mają pewne zalety w porównaniu z funkcjami czystymi, takimi jak automatyczne ładowanie i dziedziczenie. Ostatnio przechodzę od metod statycznych w kierunku rzeczywistych obiektów utworzonych za pomocą kontenera wstrzykiwania zależności.
Rarst

3

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_scriptshaku.

Jeśli chcesz zadzwonić po functions.phpzał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.


Fajne dzięki za to, przypuszczam, że są dwa punkty do powyższego pytania. Drugim jest to, czy __construct jest odpowiedni lub czy init () jest lepszym sposobem na zainicjowanie klasy.
kalpaitch

1
Cóż, wybrałbym 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.
Tim S.

0

Wiem, że to ma kilka lat, ale tymczasem php 5.3 obsługuje anonimowe metody , więc wymyśliłem:

add_action( 'plugins_loaded', function() { new My_Plugin(); } );

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.