如何自定義 wpdb 類並添加新方法
已發表: 2018-07-10WordPress的數據庫抽象層,俗稱wpdb,是一個基於ezSQL的類,負責與數據庫交互。 wpdb 類也是一個插件——一段核心 WP 代碼,可以很容易地被另一段具有類似功能的代碼替換(WP 代碼參考中提供了最新的插件列表)。
修改默認的#wpdb 類並不復雜。 您可以輕鬆地添加、刪除或修改幾個方法。 無需更換整個班級。 #wordpress
點擊推文這是一個很大的誤解發揮作用的地方。 人們將“替換”視為“編寫我自己的、完整的數據庫類”。 幸運的是,您不必編寫整個數據庫類。 您可以使用現有的類並僅添加、刪除或修改您需要的功能。 這就是我們要做的。
為什麼要修改 wpdb 類?
當然,wpdb 有你需要的一切!? 整個 WP 都建立在它之上。 從技術上講,這是正確的。 通過使用$wpdb->query()
方法,您可以執行任何 SQL 命令。 但是應用了這種邏輯,我們將永遠不會擁有或需要像$wpdb->insert()
或$wpdb->get_var()
的方法。 但我們這樣做了,因為它們可以節省時間、減少錯誤並避免錯誤查詢。 那麼,缺少哪些功能呢? 這取決於您正在從事的項目。 我們需要對這兩個查詢的支持:
INSERT IGNORE INTO tbl_name ...
INSERT INTO tbl_name ... ON DUPLICATE KEY UPDATE ...
步驟 #1 – 創建插件
創建數據庫插件的過程很簡單,最終結果可以無縫融入 WP。
創建一個名為db.php
的文件並將其放在/wp-content/
文件夾中。 給文件一個標準的插件頭並創建一個擴展 wpdb 的類。 像這樣的東西:
<?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();
標題是不言自明的。 構造方法確保我們在構造對像後創建一個新的數據庫連接,並為此使用原始的 wpdb 構造函數。 這些 DB 常量在wp-config.php
中定義。 正如我們在開始時所說的那樣——我們只是添加了一些功能並重用了其他所有內容。 第二種方法test()
純粹是為了看看一切是否正常。
最後兩行至關重要。 由於這是一個自定義類,WP 不會自動為我們創建$wpdb
對象。 我們必須自己做。 請記住使用global
關鍵字,否則,您將創建一個局部變量。
步驟 #2 – 在深入挖掘之前進行測試
打開您的 WP 儀表板並轉到插件。 除了通常的 All、Active 和 Inactive(插件)選項卡之外,您還會看到一個 Drop-ins 選項卡,其中,通過某種魔術,我們的自定義數據庫類。
由於管理員工作正常,我們知道我們做得很好。 我們新的、自定義的、擴展的類在裡面,沒有任何改變。 偉大的! 但是,為了更好的衡量,將這三行代碼放入主題的functions.php
(或插件內的某個地方,它將立即運行):
global $wpdb; $wpdb->test(); die;
運行任何管理或前端頁面,你會看到什麼? “擴展的 wpdb 正在運行。 “ 完美的。 現在為我們的現實世界的功能。
步驟 #3 – 創建、修改或替換函數
INSERT IGNORE
查詢似乎很容易做到。 我們已經有了 $wpdb->insert() 所以我們只是少了一個單詞。 不幸的是,由於在正確的地方缺少過濾器,它不會是兩行代碼。
如果您打開 wp-db.php 並前往 #2100 行的insert()
方法,您會看到它使用了 #2151 行的_insert_replace_helper()
方法。 而且該功能沒有單個過濾器或操作。 我們也不能包裝該函數,因為它會立即返回查詢結果,而不是我們可以修改的查詢本身。 真可惜。 我們必須重寫insert()
和_insert_replace_helper()
方法。 我們將添加一個額外的參數 - $ignore
。 默認值為false
的布爾值。
public function insert( $table, $data, $format = null, $ignore = false ) { return $this->_insert_replace_helper( $table, $data, $format, 'INSERT', $ignore = false ); }
在任何其他情況下,具有五個參數的函數都可以很好地將它們轉換為關聯數組。 但是我們想要向後兼容,所以我們不這樣做。 對其他功能的更改也很小:
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 ) ); }
為什麼開發人員不經常這樣做呢?
如果您只需要幾次自定義查詢,您可以輕鬆使用$wpdb->query()
。 無需替換默認類。 您還可以編寫一個擴展默認類但不覆蓋 wpdb 對象的自定義類。 在這種情況下,您將使用$mycustomclass->method()
但這不是世界末日。
除了擴展默認 wpdb 類的明顯酷炫因素之外,這是在 WP 中完成的事情,而且不是 hackish,所以請隨意使用它。 請記住兩件事:
- 當您將項目發送給某人時,不要忘記包含
db.php
文件; 它不會出現在任何主題或插件文件夾中 - 密切關注
wp-db.php
中的變化,因為它們可能會影響您的自定義類(儘管這極不可能)