各位观众老爷,晚上好!今天咱们来聊聊 WordPress 数据库交互的核心角色——wpdb
类的 get_results()
方法,尤其是它如何把冷冰冰的数据库数据变成暖乎乎的对象数组,方便我们后续操作。
开场白:数据变形记,从SQL到对象
想象一下,你给数据库发了个指令(SQL 查询),它吭哧吭哧给你吐了一堆数据回来。这些数据就像杂乱无章的零件,需要我们组装成特定的模型。wpdb
类的 get_results()
方法就是这个组装大师,它负责把数据库返回的原始结果,按照你的需求,变成更容易使用的对象数组、关联数组等等。而对象数组,则是最常用的变形方式之一。
一、get_results()
方法的庐山真面目
首先,咱们来扒一扒 get_results()
方法的源码,看看它到底长啥样。
public function get_results( $query = null, $output = OBJECT ) {
global $wp_object_cache;
$this->func_call = __FUNCTION__;
if ( $query ) {
$this->last_query = $query;
}
// Bail early if there is no query to execute.
if ( empty( $this->last_query ) ) {
return null;
}
// Raw query results.
$this->result = null;
// Take note of the call time.
$this->timer_start();
// Use cache if available.
if ( $this->use_mysqli ) {
$cache_key = md5( $this->last_query );
$cache_group = 'mysqli-query';
if ( is_object( $wp_object_cache ) && $this->use_cache && isset( $wp_object_cache->cache[ $cache_group ][ $cache_key ] ) ) {
$this->num_queries++;
$this->queries[] = $this->last_query;
$this->query_times[] = $wp_object_cache->cache[ $cache_group ][ $cache_key ]['time'];
return $wp_object_cache->cache[ $cache_group ][ $cache_key ]['data'];
}
}
// If a transactional query is in process, hold off on caching.
if ( $this->in_transaction ) {
$this->suppress_cache = true;
}
// Run the query.
$this->result = @mysqli_query( $this->dbh, $this->last_query );
$this->timer_stop();
$this->num_queries++;
$this->queries[] = $this->last_query;
$this->query_times[] = $this->timer_elapsed;
// If there is an error then handle it.
if ( $this->last_error ) {
$this->print_error();
return false;
}
$this->num_rows = 0;
// If asking for raw results, return the mysql result.
if ( strtoupper( $output ) === OBJECT_K ) {
return $this->result;
}
// Store Query Results
if ( $this->result ) {
if ( is_object( $wp_object_cache ) && $this->use_cache && !$this->suppress_cache ) {
$cache_data = array();
}
while ( $row = @mysqli_fetch_object( $this->result ) ) {
$this->num_rows++;
$results[] = $row;
if ( is_object( $wp_object_cache ) && $this->use_cache && !$this->suppress_cache ) {
$cache_data[] = $row;
}
}
@mysqli_free_result( $this->result );
if ( is_object( $wp_object_cache ) && $this->use_cache && !$this->suppress_cache ) {
$wp_object_cache->cache[ $cache_group ][ $cache_key ] = array(
'time' => $this->timer_elapsed,
'data' => $cache_data,
);
}
// If returning a single row, return an object instead of an array.
if ( 'OBJECT' == $output && 1 == $this->num_rows ) {
return $results[0];
}
if ( empty( $results ) ) {
return array();
}
return $results;
} else {
return null;
}
}
别被这一大坨代码吓着,咱们一点点拆解。
二、流程分解:从查询到对象数组
get_results()
方法的主要工作流程可以概括为以下几个步骤:
- 接收查询语句和输出类型: 接受 SQL 查询语句(
$query
)和输出类型($output
)。默认输出类型是OBJECT
,也就是对象数组。 - 查询缓存(可选): 如果开启了缓存,并且缓存中存在对应查询的结果,则直接从缓存中返回,避免重复查询数据库。
- 执行查询: 使用
mysqli_query()
函数执行 SQL 查询,获取数据库返回的原始结果集。 - 处理结果集: 这是最关键的一步,
get_results()
方法会遍历结果集,并将每一行数据转换为对象,然后将这些对象放入一个数组中。 - 返回结果: 根据输出类型(
$output
)返回最终结果。如果$output
是OBJECT
,则返回对象数组。
三、核心代码剖析:mysqli_fetch_object()
的妙用
现在,咱们把目光聚焦到处理结果集的核心代码:
while ( $row = @mysqli_fetch_object( $this->result ) ) {
$this->num_rows++;
$results[] = $row;
if ( is_object( $wp_object_cache ) && $this->use_cache && !$this->suppress_cache ) {
$cache_data[] = $row;
}
}
这段代码是把原始数据变成对象数组的关键。mysqli_fetch_object()
函数闪亮登场!
-
mysqli_fetch_object( $this->result )
: 这个函数的作用是从结果集中取出一行数据,并将其转换为一个 对象。对象的属性名对应数据库表的字段名,属性值对应字段的值。例如,如果你的数据库表
wp_posts
有ID
、post_title
、post_content
这几个字段,那么mysqli_fetch_object()
返回的对象就会有$post->ID
、$post->post_title
、$post->post_content
这几个属性。 -
$results[] = $row;
: 将取出的对象$row
添加到$results
数组中。这样,循环结束后,$results
数组就包含了所有查询结果转换成的对象。
四、输出类型:$output
参数的选择
get_results()
方法的 $output
参数决定了返回结果的类型。它有以下几种取值:
输出类型 | 常量 | 返回值 |
---|---|---|
OBJECT |
OBJECT |
对象数组。每个元素都是一个对象,对象的属性对应数据库表的字段名和值。这是默认的输出类型。 |
ARRAY_A |
ARRAY_A |
关联数组数组。每个元素都是一个关联数组,数组的键名对应数据库表的字段名,键值对应字段的值。 |
ARRAY_N |
ARRAY_N |
索引数组数组。每个元素都是一个索引数组,数组的索引对应数据库表的字段顺序,数组的值对应字段的值。 |
OBJECT_K |
OBJECT_K |
谨慎使用:返回原始的 MySQLi 结果对象。这种方式直接返回 mysqli_query() 的结果,需要手动使用 mysqli_fetch_object() 等函数来处理结果集。通常不建议直接使用这种方式,因为它绕过了 wpdb 类的封装,代码可读性和可维护性较差。 同时,wpdb 类通常会在使用完结果对象后进行释放资源,如果直接返回 OBJECT_K ,可能会导致后续使用该结果对象时出现问题。建议使用其他的输出类型,例如 OBJECT ,ARRAY_A 或 ARRAY_N ,因为这些类型已经封装了结果集的处理,并返回更易于使用的数据结构。 |
五、实战演练:代码示例
为了更好地理解 get_results()
方法的使用,咱们来看几个代码示例。
示例 1:获取所有文章的标题
global $wpdb;
$query = "SELECT post_title FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'post'";
$posts = $wpdb->get_results( $query );
if ( $posts ) {
foreach ( $posts as $post ) {
echo $post->post_title . '<br>';
}
}
这段代码会查询 wp_posts
表中所有已发布的文章的标题,并将结果以对象数组的形式返回。然后,遍历对象数组,输出每个文章的标题。
示例 2:获取指定文章的 ID 和标题,并以关联数组的形式返回
global $wpdb;
$post_id = 123;
$query = $wpdb->prepare( "SELECT ID, post_title FROM {$wpdb->posts} WHERE ID = %d", $post_id );
$post = $wpdb->get_results( $query, ARRAY_A );
if ( $post ) {
echo '文章 ID:' . $post[0]['ID'] . '<br>';
echo '文章标题:' . $post[0]['post_title'] . '<br>';
}
这段代码会查询 wp_posts
表中 ID 为 123 的文章的 ID 和标题,并将结果以关联数组数组的形式返回。注意,这里使用了 $wpdb->prepare()
函数来防止 SQL 注入。
示例 3:使用 OBJECT_K
(不推荐,仅作演示)
global $wpdb;
$query = "SELECT * FROM {$wpdb->posts} WHERE post_status = 'publish' LIMIT 1";
$result = $wpdb->get_results( $query, OBJECT_K );
if ($result) {
// 使用 mysqli_fetch_object 手动处理结果
$row = mysqli_fetch_object($result);
if ($row) {
echo "Post Title: " . $row->post_title;
}
// 记得释放结果集资源
mysqli_free_result($result);
}
六、注意事项:SQL 注入和性能优化
在使用 get_results()
方法时,需要注意以下几点:
- 防止 SQL 注入: 永远不要直接将用户输入的数据拼接到 SQL 查询语句中。使用
$wpdb->prepare()
函数来对用户输入的数据进行转义,防止 SQL 注入攻击。 - 性能优化: 尽量避免执行复杂的 SQL 查询。可以使用 WordPress 内置的查询函数(例如
get_posts()
)来简化查询操作。如果需要执行自定义查询,可以考虑使用缓存来减少数据库查询次数。
七、总结:get_results()
方法的价值
wpdb
类的 get_results()
方法是 WordPress 数据库交互的核心方法之一。它提供了一种方便的方式来执行 SQL 查询,并将查询结果转换为对象数组、关联数组等易于使用的数据结构。通过合理地使用 get_results()
方法,可以轻松地从 WordPress 数据库中获取所需的数据,并将其应用于各种 WordPress 开发场景中。
掌握 get_results()
方法,就像掌握了一把开启 WordPress 数据库大门的钥匙。希望今天的讲解能帮助你更好地理解和使用这个强大的工具。
八、进阶思考:wp_query
与 get_results
的区别
很多同学可能会疑惑,wp_query
和 get_results
都是查询数据的,它们有什么区别呢?
简单来说,wp_query
是 WordPress 专门用于查询文章(post)的类,它封装了更高级的功能,例如分页、排序、分类等等。而 get_results
则是一个更通用的数据库查询方法,可以查询任何表,返回任何类型的数据。
特性 | WP_Query |
wpdb->get_results() |
---|---|---|
主要用途 | 查询文章(posts),支持复杂的文章查询条件。 | 执行任意 SQL 查询,不限于文章。 |
核心功能 | 文章循环、分页、taxonomy 查询、meta 查询等。 | 执行 SQL 查询,结果集处理。 |
使用场景 | 需要展示文章列表、文章详情等与文章相关的场景。 | 需要自定义 SQL 查询,访问非文章表,或者执行复杂查询的场景。 |
性能 | 针对文章查询进行了优化,但复杂的 WP_Query 也可能影响性能。 |
性能取决于 SQL 查询的效率。 |
安全性 | 内置了一些安全机制,例如参数过滤。 | 需要开发者自行处理 SQL 注入等安全问题。 |
你可以把 wp_query
看作是建立在 get_results
之上的一个更高级的封装。如果你只需要查询文章,并且需要使用 WordPress 内置的功能(例如分页),那么 wp_query
是更好的选择。如果你需要执行自定义的 SQL 查询,或者查询非文章表,那么 get_results
更加灵活。
今天的讲座就到这里,希望大家有所收获!下次再见!