Il modo migliore per iniziare una lezione in un plugin WP?


90

Ho creato un plug-in e, ovviamente, essendo io, volevo seguire un approccio OO gradevole. Ora quello che ho fatto è creare questa classe e poi appena sotto creare un'istanza di questa classe:

class ClassName {

    public function __construct(){

    }
}

$class_instance = new ClassName();  

Suppongo che ci sia un modo più WP per avviare questa classe, e poi mi sono imbattuto in persone che dicevano che preferivano avere una init()funzione piuttosto che una __construct(). E allo stesso modo ho trovato alcune persone usando il seguente hook:

class ClassName {

    public function init(){

    }
}
add_action( 'load-plugins.php', array( 'ClassName', 'init' ) );

Qual è generalmente il modo migliore per creare un'istanza di classe WP sotto carico e utilizzarla come variabile globalmente accessibile?

NOTA: Come punto laterale interessante, ho notato che mentre register_activation_hook()può essere chiamato dall'interno __construct, non può essere chiamato dall'interno init()usando il secondo esempio. Forse qualcuno potrebbe illuminarmi su questo punto.

Modifica: grazie per tutte le risposte, c'è chiaramente un bel po 'di dibattito su come gestire l'inizializzazione all'interno della classe stessa, ma penso che ci sia generalmente un buon consenso che add_action( 'plugins_loaded', ...);sia il modo migliore per iniziare davvero ...

Modifica: solo per confondere le cose, ho visto anche questo usato (anche se non userei questo metodo da solo perché trasformare una classe piacevolmente OO in una funzione sembra annullarne il punto):

// Start up this plugin
add_action( 'init', 'ClassName' );
function ClassName() {
    global $class_name;
    $class_name = new ClassName();
}

1
Per quanto riguarda l'ultima modifica, se è contenuta nello stesso file plugin della classe, diventa in qualche modo inutile. Puoi anche creare un'istanza della classe secondo il metodo che descrivo. Anche se si trova in un file separato, è ancora piuttosto inutile. L'unico caso d'uso che posso vedere è se si desidera creare una funzione wrapper che consenta di creare un'istanza di una classe al di fuori dei file del plug-in, all'interno di temi e così via. Anche così, dovrei chiedermi quale logica ci sia dietro perché un uso corretto di condizionali e hook dovrebbe consentire un controllo accurato sull'istanza, permettendoti di concentrarti sull'uso del plugin.
Adam,

Sono un po 'd'accordo con questo, ma ho pensato che valesse la pena inserirlo come l'ho trovato in un paio di plugin WP.
Kalpaitch,

Risposte:


60

Bella domanda, ci sono una serie di approcci e dipende da cosa vuoi ottenere.

Lo faccio spesso;

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

Un esempio più approfondito che è emerso come risultato di alcune recenti discussioni su questo stesso argomento all'interno della chat room può essere visto in questa sintesi dal membro WPSE toscho .

L'approccio costruttore vuoto.

Ecco un estratto di vantaggi / svantaggi tratto dall'essenza di cui sopra che esemplifica pienamente l'approccio del costruttore vuoto.

  • vantaggi:

    • I test unitari possono creare nuove istanze senza attivare automaticamente alcun hook. No Singleton.

    • Nessuna variabile globale necessaria.

    • Chiunque desideri lavorare con l'istanza del plug-in può semplicemente chiamare T5_Plugin_Class_Demo :: get_instance ().

    • Facile da disattivare.

    • OOP ancora reale: nessun metodo di lavoro è statico.

  • Svantaggio:

    • Forse più difficile da leggere?

Lo svantaggio secondo me è debole in quello che è il motivo per cui dovrebbe essere il mio approccio preferito, tuttavia non l'unico che uso. In effetti, molti altri pesi pesanti entreranno senza dubbio in questo argomento con la loro opinione sull'argomento a breve perché ci sono alcune buone opinioni su questo argomento che dovrebbero essere espresse.


nota: ho bisogno di trovare l'esempio essenziale di toscho che ha attraversato 3 o 4 confronti su come creare un'istanza di una classe all'interno di un plugin che ha esaminato i pro e i contro di ciascuno, che il link sopra era il modo preferito per farlo, ma gli altri esempi offrono un buon contrasto con questo argomento. Spero che toscho lo abbia ancora in archivio.

Nota: la risposta WPSE a questo argomento con esempi e confronti pertinenti. Anche la migliore soluzione per esempio una classe in 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!
    }
}

quale sarebbe la differenza tra add_action ('plugins_loaded', ...); e add_action ('load-plugins.php', ...); L'esempio che ho preso ha usato quest'ultimo
Kalpaitch il

1
Da quello che capisco load-plugins.php, sebbene funzioni, è associato al update.phpfile core e non fa parte delle solite azioni predefinite su cui fare affidamento quando si tratta della sequenza di eventi che si attivano durante l'inizializzazione e per questo motivo preferisco per usare quei ganci che si applicano, in questo caso plugins_loaded. Questo è ciò a cui spesso mi riferisco come un'istantanea rapida di ciò che accade quando si fa riferimento ad Action . La mia spiegazione non è completa nella sua interezza.
Adam,

4
Mi piace questo approccio singleton. Tuttavia, metto in dubbio l'utilizzo di plugins_loaded come hook di azione di inizializzazione. Questo hook è pensato per essere eseguito dopo che tutti i plugin sono stati caricati. Collegandoti dopo, stai in qualche modo dirottando quell'hook e potresti divertirti in conflitti o problemi di sequenza di avvio con altri plugin o temi che si agganciano a plugins_loaded. Non mi aggancerei ad alcuna azione per eseguire il metodo di inizializzazione. L'architettura del plug-in è stata progettata per essere eseguita in linea, non su un'azione.
Tom Auger,

2
Nota che se lo usi register_activation_hook()devi chiamare quella funzione prima che l' plugins_loadedazione sia stata attivata.
Geert,

1
Come ulteriori informazioni, vedere questo post di @mikeschinkel e il dicuss nei commenti. hardcorewp.com/2012/…
bueltge

79

Arrivando qui esattamente 2 anni dopo la domanda iniziale, ci sono alcune cose che voglio sottolineare. (Non chiedermi di sottolineare molte cose , mai).

Gancio corretto

Per creare un'istanza di una classe di plug-in, è necessario utilizzare l'hook corretto . Non esiste una regola generale per cui lo sia, perché dipende da ciò che fa la classe.

L'uso di un hook molto precoce come "plugins_loaded"spesso non ha senso perché un hook del genere viene attivato per richieste di amministrazione, frontend e AJAX, ma molto spesso un hook successivo è molto meglio perché consente di istanziare le classi di plugin solo quando necessario.

Ad esempio una classe che fa cose per i template può essere istanziata "template_redirect".

In generale è molto raro che una classe debba essere istanziata prima che "wp_loaded"sia stata licenziata.

Nessuna classe di Dio

Soprattutto le classi usate come esempi nelle risposte più vecchie usano una classe chiamata like "Prefix_Example_Plugin"o "My_Plugin"... Ciò indica che probabilmente esiste una classe principale per il plugin.

Bene, a meno che un plug-in non sia creato da una singola classe (nel qual caso nominarlo con il nome del plug-in è assolutamente ragionevole), per creare una classe che gestisca l'intero plug-in (ad esempio aggiungendo tutti gli hook necessari a un plug-in o creando un'istanza di tutte le altre classi di plug-in ) può essere considerata una cattiva pratica, come esempio di un oggetto divino .

Nel codice di programmazione orientata agli oggetti dovrebbe tendere ad essere SOLIDO dove la "S" sta per "Principio di responsabilità singola" .

Significa che ogni classe dovrebbe fare una sola cosa. Nello sviluppo di plug-in WordPress significa che gli sviluppatori dovrebbero evitare di utilizzare un singolo hook per creare un'istanza di una classe principale di plug-in, ma diversi hook dovrebbero essere utilizzati per creare un'istanza di classi diverse, in base alla responsabilità della classe.

Evitare ganci nel costruttore

Questo argomento è stato introdotto in altre risposte qui, tuttavia voglio sottolineare questo concetto e collegare quest'altra risposta in cui è stata spiegata in modo abbastanza ampio nell'ambito del test unitario.

Quasi 2015: PHP 5.2 è per gli zombi

Dal 14 agosto 2014, PHP 5.3 ha raggiunto la fine della sua vita . È decisamente morto. PHP 5.4 sarà supportato per tutto il 2015, significa che per un altro anno al momento sto scrivendo.

Tuttavia, WordPress supporta ancora PHP 5.2, ma nessuno dovrebbe scrivere una singola riga di codice che supporti quella versione, soprattutto se il codice è OOP.

Ci sono diversi motivi:

  • PHP 5.2 è morto molto tempo fa, non sono state rilasciate correzioni di sicurezza, il che significa che non è sicuro
  • PHP 5.3 ha aggiunto un sacco di funzioni di PHP, funzioni anonime e spazi dei nomi über alles
  • le nuove versioni di PHP sono molto più veloci . PHP è gratuito. L'aggiornamento è gratuito. Perché utilizzare una versione più lenta e insicura se è possibile utilizzarne una più veloce e sicura gratuitamente?

Se non vuoi usare il codice PHP 5.4+, usa almeno 5.3+

Esempio

A questo punto è tempo di rivedere le risposte più vecchie in base a ciò che ho detto fino a qui.

Una volta che non ci dobbiamo più preoccupare di 5.2, possiamo e dovremmo usare gli spazi dei nomi.

Per meglio spiegare il principio della responsabilità singola, il mio esempio utilizzerà 3 classi, una che fa qualcosa sul frontend, una sul backend e una terza usata in entrambi i casi.

Classe amministratore:

namespace GM\WPSE\Example;

class AdminStuff {

   private $tools;

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

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

}

Classe frontend:

namespace GM\WPSE\Example;

class FrontStuff {

   private $tools;

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

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

}

Interfaccia strumenti:

namespace GM\WPSE\Example;

interface ToolsInterface {

   function doSomething();

}

E una classe di strumenti, utilizzata dalle altre due:

namespace GM\WPSE\Example;

class Tools implements ToolsInterface {

   function doSomething() {
      return 'done';
   }

}

Avendo queste classi, posso istanziarle usando gli hook appropriati. Qualcosa di simile a:

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

Dipendenza Inversione e Dipendenza Iniezione

Nell'esempio sopra ho usato spazi dei nomi e funzioni anonime per creare un'istanza di classi diverse con diversi hook, mettendo in pratica ciò che ho detto sopra.

Nota come gli spazi dei nomi consentono di creare classi denominate senza alcun prefisso.

Ho applicato un altro concetto che è stato indirettamente menzionato sopra: Iniezione di dipendenza , è un metodo per applicare il principio di inversione di dipendenza , la "D" nell'acronimo SOLID.

La Toolsclasse viene "iniettata" nelle altre due classi quando vengono istanziate, quindi in questo modo è possibile separare la responsabilità.

Inoltre, AdminStuffe le FrontStuffclassi usano il tipo hinting per dichiarare che hanno bisogno di una classe che implementa ToolsInterface.

In questo modo noi stessi o gli utenti che utilizzano il nostro codice possono utilizzare diverse implementazioni della stessa interfaccia, rendendo il nostro codice non accoppiato a una classe concreta ma a un'astrazione: questo è esattamente ciò che riguarda il principio di inversione di dipendenza.

Tuttavia, l'esempio sopra può essere ulteriormente migliorato. Vediamo come.

Autoloader

Un buon modo per scrivere codice OOP meglio leggibile è non mescolare la definizione dei tipi (Interfacce, Classi) con altri codici e mettere ogni tipo nel proprio file.

Questa regola è anche uno degli standard di codifica PSR-1 1 .

Tuttavia, prima di poter utilizzare una classe, è necessario richiedere il file che la contiene.

Questo può essere travolgente, ma PHP fornisce funzioni di utilità per caricare automaticamente una classe quando è necessario, usando un callback che carica un file in base al suo nome.

L'uso degli spazi dei nomi diventa molto semplice, perché ora è possibile abbinare la struttura delle cartelle alla struttura dello spazio dei nomi.

Questo non è solo possibile, ma è anche un altro standard PSR (o meglio 2: PSR-0 ora deprecato e PSR-4 ).

Seguendo tali standard è possibile utilizzare diversi strumenti che gestiscono il caricamento automatico, senza dover codificare un caricatore automatico personalizzato.

Devo dire che gli standard di codifica di WordPress hanno regole diverse per la denominazione dei file.

Quindi quando scrivono codice per il core di WordPress, gli sviluppatori devono seguire le regole del WP, ma quando scrivono codice personalizzato è una scelta dello sviluppatore, ma usare lo standard PSR è più facile usare gli strumenti già scritti 2 .

Schemi di localizzazione di accesso globale, registro e servizi.

Uno dei maggiori problemi nell'istanza di classi di plugin in WordPress è come accedervi da varie parti del codice.

WordPress stesso utilizza l' approccio globale : le variabili vengono salvate in ambito globale, rendendole accessibili ovunque. Ogni sviluppatore WP digita la parola globalmigliaia di volte nella sua carriera.

Questo è anche l'approccio che ho usato per l'esempio sopra, ma è malvagio .

Questa risposta è già troppo lunga per permettermi di spiegare ulteriormente perché, ma leggere i primi risultati nella SERP per "variabili globali malvagie" è un buon punto di partenza.

Ma come è possibile evitare le variabili globali?

Esistono diversi modi.

Alcune delle risposte precedenti qui usano l' approccio dell'istanza statica .

public static function instance() {

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

  return self::$instance;
}

È facile e abbastanza bene, ma forza l'implementazione del modello per ogni classe a cui vogliamo accedere.

Inoltre, molte volte questo approccio apre la strada al problema della classe divina, perché gli sviluppatori rendono accessibile una classe principale usando questo metodo e quindi la usano per accedere a tutte le altre classi.

Ho già spiegato quanto sia cattiva una classe god, quindi l'approccio dell'istanza statica è un buon modo per andare quando un plugin deve solo rendere accessibili una o due classi.

Questo non significa che può essere utilizzato solo per plugin che hanno solo un paio di classi, infatti, quando il principio dell'iniezione di dipendenza viene usato correttamente, è possibile creare applicazioni piuttosto complesse senza la necessità di rendere accessibile a livello globale un gran numero di oggetti.

Tuttavia, a volte i plugin devono rendere accessibili alcune classi e in tal caso l'approccio dell'istanza statica è schiacciante.

Un altro possibile approccio consiste nell'utilizzare il modello di registro .

Questa è una sua implementazione molto semplice:

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

}

Utilizzando questa classe è possibile archiviare oggetti nell'oggetto Registro di sistema tramite un ID, quindi avere accesso a un registro è possibile avere accesso a tutti gli oggetti. Naturalmente quando un oggetto viene creato per la prima volta, deve essere aggiunto al registro.

Esempio:

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' ) );

L'esempio sopra chiarisce che per essere utile il registro deve essere accessibile a livello globale. Una variabile globale per l'unico registro non è molto male, tuttavia per i puristi non globali è possibile implementare l'approccio dell'istanza statica per un registro, o forse una funzione con una variabile statica:

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

La prima volta che viene chiamata la funzione, verrà creata un'istanza del registro, nelle chiamate successive verrà restituita.

Un altro metodo specifico di WordPress per rendere accessibile una classe a livello globale è la restituzione di un'istanza di oggetto da un filtro. Qualcosa come questo:

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

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

Dopodiché è necessario il registro ovunque:

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

Un altro modello che può essere utilizzato è il modello di localizzazione di servizio . È simile al modello di registro, ma i localizzatori di servizio vengono passati a varie classi mediante l'iniezione delle dipendenze.

Il problema principale con questo modello è che nasconde le dipendenze delle classi rendendo il codice più difficile da mantenere e leggere.

DI Containers

Indipendentemente dal metodo utilizzato per rendere accessibile a livello globale il registro o il localizzatore di servizi, gli oggetti devono essere archiviati lì e prima di essere archiviati devono essere istanziati.

In applicazioni complesse, dove ci sono molte classi e molte di esse hanno diverse dipendenze, la creazione di un'istanza di classi richiede molto codice, quindi aumenta la possibilità di bug: il codice che non esiste non può avere bug.

Negli ultimi anni sono apparse alcune librerie PHP che aiutano gli sviluppatori PHP a creare istanze e archiviare facilmente istanze di oggetti, risolvendo automaticamente le loro dipendenze.

Queste librerie sono note come contenitori di iniezione di dipendenza perché sono in grado di creare istanze di classi per risolvere dipendenze e anche di archiviare oggetti e restituirli quando necessario, agendo in modo simile a un oggetto del registro.

Di solito, quando si utilizzano contenitori DI, gli sviluppatori devono impostare le dipendenze per ogni classe dell'applicazione, e quindi la prima volta che una classe è necessaria nel codice viene istanziata con dipendenze appropriate e la stessa istanza viene restituita più volte sulle richieste successive .

Alcuni contenitori DI sono anche in grado di rilevare automaticamente dipendenze senza configurazione, ma utilizzando la riflessione PHP .

Alcuni noti contenitori DI sono:

e molti altri.

Voglio sottolineare che per i plugin semplici, che coinvolgono solo poche classi e che le classi non hanno molte dipendenze, probabilmente non vale la pena usare contenitori DI: il metodo dell'istanza statica o un registro accessibile globale sono buone soluzioni, ma per plugin complessi il vantaggio di un contenitore DI diventa evidente.

Naturalmente, anche gli oggetti contenitore DI devono essere accessibili per essere utilizzati nell'applicazione e a tale scopo è possibile utilizzare uno dei metodi visti sopra, variabile globale, variabile di istanza statica, oggetto di ritorno tramite filtro e così via.

Compositore

Usare un contenitore DI spesso significa usare un codice di terze parti. Al giorno d'oggi, in PHP, quando abbiamo bisogno di usare una libreria esterna (quindi non solo contenitori DI, ma qualsiasi codice che non fa parte dell'applicazione), il semplice scaricarlo e metterlo nella nostra cartella dell'applicazione non è considerato una buona pratica. Anche se siamo gli autori di quell'altro pezzo di codice.

Il disaccoppiamento di un codice applicazione da dipendenze esterne è indice di una migliore organizzazione, migliore affidabilità e migliore sanità mentale del codice.

Compositore , è lo standard di fatto nella comunità PHP per gestire le dipendenze PHP. Lontano da essere anche mainstream nella comunità WP, è uno strumento che ogni sviluppatore di PHP e WordPress dovrebbe almeno conoscere, se non usare.

Questa risposta è già a misura di libro per consentire ulteriori discussioni, e anche discutere di Composer qui è probabilmente fuori tema, è stato menzionato solo per completezza.

Per maggiori informazioni visita il sito di Composer e vale anche la pena dare una lettura a questo minisito a cura di @Rarst .


1 PSR sono norme standard PHP rilasciate dal PHP Framework Interop Group

2 Composer (una libreria che verrà menzionata in questa risposta) contiene tra l'altro anche un'utilità di caricamento automatico.


1
Una nota aggiuntiva, che PHP 5.3 è anche fine della vita. Un host responsabile offrirà almeno 5,4 come opzione se non un valore predefinito
Tom J Nowell

2
"Dal 14 agosto 2014, PHP 5.3 ha raggiunto la fine della sua vita. È sicuramente morto." È la prima riga in "PHP 5.2 is for zombies" @TomJNowell
gmazzap

3
Mi chiedo solo, come indicheresti "molte cose" ? ;-)
MikeSchinkel il

Nel tentativo di evitare le variabili globali, mi piace l'idea del modello di registro con funzione e variabile statica. La prima volta che viene chiamata la funzione, verrà creata un'istanza del registro, nelle chiamate successive verrà restituita.
Michael Ecklund l'

10

Uso la seguente struttura:

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(  ) {


    }
}

Appunti:

  • ha definito il luogo per le cose che devono scappare immediatamente
  • disabilitare / sovrascrivere per le modifiche è facile (sganciare un initmetodo)
  • Non credo di aver mai usato / necessario l'oggetto della classe plugin - richiede di tenerne traccia, ecc .; questo è davvero uno spazio dei nomi falso per scopo, non OOP (il più delle volte)

Disclaimer Non uso ancora i test unitari ( tante cose su Myplate ) e sento che statica può essere meno preferibile per loro. Fai le tue ricerche su questo se hai bisogno di testarlo.


3
So che le persone esperte nei test unitari non amano davvero le soluzioni statiche / singleton. Penso che se comprendi appieno ciò che stai tentando di ottenere utilizzando statico e almeno sei consapevole delle conseguenze di ciò, allora è perfettamente corretto implementare tali metodi. Buoni argomenti che lo circondano allo Stack Overflow
Adam,

Questo mi ha fatto davvero pensare. Quindi perché usare una classe allora e non solo tornare alle semplici funzioni con prefisso. Facciamo questo solo per avere nomi di funzioni / metodi più puliti? Voglio dire averli annidati con un "statico" b4, è molto più leggibile? La possibilità di avere un conflitto di nomi è quasi la stessa di un singolo nome di classe se usi prefissi di propper o mi sto perdendo qualcosa?
James Mitch,

1
@JamesMitch sì, i metodi completamente statici sono per lo più solo funzioni con spazio dei nomi falso usato in WP. Tuttavia le classi presentano alcuni vantaggi rispetto alle funzioni pure anche in questo caso, come il caricamento automatico e l'ereditarietà. Ultimamente mi sono spostato da metodi statici e verso oggetti istanziati reali organizzati dal contenitore di iniezione di dipendenza.
Rarst

3

Tutto dipende dalla funzionalità.

Una volta ho creato un plug-in che registrava gli script quando veniva chiamato il costruttore, quindi dovevo agganciarlo wp_enqueue_scriptsall'amo.

Se vuoi chiamarlo quando il tuo functions.phpfile è caricato, potresti anche creare un'istanza $class_instance = new ClassName();come hai menzionato.

Potresti prendere in considerazione la velocità e l'utilizzo della memoria. Non ne sono a conoscenza, ma posso immaginare che in alcuni casi ci siano hook non richiamati. Creando la tua istanza su quell'hook potresti risparmiare alcune risorse del server.


Bene grazie per quello, suppongo che ci siano anche due punti per la domanda sopra. L'altro è se __construct è adatto o se init () è un modo migliore per inizializzare la classe.
Kalpaitch,

1
Bene, sceglierei un init()metodo statico , quindi l'istanza della classe viene chiamata nell'ambito della classe anziché in un altro ambito in cui è possibile sovrascrivere le variabili esistenti.
Tim S.

0

So che ha un paio d'anni, ma nel frattempo php 5.3 supporta metodi anonimi , quindi ho pensato a questo:

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

e in qualche modo mi piace di più. Posso usare costruttori regolari e non ho bisogno di definire alcun metodo "init" o "on_load" che rovini le mie strutture OOP.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.