如何自定义 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
中的变化,因为它们可能会影响您的自定义类(尽管这极不可能)