So passen Sie die wpdb-Klasse an und fügen neue Methoden hinzu

Veröffentlicht: 2018-07-10

Die WordPress-Datenbank-Abstraktionsschicht, besser bekannt als wpdb, ist eine auf ezSQL basierende Klasse, die für die Interaktion mit der Datenbank verantwortlich ist. Die wpdb-Klasse ist auch ein Drop-In – ein Teil des WP-Kerncodes, der leicht durch einen anderen Code mit ähnlicher Funktionalität ersetzt werden kann (eine aktuelle Liste von Drop-Ins ist in der WP-Code-Referenz verfügbar).

Das Ändern der Standardklasse #wpdb ist nicht kompliziert. Sie können nur wenige Methoden einfach hinzufügen, entfernen oder ändern. Es muss nicht die ganze Klasse ersetzt werden. #wordpress

KLICKEN, UM ZU TWEETEN

Hier kommt ein großes Missverständnis ins Spiel. Leute nehmen „ersetzt“ wahr wie in „schreibe meine eigene, komplette Datenbankklasse“. Glücklicherweise müssen Sie nicht die gesamte Datenbankklasse schreiben. Sie können die vorhandene Klasse nehmen und nur die Funktionen hinzufügen, entfernen oder ändern, die Sie benötigen. Und das werden wir tun.

Warum die wpdb-Klasse ändern?

Sicherlich hat wpdb alles, was Sie brauchen!? Das ganze WP baut darauf auf. Technisch ist das richtig. Mit der Methode $wpdb->query() können Sie beliebige SQL-Befehle ausführen. Aber mit dieser angewandten Logik würden wir niemals Methoden wie $wpdb->insert() oder $wpdb->get_var() haben oder brauchen. Aber wir tun es, weil sie Zeit sparen, Fehler reduzieren und schlechte Abfragen fernhalten. Welche Funktionen fehlen also? Das hängt von dem Projekt ab, an dem Sie arbeiten. Bei diesen beiden Anfragen benötigten wir Unterstützung:

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

Schritt #1 – Erstellen Sie das Drop-in

Der Prozess zum Erstellen eines DB-Drop-Ins ist einfach und das Endergebnis fügt sich nahtlos in WP ein.
Erstellen Sie eine Datei namens db.php und legen Sie sie im Ordner /wp-content/ ab. Geben Sie der Datei einen Standard-Plugin-Header und erstellen Sie eine Klasse, die wpdb erweitert. Etwas wie das:

<?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();

Die Kopfzeile ist ziemlich selbsterklärend. Die Konstruktmethode stellt sicher, dass wir eine neue DB-Verbindung erstellen, sobald ein Objekt erstellt wurde, und verwendet dafür den ursprünglichen wpdb-Konstruktor. Diese DB-Konstanten sind in wp-config.php definiert. Wie wir am Anfang gesagt haben – wir fügen nur einige Funktionen hinzu und verwenden alles andere wieder. Die zweite Methode test() dient lediglich dazu, zu sehen, ob alles korrekt funktioniert.

Die letzten beiden Zeilen sind entscheidend. Da dies eine benutzerdefinierte Klasse ist, erstellt WP das $wpdb Objekt nicht automatisch für uns. Wir müssen es selbst tun. Denken Sie daran, das Schlüsselwort global zu verwenden, da Sie sonst eine lokale Variable erstellen.

Schritt Nr. 2 – Testen Sie, bevor Sie tiefer graben

Öffnen Sie Ihr WP-Dashboard und gehen Sie zu Plugins. Neben den üblichen Registerkarten Alle, Aktiv und Inaktiv (Plug-Ins) sehen Sie eine Registerkarte Drop-Ins und darin, wie durch Zauberei, unsere benutzerdefinierte Datenbankklasse.

Da der Admin ordnungsgemäß funktioniert, wissen wir, dass wir gute Arbeit geleistet haben. Unsere neue, benutzerdefinierte, erweiterte Klasse ist da und nichts hat sich geändert. Toll! Aber nur zur Sicherheit fügen Sie diese drei Codezeilen in die functions.php des Themes ein (oder irgendwo in ein Plugin, wo es sofort ausgeführt wird):

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

Führen Sie eine beliebige Admin- oder Frontend-Seite aus und was sehen Sie? „ Extended wpdb läuft. " Perfekt. Nun zu unseren realen Funktionen.

Schritt #3 – Erstellen, ändern oder ersetzen Sie Funktionen

Die INSERT IGNORE Abfrage scheint ziemlich einfach zu sein. Wir haben bereits $wpdb->insert(), also fehlt uns nur ein einziges Wort. Aufgrund fehlender Filter an den richtigen Stellen werden es leider keine zwei Codezeilen sein.

Wenn du wp-db.php öffnest und zur Methode insert() in Zeile #2100 gehst, wirst du sehen, dass sie die Methode _insert_replace_helper() aus Zeile #2151 verwendet. Und diese Funktion hat keinen einzigen Filter oder Aktion. Wir können die Funktion auch nicht umschließen, da sie sofort das Abfrageergebnis zurückgibt und nicht die Abfrage selbst, die wir ändern könnten. Schade. Wir müssen die Methoden insert() und _insert_replace_helper() . Wir fügen einen zusätzlichen Parameter hinzu – $ignore . Ein boolescher Wert mit dem Standardwert false .

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

Unter allen anderen Umständen wäre eine Funktion mit fünf Parametern ein guter Kandidat, um sie in ein assoziatives Array umzuwandeln. Aber wir wollen Abwärtskompatibilität, also tun wir das nicht. Änderungen an der anderen Funktion sind ebenfalls geringfügig:

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 ) );
}

Warum machen Entwickler das nicht öfter?

Wenn Sie eine benutzerdefinierte Abfrage nur wenige Male benötigen, können Sie einfach $wpdb->query() verwenden. Es besteht keine Notwendigkeit, die Standardklasse zu ersetzen. Sie können auch eine benutzerdefinierte Klasse schreiben, die die Standardklasse erweitert, aber das wpdb-Objekt nicht überschreibt. In diesem Fall würden Sie $mycustomclass->method() verwenden, aber das ist nicht das Ende der Welt.

Abgesehen von dem offensichtlichen Coolness-Faktor ist das Erweitern der Standard-wpdb-Klasse etwas, das in WP gemacht werden soll und nicht hackisch ist, also zögern Sie nicht, damit zu spielen. Denken Sie dabei an zwei Dinge:

  • Wenn Sie Ihr Projekt jemandem schicken, vergessen Sie nicht, die Datei db.php ; es wird in keinem Theme- oder Plugin-Ordner sein
  • Behalte Änderungen in wp-db.php im Auge, da sie sich auf deine benutzerdefinierte Klasse auswirken könnten (obwohl das höchst unwahrscheinlich ist).