Come strutturare un plugin
Questa non è una domanda su come costruire un plugin WordPress. Piuttosto, quali linee guida potrebbero essere applicate per organizzare l'architettura dei file di qualsiasi plugin.
Altri linguaggi di programmazione o librerie hanno modi molto controllati di organizzare directory e file. A volte questo è fastidioso e mette in evidenza la libertà che PHP offre, ma d'altra parte i plugin WordPress vengono assemblati in qualsiasi modo determinato dal loro autore.
Non esiste una risposta corretta, ma il mio obiettivo è perfezionare il modo in cui io e altri sviluppiamo i plugin per renderli più facili da analizzare per altri sviluppatori, più semplici da debuggare, più facili da navigare e possibilmente più efficienti.
La domanda finale: qual è secondo te il modo migliore per organizzare un plugin?
Di seguito sono riportate alcune strutture di esempio, ma non è assolutamente un elenco esaustivo. Sentiti libero di aggiungere i tuoi suggerimenti.
Struttura Predefinita
/wp-content
/plugins
/my-plugin
my-plugin.php
Metodo Model View Controller (MVC)
/wp-content
/plugins
/my-plugin
/controller
Controller.php
/model
Model.php
/view
view.php
my-plugin.php
Le tre parti di MVC:
- Il model interagisce con il database, interrogando e salvando i dati, e contiene la logica.
- Il controller contiene i template tag e le funzioni che la view utilizzerà.
- La view è responsabile di visualizzare i dati forniti dal model come costruito dal controller.
Metodo organizzato per tipo
/wp-content
/plugins
/my-plugin
/admin
admin.php
/assets
css/
images/
/classes
my-class.php
/lang
my-es_ES.mo
/templates
my-template.php
/widgets
my-widget.php
my-plugin.php
WordPress Plugin Boilerplate
Disponibile su Github
Basato sulle API dei Plugin, Standard di Codifica e Standard di Documentazione.
/wp-content
/plugins
/my-plugin
/admin
/css
/js
/partials
my-plugin-admin.php
/includes
my_plugin_activator.php
my_plugin_deactivator.php
my_plugin_i18n.php
my_plugin_loader.php
my_plugin.php
/languages
my_plugin.pot
/public
/css
/js
/partials
my-plugin-public.php
LICENSE.txt
README.txt
index.php
my-plugin.php
uninstall.php
Metodo organizzato liberamente
/wp-content
/plugins
/my-plugin
css/
images/
js/
my-admin.php
my-class.php
my-template.php
my-widget.php
my-plugin.php

Nota che i plugin sono tutti "controller" secondo gli standard di WordPress.
Dipende da cosa il plugin dovrebbe fare, ma in tutti i casi cercherei di separare il più possibile l'output a schermo dal codice PHP.
Ecco un modo semplice per farlo - prima, definisci una funzione che carica il template:
function my_plugin_load_template(array $_vars){
// non puoi lasciare che locate_template carichi il tuo template
// perché gli sviluppatori di WP si sono assicurati che non si possano passare
// variabili al tuo template :(
$_template = locate_template('my_plugin', false, false);
// usa quello predefinito se il tema non lo ha
if(!_$template)
$_template = 'views/template.php';
// caricalo
extract($_vars);
require $template;
}
Ora, se il plugin utilizza un widget per mostrare i dati:
class Your_Widget extends WP_Widget{
...
public function widget($args, $instance){
$title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
// questo widget mostra gli ultimi 5 "film"
$posts = new WP_Query(array('posts_per_page' => 5, 'post_type' => 'movie'));
if($title)
print $before_title . $title . $after_title;
// qui ci affidiamo al template per mostrare i dati a schermo
my_plugin_load_template(array(
// variabili che vuoi esporre nel template
'posts' => $posts,
));
print $before_widget;
}
...
}
Il template:
<?php while($posts->have_posts()): $posts->the_post(); ?>
<p><?php the_title(); ?></p>
<?php endwhile; ?>
File:
/plugins/my_plugin/plugin.php <-- solo hook
/plugins/my_plugin/widget.php <-- classe widget, se hai un widget
/themes/twentyten/my_plugin.php <-- template
/plugins/my_plugin/views/template.php <-- template di fallback
Dove mettere i tuoi CSS, JS, immagini, o come progettare il contenitore per gli hook è meno importante. È una questione di preferenze personali credo.

Dipende dal plugin. Questa è la mia struttura di base per quasi tutti i plugin:
my-plugin/
inc/
Qui vanno eventuali file PHP aggiuntivi specifici del plugin
lib/
Classi di libreria, css, js e altri file che utilizzo con molti
plugin vanno qui
css/
js/
images/
lang/
File di traduzione
my-plugin.php
readme.txt
Questo sarebbe qualcosa che andrebbe nella cartella lib
.
Se è un plugin particolarmente complesso, con molta funzionalità nell'area di amministrazione, aggiungerei una cartella admin
per contenere tutti quei file PHP. Se il plugin fa qualcosa come sostituire i file del tema inclusi, potrebbe esserci anche una cartella template
o theme
.
Quindi, una struttura di directory potrebbe essere così:
my-plugin/
inc/
lib/
admin/
templates/
css/
js/
images/
lang/
my-plugin.php
readme.txt

Includeresti anche i file css e js dell'amministratore nella cartella /admin? Quindi avendo un altro /css e /js all'interno di /admin?

IMHO, la strada più semplice, potente e gestibile è utilizzare una struttura MVC, e WP MVC è progettato per rendere molto semplice la scrittura di plugin MVC (anche se sono un po' di parte...). Con WP MVC, devi semplicemente creare i modelli, le viste e i controller, e tutto il resto viene gestito automaticamente dietro le quinte per te.
È possibile creare controller e viste separati per le sezioni pubbliche e di amministrazione, e l'intero framework sfrutta molte delle funzionalità native di WordPress. La struttura dei file e gran parte delle funzionalità sono esattamente le stesse dei framework MVC più popolari (Rails, CakePHP, ecc.).
Maggiori informazioni e un tutorial possono essere trovati qui:

Utilizziamo un mix di tutti i metodi. Prima di tutto, nei nostri plugin utilizziamo il Zend Framework 1.11 e di conseguenza abbiamo dovuto adottare una struttura simile per i file delle classi a causa del meccanismo di autoload.
La struttura del nostro plugin core (che viene utilizzato come base da tutti i nostri plugin) è simile a questa:
webeo-core/
css/
images/
js/
languages/
lib/
Webeo/
Core.php
Zend/
/** file di ZF **/
Loader.php
views/
readme.txt
uninstall.php
webeo-core.php
- WordPress chiama il file
webeo-core.php
nella cartella root del plugin. - In questo file impostiamo il PHP include path e registriamo gli hook di attivazione e disattivazione per il plugin.
- Abbiamo anche una classe
Webeo_CoreLoader
all'interno di questo file, che imposta alcune costanti del plugin, inizializza l'autoloader delle classi e effettua una chiamata al metodo setup della classeCore.php
all'interno della cartellalib/Webeo
. Questo viene eseguito sull'hook di azioneplugins_loaded
con priorità9
. - La classe
Core.php
è il file di bootstrap del nostro plugin. Il nome è basato sul nome del plugin.
Come puoi vedere, abbiamo una sottocartella all'interno della cartella lib
per tutti i nostri pacchetti vendor (Webeo
, Zend
). Tutti i sottopacchetti all'interno di un vendor sono strutturati dal modulo stesso. Per un nuovo modulo admin Mail Settings
, avremmo la seguente struttura:
webeo-core/
...
lib/
Webeo/
Form/
Admin/
MailSettings.php
Admin.php
Core.php
Form.php
I nostri sotto-plugin hanno la stessa struttura con un'eccezione. Andiamo un livello più profondo all'interno della cartella vendor per risolvere i conflitti di naming durante l'evento di autoload. Chiamiamo inoltre la classe bootstrap del plugin Es. Faq.php
con priorità 10
all'interno dell'hook plugins_loaded
.
webeo-faq/ (usa/estende webeo-core)
css/
images/
js/
languages/
lib/
Webeo/
Faq/
Faq.php
/** tutti i file di classe rilevanti per il plugin **/
views/
readme.txt
uninstall.php
webeo-faq.php
Probabilmente rinominerò la cartella lib
in vendors
e sposterò tutte le cartelle pubbliche (css, images, js, languages) in una cartella chiamata public
nella prossima release.

Come molti hanno già risposto qui, dipende davvero da cosa deve fare il plugin, ma questa è la mia struttura base:
my-plugin/
admin/
contiene tutti i file amministrativi per il backend
js/
contiene tutti i file JavaScript per il backend
css/
contiene tutti i file CSS per il backend
images/
contiene tutte le immagini per il backend
admin_file_1.php file di funzionalità per il backend
admin_file_2.php un altro file di funzionalità per il backend
js/
contiene tutti i file JavaScript per il frontend
css/
contiene tutti i file CSS per il frontend
inc/
contiene tutte le classi helper
lang/
contiene tutti i file di traduzione
images/
contiene tutte le immagini per il frontend
my-plugin.php file principale del plugin con meta, include, action e filter hooks
readme.txt
changelog.txt
license.txt

Preferisco il seguente layout per i plugin, anche se di solito cambia a seconda delle esigenze del plugin.
wp-content/
plugins/
mio-plugin/
inc/
File specifici solo per questo plugin
admin/
File per gestire le attività amministrative
lib/
Classi di libreria/helper vanno qui
css/
File CSS per il plugin
js/
File JavaScript
images/
Immagini per il mio plugin
lang/
File di traduzione
plugin.php
Questo è il file principale che richiama/includere gli altri file
README
Normalmente inserisco qui i dettagli della licenza oltre a informazioni utili
Non ho ancora creato un plugin WordPress che richieda un'architettura in stile MVC, ma se dovessi farlo lo organizzerei con una directory MVC separata, che a sua volta contiene views/controllers/models.

Tutti i miei plugin seguono questa struttura, che sembra essere molto simile a quella utilizzata dalla maggior parte degli altri sviluppatori:
plugin-folder/
admin/
css/
images/
js/
core/
css/
images/
js/
languages/
library/
templates/
plugin-folder.php
readme.txt
changelog.txt
license.txt
Il file plugin-folder.php è solitamente una classe che carica tutti i file necessari dalla cartella core/. Nella maggior parte dei casi questo avviene tramite l'hook init o plugins_loaded.
In passato aggiungevo un prefisso a tutti i miei file, ma come ha fatto notare @kaiser sopra, è davvero ridondante e recentemente ho deciso di rimuoverlo da tutti i futuri plugin.
La cartella library/ contiene tutte le librerie esterne di supporto da cui il plugin potrebbe dipendere.
A seconda del plugin, potrebbe esserci anche un file uninstall.php nella root del plugin. Tuttavia, nella maggior parte dei casi la disinstallazione viene gestita tramite register_uninstall_hook().
Ovviamente, alcuni plugin potrebbero non richiedere file di amministrazione o template, ecc., ma la struttura sopra indicata funziona bene per me. Alla fine, devi solo trovare una struttura che funzioni per te e poi mantenerla.
Ho anche un plugin iniziale, basato sulla struttura sopra descritta, che utilizzo come punto di partenza per tutti i miei plugin. Tutto quello che devo fare è una ricerca/sostituzione per i prefissi di funzioni/classi e posso iniziare. Quando ancora aggiungevo i prefissi ai file, questo era un passaggio aggiuntivo che dovevo fare (e piuttosto fastidioso), ma ora devo solo rinominare la cartella del plugin e il file principale del plugin.

La mia logica è: più grande è il plugin, più struttura utilizzo.
Per i plugin di grandi dimensioni tendo a utilizzare MVC.
Utilizzo questo come punto di partenza e salto ciò che non è necessario.
controller/
frontend.php
wp-admin.php
widget1.php
widget2.php
model/
standard-wp-tables.php // se necessario, suddividerlo
custom-tabel1.php
custom-tabel2.php
view/
helper.php
frontend/
files...php
wp-admin/
files...php
widget1/
file...php
widget2/
file...php
css/
js/
image/
library/ //solo php, principalmente per Zend Framework, ancora una volta se necessario
constants.php //tendo a usarlo spesso
plugin.php //file di inizializzazione
install-unistall.php //solo per plugin grandi

Inoltre, dai un'occhiata a questo fantastico boilerplate per widget WP. Offre ottimi spunti sulle strutture (anche se non c'è una classe né una cartella per modelli separati).

Un approccio meno comune per strutturare i file e le directory di un plugin è l'organizzazione per tipo di file. Vale la pena menzionarlo qui per completezza:
plugin-name/
js/
sparkle.js
shake.js
css/
style.css
scss/
header.scss
footer.scss
php/
class.php
functions.php
plugin-name.php
uninstall.php
readme.txt
Ogni directory contiene solo file di quel tipo specifico. È importante notare che questo approccio risulta carente quando si hanno molti tipi di file .png .gif .jpg
che potrebbero essere più logicamente raggruppati in un'unica directory, ad esempio images/
.

Ho sviluppato un repository template su GitHub per plugin WordPress, racchiudendo oltre 10 anni di esperienza in una struttura ben definita!
https://github.com/EdwardBock/wordpress-plugin-starterkit
Il template rispetta gli standard PSR-4 per ridurre al minimo gli include di stringhe e utilizza i namespace per una denominazione concisa delle classi e una classe componente per il templating. Include inoltre un file docker compose per poter sviluppare il plugin in isolamento. Ma può anche essere semplicemente inserito in un progetto esistente e funzionare altrettanto bene.
Buona esplorazione e sentitevi liberi di contribuire!
