Jak dostosować klasę wpdb i dodać nowe metody?

Opublikowany: 2018-07-10

Warstwa abstrakcji bazy danych WordPress, popularnie znana jako wpdb, to klasa oparta na ezSQL odpowiedzialna za interakcję z bazą danych. Klasa wpdb to także drop-in – fragment podstawowego kodu WP, który można łatwo zastąpić innym fragmentem kodu o podobnej funkcjonalności (aktualna lista drop-inów jest dostępna w WP Code Reference).

Modyfikowanie domyślnej klasy #wpdb nie jest skomplikowane. Możesz łatwo dodawać, usuwać lub modyfikować tylko kilka metod. Nie ma potrzeby wymiany całej klasy. #wordpress

KLIKNIJ, ABY TWEETOWAĆ

W tym miejscu pojawia się wielkie nieporozumienie. Ludzie postrzegają „zastąpiony” jako „napisz własną, kompletną klasę bazy danych”. Na szczęście nie musisz pisać całej klasy bazy danych. Możesz wziąć istniejącą klasę i dodawać, usuwać lub modyfikować tylko te funkcje, których potrzebujesz. I to właśnie zamierzamy zrobić.

Po co modyfikować klasę wpdb?

Z pewnością wpdb ma wszystko, czego potrzebujesz!? Na nim zbudowana jest cała WP. Technicznie to prawda. Używając metody $wpdb->query() , możesz wykonać dowolne polecenie SQL. Ale po zastosowaniu tej logiki nigdy nie mielibyśmy ani nie potrzebowalibyśmy metod takich jak $wpdb->insert() lub $wpdb->get_var() . Ale robimy to, ponieważ oszczędzają czas, redukują błędy i odstraszają złe zapytania. Jakich funkcji brakuje? To zależy od projektu, nad którym pracujesz. Potrzebowaliśmy wsparcia dla tych dwóch zapytań:

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

Krok #1 – Utwórz drop-in

Proces tworzenia drop-in DB jest prosty, a wynik końcowy płynnie wtapia się w WP.
Utwórz plik o nazwie db.php i umieść go w folderze /wp-content/ . Nadaj plikowi standardowy nagłówek wtyczki i utwórz klasę rozszerzającą wpdb. Coś takiego:

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

Nagłówek jest dość oczywisty. Metoda build zapewnia, że ​​tworzymy nowe połączenie DB po skonstruowaniu obiektu i używa do tego oryginalnego konstruktora wpdb. Te stałe DB są zdefiniowane w wp-config.php . Jak powiedzieliśmy na początku – po prostu dodajemy kilka funkcji i wykorzystujemy wszystko inne. Druga metoda test() służy wyłącznie do sprawdzenia, czy wszystko działa poprawnie.

Kluczowe są dwie ostatnie linijki. Ponieważ jest to klasa niestandardowa, WP nie utworzy automatycznie dla nas obiektu $wpdb . Musimy to zrobić sami. Pamiętaj, aby użyć słowa kluczowego global , ponieważ w przeciwnym razie utworzysz zmienną lokalną.

Krok #2 – Przetestuj przed głębszym kopaniem

Otwórz pulpit nawigacyjny WP i przejdź do wtyczek. Oprócz zwykłych zakładek Wszystkie, Aktywne i Nieaktywne (wtyczki) zobaczysz zakładkę Wtyczki, a w niej, dzięki magii, nasza niestandardowa klasa bazy danych.

Ponieważ administrator działa poprawnie, wiemy, że wykonaliśmy dobrą robotę. Nasza nowa, niestandardowa, rozszerzona klasa jest już dostępna i nic się nie zmieniło. Świetny! Ale na wszelki wypadek umieść te trzy linijki kodu w pliku functions.php motywu (lub gdzieś we wtyczce, gdzie zostanie natychmiast uruchomiony):

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

Uruchom dowolną stronę administracyjną lub front-endową i co widzisz? “ Rozszerzony wpdb jest uruchomiony. " Idealny. Teraz czas na nasze funkcje w świecie rzeczywistym.

Krok #3 – Twórz, modyfikuj lub zamieniaj funkcje

Zapytanie INSERT IGNORE wydaje się dość łatwe do wykonania. Mamy już $wpdb->insert(), więc brakuje nam tylko jednego słowa. Niestety ze względu na brak filtrów w odpowiednich miejscach nie będą to dwie linijki kodu.

Jeśli otworzysz wp-db.php i przejdziesz do metody insert() w wierszu #2100, zobaczysz, że używa ona metody _insert_replace_helper() z wiersza #2151. A ta funkcja nie ma pojedynczego filtra ani akcji. Nie możemy też zawinąć funkcji, ponieważ natychmiast zwraca wynik zapytania, a nie samo zapytanie, które moglibyśmy zmodyfikować. Porażka. Będziemy musieli przesłonić metody insert() i _insert_replace_helper() . Dodamy dodatkowy parametr – $ignore . Wartość logiczna z domyślną wartością false .

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

W każdej innej sytuacji funkcja mająca pięć parametrów byłaby dobrym kandydatem do przekształcenia ich w tablicę asocjacyjną. Ale chcemy kompatybilności wstecznej, więc tego nie robimy. Zmiany w drugiej funkcji są również niewielkie:

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

Dlaczego programiści nie robią tego częściej?

Jeśli potrzebujesz niestandardowego zapytania tylko kilka razy, możesz łatwo użyć $wpdb->query() . Nie ma potrzeby zastępowania klasy domyślnej. Możesz także napisać niestandardową klasę, która rozszerza klasę domyślną, ale nie przesłania obiektu wpdb. W takim przypadku użyjesz $mycustomclass->method() , ale to nie koniec świata.

Oprócz oczywistego czynnika chłodu, rozszerzenie domyślnej klasy wpdb jest czymś, co ma być zrobione w WP i nie jest hackowe, więc możesz się z tym bawić. Pamiętaj o dwóch rzeczach:

  • kiedy wysyłasz komuś swój projekt, nie zapomnij dołączyć pliku db.php ; nie będzie go w żadnym folderze motywów ani wtyczek
  • miej oko na zmiany w wp-db.php , ponieważ mogą one wpłynąć na twoją niestandardową klasę (chociaż jest to bardzo mało prawdopodobne)