Come possono essere progettati i sisthemes di plugin in modo che non sprechino così tante risorse?

Sto cercando di creare un sistema di plugin di base come il tipo che si trova spesso in un CMS come WordPress. Si dispone di una cartella di plug-in che si collega all'operazione del sistema principale tramite notifiche di events utilizzando un model di progettazione Observer o Event .

Il problema è che il sistema non è in grado di sapere su quali events il plug-in vuole agire, quindi il sistema deve caricare ciascun plug-in per each richiesta di pagina solo per scoprire se quel plugin è effettivamente necessario a un certo punto. Inutile dire che ci sono un sacco di risorse sprecate proprio lì – nel caso di WordPress, che aggiunge fino a diversi MB di memory extra per each richiesta!

Ci sono modi alternativi per farlo?

Ad esempio, esiste un modo per caricare tutto questo una volta e quindi memorizzare nella cache i risultati in modo che il sistema sappia come caricare i plug-in in modo lazy? In altre parole, il sistema carica un file di configuration che specifica tutti gli events che il plug-in desidera colbind e quindi lo salva in APC o qualcosa per richieste future?

Se anche questo si comport male, allora forse c'è una speciale struttura di file che potrebbe essere usata per formulare ipotesi su quando alcuni plug-in non sono necessari per soddisfare la richiesta.

Ho uno strumento di gestione dei plug-in, ma l'ho usato solo con plug-in prevalentemente procedurali, e con tutti gli include di solito caricati contemporaneamente. Ma per un'API basata sugli events e per il caricamento lento, potrei immaginare di usare involucri poco profondi per la gestione dei plugin e ricorrere all'autoloading per le estensioni effettive.

<?php /** * api: whatever * version: 0.1 * title: plugin example * description: ... * config: <var name="cfg[pretty]" type="boolean" ...> * depends: otherplugin */ $plugins["title_event"] = "TitleEventClass"; $plugins["secondary"] = arrays("Class2", "callback"); ?> 

In questo esempio assumerei che l'API del plugin sia una list semplice. Questo script di esempio feature-plugin-123.php non farebbe altro che aggiungere a un arrays quando caricato. Quindi, anche se disponi di una dozzina di plug-in di funzionalità, si incorrebbero in un include_once aggiuntivo include_once tra ciascuno.

Ma l'API principale dell'applicazione / o del plugin potrebbe invece semplicemente istanziare le classi menzionate (o new $eventcb; per i call_user_func_arrays di call_user_func_arrays raw o call_user_func_arrays per i callback). Dove, a sua volta, scaricherà l'attività effettiva su un caricatore automatico. Quindi hai un sistema duale, in cui una parte gestisce la list, l'altra individua il codice reale.

In questo modo sto ancora immaginando un semplice config.php che elenca solo plug-in e impostazioni come questa:

 <?php include_once("user/feature-plugin-123.php"); include_once("user/otherplugin2.php"); include_once("user/wrapper-for-htmlpurifier.php"); $cfg["pretty"] = 1; 

Tenendo ancora presente che questi sono solo wrapper / script di dati, con la descrizione del plugin per la gestibilità. Si potrebbe anche usare una vera API register_even() e definire una function wrapper aggiuntiva in ciascuna. Ma elencare i nomi di class sembra l'opzione più semplice.

Lo strumento di gestione di cui sopra è un po 'arrugginito e brutto: http://milki.include-once.org/genericplugins/
Ma non è necessario se hai solo bisogno di una list (tabella sql) e nessuna gestione delle impostazioni. Quel sovraccarico è solo per il prettyprinting dei meta dati del plugin e per mantenere un config.php leggibile.

In conclusione:

spl_autoload() su include_path e un semplice event-> classname registry, uno script di wrapper ciascuno, semplicemente incluso tutto in una volta.

WordPress e altri sisthemes CMS sono pessimi esempi.

Quello che dobbiamo capire è che modulare, quasi sempre significa più pesante.

Lo schema migliore con cui ho mai lavorato per risolvere questa situazione è un plugin basato sulla class, con una convenzione di denominazione rigida che utilizza un caricatore automatico.

Pertanto, prima di utilizzare il plug-in, è necessario creare un'istanza o utilizzare funzioni statiche.

Puoi anche call il plugin come:

 <?php $thePlugin::method(); ?> 

per esempio:

 <?php spl_autoload_register('systemAutoload'); function systemAutoload($class) { $parts = explode('_',$class); switch($parts[1]) { case "Plugin": include("/plugins/{$parts[2]}/{$parts[2]}.php"); break; } // ... } ?> 

Per quanto riguarda gli events:

Devi registrare questi events staticamente per evitare di portrli dynamicmente.

Il database sarebbe il posto giusto per farlo. È ansible avere una tabella degli events e methods di installazione () e uninstall () nella class plugin per aggiungere events specifici o methods di associazione ad altri events. È una query di database e, se vuoi saperne di più, aggiungila a memcached o a un file ini flat.

Funziona bene per me. In questo modo sono riuscito a get un sistema pesante che consumava 8 MB per richiesta per passare a 1 MB, con lo stesso identico elenco di funzionalità, senza cache avanzata. Ora possiamo aggiungere più funzionalità e mantenere il sistema "pulito"

Spero possa aiutare

Vorrei salvare il nome della class del plugin insieme ai suoi events sottoscritti in un file di configuration e quindi salvare il file di configuration analizzato in APC, ad esempio. Quindi, quando viene triggersto un evento, il sistema può caricare le classi di plug-in appropriate secondo necessità.