Czy wszystkie wtyczki powinny być zawarte w klasie?


28

Czy podczas opracowywania wtyczki funkcje powinny być zgrupowane w klasę, aby uniknąć konfliktów przestrzeni nazw?

Czy używanie klas powoduje zwiększenie wydajności PHP?

Jeśli występuje błąd wydajności, czy zamiast tego nazwy funkcji powinny być wstępnie ustawione?


8
Prawdopodobnie więcej pytań PHP niż WordPress, sprawdź, czy to pytanie Stackoverflow odpowiednio rozwiązuje twoje pytanie.
t31os

Odpowiedzi:


24

Czy podczas opracowywania wtyczki funkcje powinny być zgrupowane w klasę, aby uniknąć konfliktów przestrzeni nazw?

Tak, ale to tylko jeden z drobnych argumentów. W rzeczywistości nie jest to „prawdziwa” natura klasy w OOAD .

Czy używanie klas powoduje zwiększenie wydajności PHP?

Nie, szczególnie. Zły projekt i / lub źle napisany kod lub wcześniejsza optymalizacja powodują znacznie więcej problemów z wydajnością niż rzeczywiste funkcje językowe.

Jeśli występuje błąd wydajności, czy zamiast tego nazwy funkcji powinny być wstępnie ustawione?

Jak napisano, nie ma wydajności. Źle napisany kod będzie bardziej uderzeniem w wydajność niż dobry napisany kod, który zawiera więcej wierszy kodu, ale nie zmusza cię do robienia złych rzeczy.


Dolna linia:

Możesz inaczej używać klas dla wtyczek. Możesz po prostu ich użyć, aby mieć jakąś przestrzeń nazw i użyć ich „tylko” dla funkcji globalnych. Najbardziej bezpośrednią formą tego są funkcje klasy statycznej, poniższy przykład kodu pokazuje zarówno funkcje globalne, a następnie funkcje globalnej klasy statycznej:

/* global function */
function myplug_hook()
{
}

add_filter('the_hook', 'myplug_hook');


/* global static function */
class myplug
{
    public static function hook()
    {
    }
}

add_filter('the_hook', 'myplug::hook');

To tylko mały przykład pokazujący, że musisz wpisać więcej dla pojedynczego haka. Dodatkowo pokazuje, jak działa przestrzeń nazw: Możesz łatwiej zastąpić nazwę pojedynczej klasy, aby zmienić nazwę wszystkich funkcji statycznych, a następnie wyszukać i zastąpić, myplug::co może być trudniejsze z myplug_powodu fałszywych trafień. Ale ostatecznie nie ma dużej różnicy.

Kluczową kwestią jest: statyczne funkcje klasy Dokumenty nie są tak naprawdę niczym więcej niż funkcje globalne Dokumenty .

I ten przykład pokazuje również: Przestrzeń nazw jest w porządku, ale w przypadku worpdress przestaje ona używać haczyków: Funkcja wywołania zwrotnego jest zakodowana, dlatego korzyść z przestrzeni nazw przy użyciu klasy (jedno miejsce dla nazwy podstawowej, nazwa klasy) nie pomoc w interweniowaniu kodu za pomocą wordpress dla nazw haków.

Prawdziwa korzyść zaczyna się od użycia rzeczywistych instancji klasy i funkcji niestatycznych. Ma to tę zaletę, że możesz zacząć korzystać z zasad OO i usprawnić swój kod. Funkcje klasy statycznej są bardziej problemem niż faktycznym rozwiązaniem.

Zatem to coś więcej niż cukier syntaktyczny.

Kluczową kwestią jest: Zrób coś, co pomoże Ci napisać kod, z którym możesz łatwo sobie poradzić i utrzymać. Nie przeceniaj wydajności, to częsty błąd. Ważniejsze jest to, że piszesz kod, który jest łatwy do odczytania i zrozumienia, i robi to, czego potrzebujesz. Być może to pytanie i odpowiedź są pomocne w celu uzyskania większego obrazu w tym kontekście: Multiple Custom Metabox Help .

Jednym z powszechnych podejść, jakie stosuję nawet w przypadku mniejszych wtyczek, jest używanie statycznej funkcji pomocniczej do tworzenia instancji wtyczki, a reszta znajduje się wtedy w instancji wtyczki. Pomaga to w enkapsulacji głównej logiki wtyczek i korzysta z przestrzeni nazw z hakami, a także że członkowie prywatni mogą być ponownie wykorzystywani między hakami, co nie jest możliwe przy standardowych funkcjach globalnych. Poniższy przykład kodu pokazuje wzorzec:

<?php
/** Plugin Headers ... */

return MyPlugin::bootstrap(); 

class MyPlugin
{
    /** @var MyPlugin */
    static $instance;
    static public function bootstrap() {
        if (NULL === self::$instance) {
            self::$instance = new __CLASS__;
        }
        return self::$instance;
    }
    # ...
}

Jest to typowy wzorzec, którego używam dla podstawowego pliku wtyczki. Klasa wtyczek z jednej strony reprezentuje wtyczkę do WordPressa, az drugiej strony pozwala zacząć używać paradygmatów obiektowych dla własnego kodu, który może być całkowicie zorientowany obiektowo (ale nie musi). To rodzaj kontrolera, który współpracuje z całym interfejsem API wordpress jako żądanie (żądania).

Jak pokazuje przykład, zostanie utworzone wystąpienie wtyczki. Umożliwia to korzystanie ze znanych wspólnych elementów, takich jak Constructor Docs ( __construct), w celu zainicjowania właściwej wtyczki:

# ...
class MyPlugin
{
    # ...
    public function __construct()
    {
        add_filter('the_hook', array($this, 'hook'));
    }

    public function hook()
    {
    }
    # ...
}

W czasie, gdy hak jest zarejestrowany, to obiekt już korzyści z niego za projektowanie wtyczki: pan przestał twardym kodu rzeczywistą funkcję haka przed Wtyczka beton classname . Jest to możliwe ze względu na powiązanie klasy z instancją obiektu dla wywołania zwrotnego. Brzmi skomplikowanie, mówiąc tylko: $this to wtyczka. Może być stosowany w wywołaniach zwrotnych przechwytujących, porównaj metody rejestracji jako klasy wywołania zwrotne .

Ten wzór pozwala na łatwiejszy interfejs z wordpress: wtrysk jest zredukowany do nazw haków i dostarczanych przez nie danych. Następnie możesz zacząć wdrażać bezpośrednio w tej klasie wtyczek lub przefakturować implementację, aby wstawić kod tylko do klasy wtyczek, która jest absolutnym minimum do zdefiniowania interfejsu wtyczek przed WordPressem, ale z ogólną logiką pomiń worpdress. Tutaj zaczyna się zabawa i najprawdopodobniej to, co każdy autor wtyczki chce osiągnąć na dłuższą metę.

Więc nie programuj z worpdress, ale przeciwko niemu. Ponieważ worpdress jest dość elastyczny, nie ma wspólnego ani łatwego do opisania interfejsu, przeciwko któremu program mógłby zostać użyty. Podstawowa klasa wtyczek może przejąć tę rolę, zapewniając większą elastyczność dla własnego kodu, co doprowadzi do łatwiejszego kodu i lepszej wydajności.

Tak więc odstępy między nazwami to nie tylko korzyść. Najlepsza propozycja, jaką mogę dać, to: Spróbuj sam. Nie stracisz wiele, tylko nowe rzeczy do odkrycia.

Najprawdopodobniej zauważysz różnice po przejściu kilku poważniejszych aktualizacji Wordpress przy jednoczesnym zachowaniu kompatybilności wtyczki.

Uwaga : jeśli Twoja wtyczka bezpośrednio integruje się z wordpress, aby wykonać zadanie, korzystanie z jednej lub dwóch funkcji publicznych może Ci bardziej odpowiadać. Wybierz odpowiednie narzędzie do pracy.


1
Jeśli funkcje klasy statycznej tak naprawdę nie różnią się od funkcji globalnych, a twoim celem jest zapobieganie konfliktom przestrzeni nazw, naprawdę nie zrozumiałem (jeszcze) konieczności przejścia na pisanie wtyczek jako klas. Poza tym jestem zdezorientowany twoją funkcją ładowania pomocnika. Dlaczego nie zadeklarować nowego obiektu jako $ new_object = new MyClass () ;?
AlxVallejo 30.12.12

@AlxVallejo: W przypadku samej przestrzeni nazw nie ma prawdziwej konieczności (jak napisałem w odpowiedzi, metody klas statycznych są prawie takie same jak funkcje globalne). Możesz więc zrobić własną przestrzeń nazw (tj. Rodzaj przestrzeni nazw wcześniejszej niż PHP 5.3). Więc doskonale to zauważyłeś. Podobnie z statyczną funkcją ładowania początkowego: technicznie nie jest to konieczne, proste return $myPlugin = new MyPlugin(); też. Jednak dla większego obrazu prosty nowy może nie wystarczyć, porównaj wtyczkę WordPress: Jak uniknąć „ciasnego połączenia”? .
hakre

9

Zestaw funkcji VS klasy


Wydajność

Ogólne: Afaik, nie ma różnicy w „wydajności” między klasami i zestawami funkcji.

Szczegół:

  • Jest duża różnica, jeśli pytasz function_exists()kontra class_exists()jak zwykle masz wiele funkcji (~ 1.800 (?) W rdzeniu wp) w porównaniu do klas (~ 100 (?) W rdzeniu wp). Tak więc uczynienie rzeczy „podłączalnymi” i dlatego kwestionowanie istnienia jest różnicą w czasie wykonania.
  • Klasy oferują jedną wielką przewagę nad zestawami funkcji: można znacznie łatwiej uniknąć wywoływania go na żądanie, gdy nie jest potrzebne, a następnie z funkcjami. Musisz tylko przeprowadzić kontrolę warunkową dla klasy, a nie dla każdej funkcji. Jeśli więc nie potrzebujesz go przy każdym ładowaniu strony i możesz uniknąć wywoływania wielu instrukcji if / else, funkcja „działa lepiej”.

Architektura - jak działają rzeczy:

zestaw funkcji: Ogólnie, funkcje są wykonywane w wierszu, który nazywasz. Więc za każdym razem, gdy dzwonisz, musisz napisać to jeszcze raz, jeśli musisz zadzwonić więcej niż raz.

Klasa: Istnieją różne aproaches do klas. Klasa najbliższa zestawowi funkcji to klasa „fabryczna” ( wikipedia / google ). Imo jest prawie taki sam jak zestaw funkcji, ale jest zamknięty w klasie. Ale są też inne „typy” klas. Możesz na przykład napisać klasę abstrakcyjną lub klasę nadrzędną, którą rozszerzasz za pomocą klasy podrzędnej. W przykładzie ze świata rzeczywistego: Załóżmy, że masz klasę, która tworzy statyczne pola tekstowe. W swojej __construct()funkcji masz zestaw scenariuszy takich jak „left_column”, „right_column” i „footer_field”. Następnie wywołujesz coś w rodzaju $text_field = new TextFieldClass();instancji klasy. A później po prostu dzwonisz $text_field->add( $case => 'left_column', 'case' => 'foo text' );i$text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Następnie wszystkie warunki warunkowe i inne zostały już wykonane podczas tworzenia instancji klasy i tylko dwie funkcje klasy byłyby wywoływane podczas tworzenia pól tekstowych. W tym szenario mogłeś zaoszczędzić kilka ms czasu wykonania.


Osobista opinia

Jeśli mądrze piszesz swoje zajęcia, będziesz miał niewielką przewagę pod względem wydajności. Ale będziesz miał dobrze zorganizowaną strukturę do pracy. Jak dotąd nic spektakularnego. Ale jeśli wziąć pod uwagę następujące „podzielone” przypadki użycia dla klas i funkcji w wtyczki, a następnie dostaniesz mój ostateczny punkt: klasa jest wewnętrzne, funkcje API . Tak długo, jak będziesz oferować API tylko poprzez funkcje publiczne (które następnie wywołują klasy lub funkcje klasowe), będziesz po stronie zapisywania, rozwijając swoją wtyczkę dalej. Osiągnąłeś swobodę zmiany wewnętrznej struktury, a nawet możliwości wtyczki bez wpływu na użytkowników w dowolnym miejscu i czasie.

Przykład:

// construction of object
if ( ! class_exists( 'WPSE_HelloWorld' ) )
{

class WPSE_HelloWorld
{
    function __construct( $args = array( 'text', 'html', 'echo' ) )
    {
        // call your object building procedures here
        $this->hello_world( 'text', 'html', 'echo' );
    }

    function hello_world( 'text', 'html', 'echo' )
    {
        $start_el = '<{$html}>';
        $end_el = '</{$html}>';
        if ( $echo )
        {
            return print "{$start_el}{$some}{$end_el}";
        }

        return "{$start_el}{$some}{$end_el}";
    }
} // END Class 

}

// API: public functions
function the_hello_world( $args( 'echo' => true ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

function get_hello_world( array( $args( 'echo' => false) ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

// then you can call it like get_the_title() or the_title(), which you know from the WP API:
// 'echo' is set to false per default:
$some_var = get_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *returns* "<strong>hello reader</strong>"

// 'echo' is set to true per default:
the_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *prints/echos* "<strong>hello reader</strong>"

Uwaga: Przeczytaj również link @ t310s opublikowany w komentarzu do Q.


Ciekawe, dlaczego spodziewasz się, że Twój plik wtyczki zostanie dołączony do WordPressa więcej niż jeden raz?
hakre

@hakre Gdzie dokładnie to powiedziałem? płacz, bardzo zmęczona mamą.
kaiser

1
@kaiser, zakładam, że @hakre odnosi się do if( ! class_exists )linii, którą masz na początku?
jjeaton

1
@hakre Zakładam, że @kaiser wykonuje class_existssprawdzenie nie dlatego, że można go dołączyć więcej niż jeden raz, ale aby uniknąć konfliktu z inną klasą?
Michał Mau,

Tak, zastanawiałem się nad klasami.
hakre

4

Jest to czysto stylistyczny wybór autora wtyczki. Nie ma prawdziwej różnicy pod względem prędkości.


1

Klasy zwykle nie oferują żadnych korzyści pod względem wydajności, ale bardzo rzadko mają również negatywne skutki. Ich prawdziwą zaletą jest zwiększenie przejrzystości kodu i unikanie konfliktów przestrzeni nazw.


Jednak, jak wspomniano @hakre, konflikty przestrzeni nazw tak naprawdę nie różnią się w przypadku używania prefiksów funkcji globalnych. Kod „oczyszczający” i zapobiegający konfliktom przestrzeni nazw jest w tym przypadku synonimem, nie?
AlxVallejo

@AlxVallejo tak myślę :)
Bainternet 30.12.12

0

W większości przypadków, jeśli korzystasz z funkcji, wstawiasz nazwę wtyczki do nazwy każdej funkcji, więc skutecznie powielisz tę nazwę kilkanaście razy, jeśli wtyczka ma tuzin funkcji, co jest trochę uciążliwe .

W przypadku klas prawdopodobnie po prostu będziesz mieć nazwę wtyczki w nazwie klasy.

Dodatkowo możesz użyć dziedziczenia lub innych konstrukcji oo, aby zaimplementować zachowania w bardzo czysty sposób. Oto ex:

class animalplugin{
  //plugin functions...
  function talk(){print "animalnoise";}
}
class animalplugin_with_cat_mods extends abcplugin{
  //cat functions overrides
  function talk(){print "meow";}
}
if (iscat()){
  new animalplugin_with_cat_mods();
} else {
  new animalplugin();
}
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.