各位观众老爷,大家好!我是今天的主讲人,老码农小李。今天咱们来聊聊 WordPress 里面那个神秘又常用的 wpdb 类,特别是它的 query_as_array() 方法。这玩意儿能把数据库查询结果变成咱们熟悉的关联数组,用起来那叫一个顺手。
咱们今天的目标就是:扒开它的底裤,看看它到底是怎么运作的!
一、wpdb 类,你是谁?
在深入 query_as_array() 之前,咱们先简单认识一下 wpdb 类。你可以把它想象成 WordPress 访问数据库的“总代理”。它封装了各种数据库操作,让你不用直接写那些复杂的 SQL 语句(当然,如果你喜欢,也可以直接写)。
wpdb 类提供了很多方法,比如 query()、get_results()、get_row() 等等,它们的功能各不相同,但最终目的都是为了从数据库里捞数据。
二、query_as_array():化腐朽为神奇
query_as_array() 方法,顾名思义,就是把查询结果转换成数组的。更准确地说,是关联数组,也就是可以用字段名作为键来访问数据的数组。
它的基本用法是这样的:
global $wpdb;
$results = $wpdb->query_as_array("SELECT * FROM wp_posts LIMIT 10");
if ($results) {
foreach ($results as $row) {
echo "Post Title: " . $row['post_title'] . "<br>";
echo "Post Content: " . $row['post_content'] . "<br>";
}
} else {
echo "No posts found.";
}
这段代码会从 wp_posts 表里取出前 10 条记录,然后把每条记录都转换成一个关联数组,方便你直接通过字段名访问数据。
三、源码剖析:一层一层扒开你的心
好了,废话不多说,直接上源码!(以下代码基于 WordPress 6.3.1 版本,不同版本可能会有细微差异):
/**
* Perform a query and return the entire result set as an array of associative arrays.
*
* This is a wrapper around {@see wpdb::get_results()}.
*
* @since 5.5.0
*
* @param string|null $query Optional. The SQL query to execute. Can be null to return the last query results.
* Default null.
* @param int $output Optional. The required return type. One of ARRAY_A, ARRAY_N, or OBJECT.
* Default ARRAY_A.
* @param int $y Optional. Offset of the returned row. Default 0.
* @return array|null An array of associative arrays representing the query result.
* Null if there is an error or no rows were returned.
*/
public function query_as_array( ?string $query = null, int $output = ARRAY_A, int $y = 0 ) {
return $this->get_results( $query, $output, $y );
}
看到没?query_as_array() 实际上只是 get_results() 方法的一个“马甲”!它只是简单地把 output 参数设置成了 ARRAY_A,然后调用了 get_results()。
所以,咱们的重点就转移到 get_results() 方法上了。
/**
* Perform a query and return the entire result set as an array.
*
* By default, returns an array of associative arrays, as in
* {@link https://www.php.net/mysqli_fetch_assoc mysqli_fetch_assoc()}.
*
* @since 2.0.0
* @since 3.5.0 The `$output` parameter accepts OBJECT, ARRAY_A, or ARRAY_N.
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string|null $query Optional. The SQL query to execute. Can be null to return the last query results.
* Default null.
* @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N.
* Default OBJECT.
* @param int $y Optional. Offset of the returned row. Default 0.
* @return array|object|null An array of results (usually associative arrays), null if there is an error.
*/
public function get_results( ?string $query = null, string $output = OBJECT, int $y = 0 ) {
global $wpdb;
// Bail early if there is no query to execute.
if ( empty( $query ) && empty( $this->last_query ) ) {
return null;
}
// Set the query to execute.
if ( empty( $query ) ) {
$query = $this->last_query;
}
// Clear the last result.
$this->last_result = null;
// Execute the query.
$result = $this->query( $query );
// Bail if there is an error.
if ( ! $result ) {
return null;
}
// Initialize variables to store the results.
$i = 0;
$j = 0;
$num_rows = $this->num_rows;
// If there are rows to return.
if ( $num_rows ) {
$this->last_result = array();
// Move the internal data pointer to the start of the result set.
if ( $y != 0 ) {
mysqli_data_seek( $this->dbh, $y );
}
// Fetch the results.
while ( $i < $num_rows ) {
if ( $output == OBJECT ) {
$this->last_result[ $i ] = mysqli_fetch_object( $this->dbh );
} elseif ( $output == ARRAY_A ) {
$this->last_result[ $i ] = mysqli_fetch_assoc( $this->dbh );
} elseif ( $output == ARRAY_N ) {
$this->last_result[ $i ] = mysqli_fetch_row( $this->dbh );
} else {
$this->last_result[ $i ] = mysqli_fetch_object( $this->dbh );
}
if ( $y != 0 && $i == $y ) {
break;
}
$i++;
}
// If we want a single row, return it.
if ( $i == 1 && ! empty( $this->last_result ) ) {
$this->last_result = $this->last_result[0];
}
mysqli_free_result( $this->dbh );
}
// Return null if there is no result.
if ( empty( $this->last_result ) ) {
return null;
}
// Return the result.
return $this->last_result;
}
好家伙,代码有点长,咱们一点一点分析:
-
参数处理:
$query:要执行的 SQL 查询语句。如果没有传入,就使用上次执行的查询语句。$output:指定返回结果的类型。它可以是OBJECT(对象)、ARRAY_A(关联数组)或ARRAY_N(数字索引数组)。 重点是,query_as_array()调用get_results()的时候,把这个参数设置成了ARRAY_A。$y:结果集的偏移量,表示从哪一行开始获取数据。
-
执行查询:
$result = $this->query( $query );:这行代码调用wpdb类的query()方法来执行 SQL 查询。query()方法负责连接数据库,发送 SQL 语句,并返回执行结果。- 如果查询失败,
get_results()会直接返回null。
-
处理查询结果:
$num_rows = $this->num_rows;:获取查询结果的行数。- 如果查询结果有数据,
get_results()会进入一个while循环,逐行处理结果集。 - 关键就在这里:
mysqli_fetch_assoc( $this->dbh );。这行代码使用 PHP 的mysqli_fetch_assoc()函数从结果集中获取一行数据,并将其转换成一个关联数组。$this->dbh是数据库连接句柄。
参数 说明 $this->dbh数据库连接句柄,指向当前连接的 MySQLi 资源。 mysqli_fetch_assoc()从结果集中获取下一行数据,并将其作为关联数组返回。数组的键是列名,值是对应列的值。 如果结果集中没有更多行,则返回 null。$this->last_result[ $i ] = mysqli_fetch_assoc( $this->dbh );:将获取到的关联数组存储到$this->last_result数组中。- 如果
$output参数是OBJECT,则使用mysqli_fetch_object()函数获取对象;如果$output参数是ARRAY_N,则使用mysqli_fetch_row()函数获取数字索引数组。 - 循环结束后,
$this->last_result数组就包含了所有查询结果,每个元素都是一个关联数组。
-
返回结果:
get_results()方法最终会返回$this->last_result数组。
四、mysqli_fetch_assoc():幕后英雄
现在,咱们来重点分析一下 mysqli_fetch_assoc() 函数。这个函数是 PHP 内置的,用于从 MySQLi 结果集中获取一行数据,并将其转换为关联数组。
它的工作原理很简单:
- 接收一个 MySQLi 结果集资源作为参数。
- 从结果集中读取下一行数据。
- 将每一列的数据以键值对的形式存储到一个数组中,其中键是列名,值是对应列的值。
- 返回这个数组。
- 如果结果集中没有更多行,则返回
null。
举个例子,假设你执行了以下 SQL 查询:
SELECT id, name, email FROM users WHERE id = 1;
查询结果如下:
| id | name | |
|---|---|---|
| 1 | John Doe | [email protected] |
那么,mysqli_fetch_assoc() 函数会将这行数据转换成以下关联数组:
array(
'id' => '1',
'name' => 'John Doe',
'email' => '[email protected]'
)
五、总结:query_as_array() 的工作流程
现在,咱们可以总结一下 query_as_array() 方法的工作流程了:
query_as_array()接收一个 SQL 查询语句作为参数。query_as_array()将output参数设置为ARRAY_A,并调用get_results()方法。get_results()方法执行 SQL 查询,并获取查询结果。get_results()方法使用mysqli_fetch_assoc()函数逐行处理查询结果,将每一行数据转换成一个关联数组。get_results()方法将所有关联数组存储到一个数组中,并返回该数组。query_as_array()方法将get_results()方法返回的数组作为自己的返回值。
简单来说,query_as_array() 就是 get_results() 方法的一个“快捷方式”,它帮你省去了设置 output 参数的麻烦。
六、注意事项:一些坑需要避开
- 性能问题: 如果查询结果集非常大,
query_as_array()可能会占用大量的内存。在这种情况下,可以考虑使用迭代器或者分页查询来减少内存消耗。 - 安全性问题: 在使用
query_as_array()方法时,一定要注意 SQL 注入攻击。不要直接将用户输入的数据拼接到 SQL 语句中,而是应该使用wpdb类的prepare()方法来对 SQL 语句进行转义。 - 错误处理: 在使用
query_as_array()方法时,一定要进行错误处理。如果查询失败,query_as_array()会返回null,你需要检查返回值是否为null,并根据情况进行处理。
七、高级用法:更上一层楼
除了基本用法之外,query_as_array() 还有一些高级用法,可以让你更灵活地处理查询结果:
- 指定偏移量: 你可以使用
$y参数来指定结果集的偏移量,从而只获取部分数据。 - 自定义处理: 你可以自定义一个函数来处理每一行数据,并将处理后的结果存储到数组中。
八、实例演示:代码才是王道
为了更好地理解 query_as_array() 方法,咱们来看几个实例:
实例 1:获取指定 ID 的文章标题
global $wpdb;
$post_id = 123;
$query = $wpdb->prepare("SELECT post_title FROM wp_posts WHERE ID = %d", $post_id);
$results = $wpdb->query_as_array($query);
if ($results) {
echo "Post Title: " . $results[0]['post_title'] . "<br>";
} else {
echo "Post not found.";
}
实例 2:获取所有文章的 ID 和标题,并存储到数组中
global $wpdb;
$query = "SELECT ID, post_title FROM wp_posts";
$results = $wpdb->query_as_array($query);
$posts = array();
if ($results) {
foreach ($results as $row) {
$posts[$row['ID']] = $row['post_title'];
}
}
print_r($posts);
实例 3:使用偏移量获取部分文章
global $wpdb;
$offset = 10;
$limit = 5;
$query = "SELECT ID, post_title FROM wp_posts LIMIT $offset, $limit";
$results = $wpdb->query_as_array($query);
if ($results) {
foreach ($results as $row) {
echo "Post ID: " . $row['ID'] . ", Post Title: " . $row['post_title'] . "<br>";
}
} else {
echo "No posts found.";
}
九、总结:掌握 query_as_array(),走遍天下都不怕
好了,今天的讲座就到这里。希望通过今天的讲解,你已经对 wpdb 类的 query_as_array() 方法有了更深入的了解。掌握了这个方法,你就可以更轻松地从 WordPress 数据库中获取数据,并将其转换成你需要的格式。
记住,代码才是王道!多写代码,多实践,你才能真正掌握这些知识。
下次有机会,咱们再聊聊 wpdb 类的其他方法。再见!