Prototipazione rapida: dal prototipo al codice, parte 2
Il post precedente dimostra molto lavoro nel prendere qualcosa che una volta era un prototipo rapido e portare quel prototipo al codice. Se non hai seguito insieme, abbiamo fatto quanto segue:
- parlato e costruito un prototipo per un plugin,
- schematizzato un approccio orientato agli oggetti può funzionare,
- e rifattorizzato il nostro prototipo in codice reale.
A questo punto, ci sono alcune altre cose che possiamo fare per migliorare il nostro codice. Vale a dire, possiamo introdurre il concetto di namespace. Ciò porta l’organizzazione a fare un ulteriore passo avanti e può pagare dividendi per progetti più grandi.
Quindi, ecco uno sguardo a come questo si svolge nel nostro progetto attuale.
Prototipo da codificare: spazi dei nomi
Ho trattato in modo approfondito gli spazi dei nomi nei post precedenti. Se non l’hai letto, te lo consiglio. Quindi torna indietro e controlla il resto del post.
Se scegli di saltare l’articolo, ecco una breve definizione di spazio dei nomi :
I namespace sono progettati per risolvere due problemi che gli autori di librerie e applicazioni incontrano durante la creazione di elementi di codice riutilizzabili come classi o funzioni…
E l’idea generale è che organizziamo le nostre classi sulla base di una relazione logica che hanno tra loro.
Inoltre, organizziamo anche i file all’interno di directory che corrispondono allo spazio dei nomi. Questo non è qualcosa che deve essere fatto, ma trovo che aiuti avere le classi organizzate logicamente sul disco nel modo in cui sono organizzate virtualmente nello spazio dei nomi.
Detto questo, organizziamo i file.
Organizzare i file
Invece di iniziare con il file del plugin principale, iniziamo prima con l’organizzazione dei nostri file.
- I file Meta Box e Meta Box Display risiederanno in una directory chiamata Display. Questo è completamente arbitrario, ma poiché è quello che fanno quei file, sembra avere senso che sia lì che risiedono.
- Possiamo anche inserire i file message-description.php e no-post-list.php in quella directory, ma inserirli in una sottodirectory chiamata Views. Potresti chiamarlo Modelli o Parziali o qualcosa di simile.
- Successivamente, abbiamo le classi responsabili dell’interrogazione del database e la classe responsabile del coordinamento della messaggistica. Mettiamo ognuno di questi in Utility. Ci sono altri posti in cui potrebbero andare, certo, ma ricorda che lo scopo è dimostrare come utilizzare gli spazi dei nomi. Quindi, se ti senti così incline, sentiti libero di adattare i tuoi file a tuo piacimento.
Se hai seguito quello che abbiamo sopra, dovresti avere una struttura di directory simile a questa:
Un modo per organizzare i tuoi file.
Ora è il momento di definire gli spazi dei nomi per ciascuna delle classi. Dal momento che li abbiamo organizzati tutti nelle loro directory, sarà facile specificare uno spazio dei nomi; tuttavia, è importante riconoscere che dovremo usare la parola chiave use quando utilizziamo classi che si trovano in altri spazi dei nomi.
Esaminiamo ciascuno dei nostri file iniziando con i file in Utility. Innanzitutto, inizieremo con Post Messenger :
<?php
/**
* Display content for the meta box when requested.
*
* @author Tom McFarlin
* @since 0.2.0
*/
namespace McFarlinTRPUtility;
use McFarlinTRPUtilityPost_Query;
/**
* Retrieves information from the class responsible for querying the database and
* renders it in the context of our meta box when called via the Meta Box Display.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Post_Messenger {
// Snip for brevity.
}
Noterai che lo spazio dei nomi del file appare nell’intestazione insieme a una dichiarazione per utilizzare la classe Post Query che abbiamo creato. Ho aggiunto il nome della classe alla fine dello spazio dei nomi, quindi non devo usarlo in tutta la codebase.
Notare che il costruttore ora appare così :
<?php
/**
* Instantiates the class by setting a reference to the query.
*
* @param string $plugin_dir The path to the root of the plugin directory.
*/
public function __construct( $plugin_dir) {
$this->query = new Post_Query();
$this->plugin_dir = trailingslashit( $plugin_dir );
}
Ho aggiunto un argomento $plugin_dir perché dobbiamo usarlo per visualizzare correttamente i risultati della query. E poiché ora risiedono in un’area di differenza dell’applicazione, le funzioni sono simili a questa :
<?php
/**
* Displays the description of the content of the meta box.
*
* @access private
*/
private function get_post_message() {
include_once $this->plugin_dir. 'Display/Views/post-list.php';
}
/**
* Displays the description of the content of the meta box.
*
* @access private
*/
private function get_description() {
include_once $this->plugin_dir. 'Display/Views/message-description.php';
}
/**
* Displays a message of there are no recent posts.
*
* @access private
*/
private function get_no_posts_message() {
include_once $this->plugin_dir. 'Display/Views/no-post-list.php';
}
Quindi, diamo un’occhiata alla classe Post Query. Non è cambiato molto in questa classe tranne che gli abbiamo assegnato uno spazio dei nomi e abbiamo anche aggiornato la query solo per recuperare tre post (come da questo commento ).
<?php
namespace McFarlinTRPUtility;
/**
* Queries the database for three most recent posts. Returns the query to the
* caller so that it can be interrogates for posts or not.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Post_Query {
// Snip for brevity.
private function get_posts() {
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 3,
'orderby' => 'date',
'order' => 'desc',
);
$this->query = new WP_Query( $args );
return $this->query;
}
}
Nota nel codice, ho anche prefissato WP_Query con una barra perché fa parte dello spazio dei nomi globale.
Spostiamoci nella directory Display e diamo un’occhiata alla classe Meta Box. A questo è stato anche assegnato uno spazio dei nomi e utilizza anche il nome completo della classe Meta Box Display che esamineremo momentaneamente.
<?php
namespace McFarlinTRPDisplay;
use McFarlinTRPDisplayMeta_Box_Display;
/**
* Registers the Meta Box with WordPress. Defines the ID, title, display function,
* and the post type on which it will live.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Meta_Box {
/**
* A reference to the class that will display the contents in the meta box.
*
* @access private
* @var Meta_Box_Display
*/
private $meta_box_display;
/**
* Instantiates the class by setting its property equal to a reference to its display.
*
* @param string $plugin_dir A reference to the root of the plugin's directory.
*/
public function __construct( $plugin_dir) {
$this->meta_box_display = new Meta_Box_Display( $plugin_dir );
}
// Snip for brevity.
}
Notare che questo costruttore accetta anche la directory del plugin come argomento e la passa anche alla classe Meta Box Display. Questo perché le funzioni responsabili della visualizzazione dei messaggi possono essere trovate correttamente nella loro posizione nella directory Views.
Infine, esaminiamo la classe Meta Box Display. Questa è una classe semplice che include lo spazio dei nomi e fa riferimento al Post Messenger che abbiamo esaminato sopra.
<?php
/**
* Defines the display for the meta box.
*
* @author Tom McFarlin
* @since 0.2.0
*/
namespace McFarlinTRPDisplay;
use McFarlinTRPUtilityPost_Messenger;
/**
* Defines the display for the meta box that will render the content in the
* context of its meta box.
*
* @author Tom McFarlin
* @since 0.2.0
*/
class Meta_Box_Display {
/**
* A reference to the class that will display the contents in the meta box.
*
* @access private
* @var Post_Messenger
*/
private $messenger;
/**
* Instantiates the object by setting a property equal to that of the class
* responsible for rendering the messages from the post query.
*
* @param string $plugin_dir A reference to the root of the plugin's directory.
*/
public function __construct( $plugin_dir) {
$this->messenger = new Post_Messenger( $plugin_dir );
}
/**
* If there are posts to display, renders them in the metabox. Otherwise, displays
* a note that there are no posts to display.
*/
public function display() {
$this->messenger->get_message();
}
}
A questo punto, abbiamo chiuso il cerchio attraverso il plugin. Con un’eccezione: il file bootstrap. Abbiamo aggiunto uno spazio dei nomi e dobbiamo aggiornare il modo in cui è stato istanziato :
<?php
namespace McFarlinTRP;
use McFarlinTRPDisplayMeta_Box;
include 'Display/class-meta-box.php';
include 'Display/class-meta-box-display.php';
include 'Utility/class-post-messenger.php';
include 'Utility/class-post-query.php';
add_action( 'add_meta_boxes', __NAMESPACE__. 'trp_start' );
/**
* Starts the plugin.
*/
function trp_start() {
$meta_box = new Meta_Box( dirname( __FILE__) );
$meta_box->init();
}
Vale a dire, abbiamo:
- definito lo spazio dei nomi,
- fare riferimento alla posizione della classe Meta Box ,
- aggiornato i percorsi per includere dove trovare i file (che alla fine può essere fatto con un caricatore automatico),
- e aggiornato la chiamata add_action.
Ecco il problema della chiamata ad azione aggiuntiva: poiché WordPress deve individuare questa funzione e la funzione risiede in uno spazio dei nomi, il nome completo della funzione deve essere identificato in modo che WordPress possa richiamarla. Da qui la necessità di NAMESPACE nel nome della funzione.
Ora siamo organizzati (con un’eccezione)
Come puoi vedere, gli spazi dei nomi e le directory che li corrispondono aggiungono molta organizzazione a un progetto. È più facile da seguire, più facile capire dove vanno le cose (sia per i file esistenti che per quelli nuovi). E dà meno sensazione di accumulare molti file in un unico posto.
Anche se una classe è un po’ un monolito, può comunque essere organizzata in modo tale da semplificare la manutenzione.
Detto questo, c’è ancora qualcosa che cambierei su questo plugin: passare nella directory del plugin in questo modo non è qualcosa che aiuta con una bassa coesione e accoppia più strettamente le classi perché il file bootstrap deve passare un valore in una classe che lo passa a un’altra classe che lo utilizza per caricare file e così via.
Quindi ci sono modi per risolvere questo problema? Assolutamente. E forse daremo un’occhiata a questo nel post finale.
Fino ad allora, ricorda che la versione più recente del plugin è disponibile sul ramo master, etichettato come 0.3.0, su GitHub.
Messaggi di serie
- Prototipazione rapida con WordPress: dal concetto al plug-in
- Prototipazione rapida con WordPress: analisi concettuale
- Prototipazione rapida: da prototipazione a codice, parte 1
- Prototipazione rapida: dal prototipo al codice, parte 2
- Prototipazione rapida: introduzione del caricamento automatico