Come personalizzare la classe wpdb e aggiungere nuovi metodi

Pubblicato: 2018-07-10

Il livello di astrazione del database di WordPress, più comunemente noto come wpdb, è una classe basata su ezSQL responsabile dell'interazione con il database. La classe wpdb è anche un drop-in, un pezzo di codice WP di base che può essere facilmente sostituito da un altro pezzo di codice con funzionalità simili (un elenco aggiornato di drop-in è disponibile in WP Code Reference).

La modifica della classe #wpdb predefinita non è complicata. Puoi facilmente aggiungere, rimuovere o modificare solo alcuni metodi. Non c'è bisogno di sostituire l'intera classe. #wordpress

CLICCA PER TWEET

È qui che entra in gioco un grande equivoco. Le persone percepiscono "sostituito" come in "scrivi la mia classe di database completa". Fortunatamente, non è necessario scrivere l'intera classe del database. Puoi prendere la classe esistente e aggiungere, rimuovere o modificare solo le funzioni di cui hai bisogno. Ed è quello che faremo.

Perché modificare la classe wpdb?

Sicuramente, wpdb ha tutto ciò di cui hai bisogno!? L'intero WP è costruito su di esso. Tecnicamente è corretto. Usando il $wpdb->query() puoi eseguire qualsiasi comando SQL. Ma con quella logica applicata non avremmo mai né bisogno di metodi come $wpdb->insert() o $wpdb->get_var() . Ma lo facciamo, perché fanno risparmiare tempo, riducono i bug e tengono lontane le domande errate. Quindi, quali funzioni mancano? Dipende dal progetto su cui stai lavorando. Avevamo bisogno di supporto per queste due domande:

INSERT IGNORE INTO tbl_name ...
INSERT INTO tbl_name ... ON DUPLICATE KEY UPDATE ...

Passaggio 1: crea il drop-in

Il processo di creazione di un drop-in DB è semplice e il risultato finale si integra perfettamente in WP.
Crea un file chiamato db.php e mettilo nella cartella /wp-content/ . Assegna al file un'intestazione di plug-in standard e crea una classe che estenda wpdb. Qualcosa come questo:

<?php
/*
  Plugin Name: Extended wpdb
  Description: A few extra functions for wpdb
  Version: 1.0
  Author: WebFactory Ltd
*/

class wpdb_extended extends wpdb {

  public function __construct(){
    parent::__construct( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
  }

  public function test() {
    echo 'Extended wpdb is running.';
  }
}


global $wpdb;
$wpdb = new wpdb_extended();

L'intestazione è abbastanza autoesplicativa. Il metodo di costruzione si assicura di creare una nuova connessione DB una volta che un oggetto è stato costruito e utilizza il costruttore wpdb originale per questo. Queste costanti DB sono definite in wp-config.php . Come abbiamo detto all'inizio, stiamo solo aggiungendo alcune funzioni e riutilizzando tutto il resto. Il secondo metodo test() serve esclusivamente a vedere se tutto funziona correttamente.

Le ultime due righe sono cruciali. Poiché questa è una classe personalizzata, WP non creerà automaticamente l'oggetto $wpdb per noi. Dobbiamo farlo da soli. Ricorda di utilizzare la parola chiave global perché altrimenti creerai una variabile locale.

Passaggio 2: prova prima di scavare più a fondo

Apri la tua dashboard WP e vai su Plugin. Oltre alle solite schede All, Active e Inactive (plugin), vedrai una scheda Drop-in e in essa, per magia, la nostra classe di database personalizzata.

Poiché l'amministratore funziona correttamente, sappiamo di aver fatto un buon lavoro. La nostra nuova classe estesa e personalizzata è entrata e non è cambiato nulla. Grande! Ma, solo per buona misura, inserisci queste tre righe di codice nel functions.php del tema (o da qualche parte all'interno di un plug-in dove verrà eseguito immediatamente):

global $wpdb;
$wpdb->test();
die;

Esegui qualsiasi pagina di amministrazione o front-end e cosa vedi? “ Wpdb esteso è in esecuzione. " Perfetto. Ora per le nostre funzioni del mondo reale.

Passaggio 3: crea, modifica o sostituisci funzioni

La query INSERT IGNORE sembra abbastanza facile da eseguire. Abbiamo già $wpdb->insert() quindi ci manca solo una singola parola. Sfortunatamente, a causa della mancanza di filtri nei posti giusti, non saranno due righe di codice.

Se apri wp-db.php e vai al metodo insert() sulla riga #2100, vedrai che utilizza il metodo _insert_replace_helper() dalla riga #2151. E quella funzione non ha un singolo filtro o azione. Non possiamo nemmeno eseguire il wrapping della funzione perché restituisce immediatamente il risultato della query e non la query stessa che potremmo modificare. Peccato. Dovremo sovrascrivere entrambi i metodi insert() e _insert_replace_helper() . Aggiungeremo un parametro aggiuntivo: $ignore . Un booleano con il valore predefinito false .

public function insert( $table, $data, $format = null, $ignore = false ) {
  return $this->_insert_replace_helper( $table, $data, $format, 'INSERT', $ignore = false );
}

In qualsiasi altra circostanza, una funzione con cinque parametri sarebbe un buon candidato per trasformarli in un array associativo. Ma vogliamo la compatibilità con le versioni precedenti, quindi non lo stiamo facendo. Anche le modifiche all'altra funzione sono minori:

function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT', $ignore = false ) {
  $this->insert_id = 0;

  if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) {
    return false;
  }

  $data = $this->process_fields( $table, $data, $format );
  if ( false === $data ) {
    return false;
  }

  $formats = $values = array();
  foreach ( $data as $value ) {
    if ( is_null( $value['value'] ) ) {
      $formats[] = 'NULL';
      continue;
    }

    $formats[] = $value['format'];
    $values[]  = $value['value'];
  }

  $fields  = '`' . implode( '`, `', array_keys( $data ) ) . '`';
  $formats = implode( ', ', $formats );
  
  // modification for IGNORE keyword
  if (true == $ignore && 'INSERT' == $type) {
    $type = 'INSERT IGNORE';
  }

  $sql = "$type INTO `$table` ($fields) VALUES ($formats)";

  $this->check_current_query = false;
  return $this->query( $this->prepare( $sql, $values ) );
}

Perché gli sviluppatori non lo fanno più spesso?

Se hai bisogno di una query personalizzata solo poche volte puoi facilmente usare $wpdb->query() . Non è necessario sostituire la classe predefinita. Puoi anche scrivere una classe personalizzata che estende quella predefinita ma non sovrascrive l'oggetto wpdb. In tal caso $mycustomclass->method() ma non è la fine del mondo.

Oltre all'ovvio fattore di freddezza, l'estensione della classe wpdb predefinita è qualcosa che dovrebbe essere fatto in WP e non è un hackish, quindi sentiti libero di giocarci. Tieni a mente due cose:

  • quando invii il tuo progetto a qualcuno, non dimenticare di includere il file db.php ; non sarà in nessuna cartella di temi o plugin
  • tieni d'occhio le modifiche in wp-db.php in quanto potrebbero influenzare la tua classe personalizzata (anche se è altamente improbabile)