OOP in pratica con WordPress: gestire gli script

OOP in pratica con WordPress: gestire gli script

Nel corso degli articoli precedenti abbiamo analizzato le basi della programmazione OOP in WordPress. In questo articolo ed in quelli successivi vedremo alcune applicazioni pratiche dell'OOP in WordPress.

Gli script in WordPress

Gli script JavaScript devono essere prima registrati e solo dopo possono essere inclusi.

Per registrare uno script si utilizza la funzione wp_register_script() e per includerlo la funzione wp_enqueue_script().

Entrambe queste funzioni lavorano unitamente all'action di WordPress wp_enqueue_scripts.

Supponiamo di aver creato uno script chiamato myscript.js e di volerlo includere nel footer, ossia prima della chiusura dell'elemento body:

function my_theme_add_scripts() {
wp_register_script( 'myscript', get_template_directory_uri() . '/js/myscript.js', '1.0', true );
wp_enqueue_script( 'myscript' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_add_scripts' );

Se aggiungiamo questo codice al file `functions.php`del nostro tema otterremo il risultato voluto. Il problema dell'approccio procedurale, come abbiamo già detto, è la difficoltà nella gestione e nella manutenzione del codice. Infatti:

  • Dovremo stabilire quale libreria JavaScript usare e all'occorrenza cambiarla con semplicità.
  • Se includiamo script remoti, dovremo trovare un modo di evitare che il browser vada in timeout qualora la risorsa non sia disponibile.
  • Dovremo verificare sempre che una data libreria, un plugin o uno script non sia già stato caricato in precedenza.
  • Dovremo automatizzare il processo di registrazione ed inclusione degli script per evitare di scrivere codice ridondante.

Definizione della classe

Definiamo la nostra classe come segue:

if( !class_exists( 'My_Theme_Scripts' ) ) {
  class My_Theme_Scripts {
  // proprietà
  public function __construct() { }
  }
}

Verificare sempre che una classe non sia stata definita in precedenza è sempre una buona pratica da seguire per evitare conflitti ed errori fatali in PHP.

Definire la libreria JavaScript in uso

La prima cosa che definiremo nella nostra classe è la libreria JavaScript che useremo. WordPress dispone già di diverse librerie incluse nel suo Core, quindi un ulteriore passaggio da effettuare sarà quello di specificare se vogliamo usare la versione built-in o una versione esterna (presente nel tema, plugin o su un CDN remoto).

L' informazione sulla libreria scelta sarà pubblica perché vogliamo che anche altre parti del nostro codice dispongano di questo dato:

// proprietà
public $jsLibrary;
private $_isBuiltInLibrary;

public function __construct( $library, $builtIn ) {
  $this->jsLibrary = $library;
  $this->_isBuiltInLibrary = $builtIn;
  //...
}

Esempio d'uso:

$myThemeScripts = new My_Theme_Scripts( 'jquery', true );
echo $myThemeScripts->jsLibrary; // 'jquery'

Agli altri componenti del nostro codice serve sapere che stiamo usando jQuery, mentre l'informazione circa l'origine della libreria è ininfluente.

Un'altra informazione utile è sicuramente la versione della libreria:

// proprietà
public $jsLibrary;
        public $jsLibraryVer;
private $_isBuiltInLibrary;

public function __construct( $library, $version, $builtIn ) {
  $this->jsLibrary = $library;
  $this->jsLibraryVer = $version;
  $this->_isBuiltInLibrary = $builtIn;
  //...
}

Un semplice test:

$myThemeScripts = new My_Theme_Scripts( 'jquery', '1.9', true );
echo $myThemeScripts->jsLibrary; // 'jquery'
echo $myThemeScripts->jsLibraryVer; // '1.9'

A questo punto possiamo definire un metodo privato per includere la libreria principale. La nostra libreria è un componente speciale, quindi merita un trattamento a parte:

private function _addLibrary( $url = '' ) {
  if( $this->_isBuiltinLibrary ) {
      wp_enqueue_script( $this->jsLibrary );
  } else {
    wp_deregister_script( $this->jsLibrary );
    wp_register_script( $this->jsLibrary, $url, $this->jsLibraryVer, true );
    wp_enqueue_script( $this->jsLibrary );
  }
}

Il nostro metodo verrà chiamato all'interno del metodo pubblico che andremo a legare al costruttore e all'action wp_enqueue_scripts:

public function __construct( $library, $version, $builtIn ) {
  // proprietà
  add_action( 'wp_enqueue_scripts', array( &$this, 'addScripts' ) );

}

public function addScripts() {
  $this->_addLibrary();
  // altri script
}

Evitare i timeout per gli script remoti

Se includiamo degli script remoti c'è la possibilità che tali script non siano disponibili. In questo caso, e specialmente nel caso delle librerie, l'intero codice JavaScript del nostro sito cessa di funzionare.

La soluzione in questi casi è quella di verificare che lo script remoto sia disponibile ed impostare uno script di ripiego locale nel caso in cui il tempo di attesa sia troppo lungo.

private function _isRemoteScriptAlive ( $url ) {
  $request = wp_remote_get( $url, array( 'timeout' => 3 ) );
  return ( !is_wp_error( $request ) );
}  

In pratica abbiamo impostato un timeout di tre secondi per verificare se lo script remoto è accessibile. Possiamo usare questo metodo nel seguente modo:

$remoteScript = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
if( $this->_isRemoteScriptAlive( $remoteScript ) ) {
  // includiamo la copia CDN
} else {
  // includiamo la copia locale
}

Evitare di caricare gli script due volte

WordPress dispone della funzione wp_script_is() che per ignoti motivi viene usata raramente.

In realtà questa funzione è utilissima perché ci permette di sapere se uno script è già stato incluso o meno restituendo un valore booleano.

Il problema della duplicazione degli script è molto diffuso: molti plugin infatti registrano ad esempio due volte la libreria jQuery andando ad aggiungere la loro versione a quella del tema in uso.

Il risultato è disastroso: si ha infatti la sovrascrittura della versione precedentemente registrata ed una miriade di effetti collaterali sul codice.

Possiamo aggiungere un semplice metodo alla nostra classe:

private function _isScriptAlreadyLoaded( $handle ) {
  if( !wp_script_is( strtolower( $handle ) ) ) {
    return false;
  }
  return true;
}

In questo modo sapremo sempre se c'è effettivamente bisogno di caricare uno script:

if( !$this->_isScriptAlreadyLoaded( 'jquery' ) ) {
  // inserisco jQuery
}

Automatizzare l'inserimento degli script

Sinora abbiamo visto come includere la libreria principale. Il problema ora sta nel trovare una soluzione per includere gli altri script senza dovere ogni volta ripetere le funzioni di WordPress per ciascuno script.

Sicuramente una soluzione valida è quella di utilizzare un array associativo come proprietà della nostra classe:

// proprietà
public $otherScripts = array();
public function __construct(..., $scripts ) {
  // proprietà
  $this->otherScripts = $scripts;
  // qui usiamo addScripts()
}

Il nostro array dovrà avere il nome dello script, la versione, il percorso o URL, un valore booleano per sapere se va incluso nel footer o meno e l'eventuale dipendenza da altri script:

$myScripts = array(
  0 => array(
    'handle' => 'flexslider'
    'url' => get_template_directory_uri() . '/js/jquery.flexslider.js',
    'ver' => '2.0',
     'dep' => array( 'jquery' );
    'infooter' => true
  ),
  //...
);

Quindi nel nostro metodo addScripts() scriveremo il seguente codice:

foreach( $this->otherScripts as $script => $value ) {
  $handle = $value['handle'];
  $url = $value['url'];
  $ver = $value['ver'];
  $dep = $value['dep'];
  $inFooter = $value['infooter'];
  if( is_array( $dep ) ) {
    wp_register_script( $handle, $url, $ver, $dep, $inFooter );
  } else {
    wp_register_script( $handle, $url, $ver, $inFooter );
  }
  wp_enqueue_script( $handle );
}

In questo modo è sufficiente aggiungere un'altra voce all'array per ottenere il risultato voluto.

Documentazione ufficiale

Torna su