OOP in pratica con WordPress: introduzione

OOP in pratica con WordPress: introduzione

In questo articolo introdurremo alcuni dei concetti chiave per programmare in modo object-oriented in WordPress. Un requisito necessario è la conoscenza dell’OOP in PHP oltre che la conoscenza di base del funzionamento di WordPress.

Un CMS misto: OOP e programmazione procedurale in WordPress

Un mito comune riguardante WordPress è quello secondo cui questo CMS sia interamente procedurale nel suo design. Nulla di più falso: la scelta di design di WordPress è stata quella di costruire le fondamenta del CMS usando le classi e di esporre i metodi e le proprietà di tali classi tramite funzioni e variabili globali.

Ad esempio tutti noi sappiamo che il Loop principale di WordPress - ossia il ciclo attraverso cui vengono reperiti i contenuti - può di solito presentarsi come segue:

if( have_posts() ) {
    while( have_posts() ) {
        the_post();
    }
}

Apparentemente il codice è interamente procedurale. In realtà tutte le funzioni che abbiamo utilizzato non sono altro che una scorciatoia per il seguente codice OOP:

$loop = new WP_Query( array( 'posts_per_page' => -1 ) );
if( $loop->have_posts() ) {
     while( $loop->have_posts() ) {
         $loop->the_post();
     }
}

Lo stesso concetto vale per le funzioni get_posts() e query_posts(): sono tutte basate sulla classe WP_Query. Più precisamente tutto ciò che in WordPress ha a che fare con il Loop - ossia con il reperimento dei contenuti (post, pagine, allegati) dal database - dipende direttamente da tale classe e non può in alcun modo prescindervi.

Ma non basta: anche la temporizzazione degli eventi, la gestione degli errori, la gestione delle richieste AJAX, la gestione delle query dirette al database, la gestione degli utenti e dei loro ruoli, la gestione dei menu di navigazione, i widget e altro ancora sono tutte funzionalità gestite da classi.

In pratica noi usiamo quasi sempre funzioni in WordPress ma in realtà stiamo usando le sue classi che restano nascoste dietro le quinte.

Perchè usare l’OOP?

Abbiamo detto che in WordPress le funzioni svolgono egregiamente il loro compito. Quindi solitamente per aggiungere una funzionalità al nostro tema è sufficiente modificare il file functions.php (il nome è significativo) con il nostro codice per avere l’effetto sperato.

Quindi se volessimo creare uno shortcode per visualizzare una citazione di blocco dovremmo semplicemente aggiungere il seguente codice:

function my_pullquote( $content ) {
    return '<blockquote class="pullquote">' . $content . '</blockquote>';
}
add_shortcode( 'my-pullquote', 'my_pullquote' );

Ma cosa succederebbe se aveste più di uno shortcode da aggiungere? A livello di gestione e manutenibilità del codice vi ritrovereste con un file functions.php letteralmente traboccante di funzioni.

E ogni volta che dovrete modificare una funzionalità sarete costretti a ricordarvi in quale funzione l’avete definita. Si tratta di uno scenario davvero difficile da gestire.

Le classi ci permettono invece di raggruppare il codice in moduli separati, ciascuno con una propria logica ed una propria struttura. Quindi per gli shortcode potreste definire una classe apposita:

class MyThemeShortcodes {
}

Al suo interno saranno i metodi della classe a definire le azioni legate a ciascuno shortcode:

class MyThemeShortcodes {
    public function __construct() {
        add_shortcode( 'my-pullquote', array( &$this, 'createPullQuote' ) );
    }
    public function createPullQuote( $content ) {
          return '<blockquote class="pullquote">' . $content . '</blockquote>';
    }
}
$myThemeShortcodes = new MyThemeShortcodes();

In questo caso specifico l’istanziazione della classe richiama direttamente la funzione di WordPress add_shortcode() che va a creare lo shortcode. Quindi in functions.php richiamerete i moduli desiderati:

require_once( TEMPLATEPATH . '/framework/MyThemeShortcodes.php' );

Si potrebbe obiettare che questo tipo di classi in WordPress non sono altro che dei wrapper per metodi pubblici. In realtà non è così: si supponga ad esempio di voler eliminare la marcatura aggiuntiva inserita da WordPress nel contenuto degli shortcode:

private function _removeWPAutop( $content ) {
    $content = do_shortcode( shortcode_unautop( $content ) );
    $content = preg_replace( '#^<\/p>|^<br \/>|<p>$#', '', $content );
    return $content;
}

public function createPullQuote( $content ) {
    return '<blockquote class="pullquote">' .
    $this->_removeWPAutop( $content ) . '</blockquote>';
}

Come si può notare, viene applicata la stessa distinzione alla base della logica OOP di PHP: un metodo privato opera all’interno della sua classe di appartenenza secondo il principio dell’incapsulamento.

Il metodo è privato perché al di fuori della classe che gestisce gli shortcode non sarebbe di alcuna utilità. Infatti il problema della marcatura extra è un problema peculiare degli shortcode di WordPress.

Lo stesso principio si applica alle proprietà di queste classi. Ad esempio potremmo volere che sia l’utente a scegliere se rimuovere la marcatura dagli shortcode o se preferisca invece mantenerla:

class MyThemeShortcodes {
    public $removeAutop = false;
    public function __construct() {
        if(get_option('my-no-autop')) {
            $this->removeAutop = (bool) get_option('my-no-autop');
        }

        //...
    }
    public function createPullQuote( $content ) {
         if($this->removeAutop) {
              // rimuove la marcatura
          } else {
             // non la rimuove
          }
    }
}

In questo caso usiamo una proprietà pubblica in modo da poter comunicare lo status della classe - ossia la scelta di non intervenire sul contenuto degli shortcode - alle altre classi che andremo a definire.

Da qui in poi

L’OOP in WordPress ha un margine di sviluppo pressoché illimitato: abbiamo semplicemente accennato ad un uso nei temi, ma questo approccio si applica anche ai plugin.

Con l’OOP è possibile partire da una semplice collezione di classi che gestiscono un tema per arrivare a framework completi che possono gestire qualsiasi tipo di tema (corporate, blog, e-commerce e così via).

La sfida sta nell’astrarre le funzionalità necessarie e gestirle con classi e oggetti. La sfida finale è quella di rendere il nostro codice estendibile, ossia in grado di gestire nuove funzionalità che si verranno ad aggiungere con il minimo sforzo.

Torna su