WordPress是最好的博客平台和一般CMS系统之一。它的灵活性证明了它背后惊人的代码库。在本文中,我想介绍系统的“更深”领域之一,$wpdb类。
$wpdb类是一个直接与数据库交互的简单实用工具。台山网络公司如果您熟悉WordPress代码,您可能已经看到get_post()函数或WP_Query类。这些允许您以灵活的方式检索帖子,但有时您只需要更多。$wpdb类允许您模块化地添加/修改/删除WordPress中的任何数据,使其成为一个非常强大的工具。但是要小心,强大的力量带来了巨大的责任(以及令人敬畏的特性)。
什么是wpdb?
Wpdb是一个基于Justin Vincent的ezSQL类的类。它为我们提供了一种与WordPress数据库对话的简单方法。$wpdb是该对象的am实例。它是创建NY WordPress的,您所需要做的就是开始使用它。
什么时候使用wpdb?
通过直接与WordPress数据库对话,您可以提供更复杂的特性。WordPress为用户、帖子、分类法提供了很多功能,但是如果你添加了一些不同的功能--比如时间跟踪工具--怎么办?在某些情况下,提供的函数就是不切断它。这就是Wpdb的目的--一种安全和标准化的直接操作数据库的方法。
什么时候不使用wpdb?
老实说,你不应该使用wpdb的时间远远大于你应该使用的次数。当面对这个系统的开放性时,我很想用我自己的代码在我自己的表中做所有的事情。用Wpdb实现图书管理系统听起来不错,但当您可以使用自定义POST类型和自定义分类法时,这是很愚蠢的。
始终尝试和使用WordPress-本机功能第一。如果这是不可能的,或者太不方便,那就去做吧。
开始
Wpdb可以在任何地方使用。它对您来说是实例化和全球化的,所以您所需要做的就是开始编写代码。当然,只有在函数中才有例外,您必须将其全球化。
在详细了解所有可用方法之前,让我们先看看一个简单的示例,即检索一个POST ID列表。
?
1 | $my_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_author = 24" ); |
这其中有三个部分我们应该讨论。
- get_coll()是一种方法,它将从所讨论的表中检索一列。我们还可以使用get_var()获取单个值,也可以使用get_row()来提取单行。
- 查询本身就是下一个,这是标准SQL。您可以在这里写入将执行的任何查询,结果以所使用的方法(get_coll()、get_var()等)确定的方式返回。
- $wpdb->post是指向post表的变量。您可能习惯于POST表是wp_post,但情况并不总是如此。每当引用表时,始终使用适当的变量。
既然我们已经解决了这个问题,剩下的就很简单了,我们只需要检查所有可用的方法
检索数据
从WordPress表读取数据时,需要:
- 获取单个数据(检索作者所有帖子上的评论总数)
- 获取单个行(获取特定日期后发布的第一篇文章的详细信息)
- 获取一列(由单个作者获取所有草稿的ID)
- 获取多个行和列(获取注释计数为6或更多的所有帖子的id和标题)
有四种方法符合这些需要,这里有一些简单的例子;
?
1 | $comments = $wpdb->get_var( "SELECT SUM(comment_count) FROM $wpdb->posts WHERE post_author = 3 " ); |
在上面的例子中,我们计算了给定作者的注释总数。$Comments变量应该包含一个值。
?
1 | $after_birthday = $wpdb->get_col( "SELECT * FROM $wpdb->posts WHERE post_status = 'publish' AND post_date > '2013-05-12 00:00:00' " ); |
执行此查询后,$After_生日变量应该包含一个对象,其成员对应于字段名。您可以显示通过使用检索到的帖子标题;
?
1 | echo $after_birthday->post_title; |
请注意这里的任何查询,以及检索多个值的查询。使用“*”检索所有数据通常不是一个好主意,因为它效率低下。如果我们只是使用数据库调用来显示帖子列表,那么我们真的需要‘post_content_filter’和‘to_ping’字段吗?我们甚至不需要‘POST_Content’,这可能相当大。确保只选择你真正需要的!
?
1 | $author_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_author = 24 AND post_status = 'draft' " ); |
在上面的例子中,$Author_post应该是一个简单的、一维的POST ID数组。
?
1 | $most_discussed = $wpdb->get_results( "SELECT ID, post_title, comment_count FROM $wpdb->posts WHERE comment_count > 6 ORDER BY comment_count DESC " ); |
上面讨论的$变量将是一个数组对象。您可以遍历这个数组并轻松地显示所有的帖子。
?
1 2 3 4 5 | echo '<ul>'; foreach( $most_discussed as $item ) { echo '<li><a href="' . get_permalink( $item->ID ) . '">' . $item->post_title . '</a></li>'; } echo '</ul>'; |
请注意,虽然这个示例运行良好,但它并不是我在生产环境中实际使用的,稍后会详细介绍。
添加到数据库中
wpdb类准备使用INSERT()方法将东西添加到数据库中。这种方法的一般用途如下:
?
1 | $wpdb->insert( $table, $data, $format ); |
您需要知道要添加到哪个表,需要准备要添加的数据数组和使用的格式数组。以身作则!
假设我们添加了时间跟踪功能,并且我们有一个表,它允许我们存储时间条目。它包含以下字段:id、start_time、end_time、jobid、user_id。我们可以添加像这样的条目,表示计时器的启动(因此没有结束时间)。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $table = $wpdb->prefix . 'timetracking'; $data = array( 'start_time' => '2013-06-20 17:32:23', 'end_time' => '', 'job_id' => 44, 'user_id' => 145 ); $format = array( '%s', '%s', '%d', '%d' ); $wpdb->insert( $table, $data, $format ); |
注意,由于我们台山网络公司使用的是自定义表,所以没有像POST表那样为表名预定义的变量。在本例中,我们可以使用$wpdb->前缀来获取表前缀,然后在它后面添加我们的表名。
$data数组应该是不言自明的,它是一个将表列和它们的数据绑定在一起的数组。
$Format数组按照$Data数组中给定的顺序确定每个列的格式。这里的可能值是字符串的%s、整数的%d和浮点数的%f。
一旦添加了项,您就可以使用$wpdb->INSERT_id变量访问自动增量ID。
如果您以前使用过数据库,您可能会注意到这里缺少转义值。这是因为如果您使用wpdb类提供的专门方法,则值将为您转义。
修改数据库条目
继续我们的时间跟踪示例,我们可以假设,每当有人停止计时器时,我们就会将结束时间添加到前面所做的条目中。
一般来说,我们使用如下的UPDATE()方法:
?
1 | $wpdb->update( $table, $data, $where, $format = null, $where_format = null ); |
首先,您需要指定适当的表,然后是数据(只有您正在修改的数据)、执行更新的条件、数据的格式和标准的格式。如果没有给出格式,则整个字符串都被假定为字符串。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $table = $wpdb->prefix . 'timetracking'; $data = array( 'end_time' => '2013-06-20 21:13:45' ); $where = array( 'ID' => 34 ); $format = array( '%s' ); $where_format = array( '%d' ); $updated = $wpdb->update( $table, $data, $where, $format, $where_format ); |
正如您所看到的,这与插入的方式非常相似。值将为您转义,并在成功操作时返回更新的行数。
运行任何查询
到目前为止,我们已经了解了三个基本操作:插入、更新和选择。有时,您需要执行其他操作,如删除某些内容,或非常复杂的更新,这些更新将需要定制查询,而您只是无法适应任何可用的方法。在这种情况下,您可以使用query()方法。
?
1 | $wpdb->query( "DELETE FROM $wpdb->posts WHERE comment_count < 3 AND post_author = 16 AND post_status = 'publish' " ); |
虽然这非常简单,但您很可能永远不会单独使用query()方法。这个方法不会为您转义值,在绝大多数情况下,您将使用变量作为参数,所以我们需要自己转义--或者我们会吗?
当然,有一个名为prep()的方便方法,它将为您完成繁重的工作。使用它有点像使用sprintf()函数。我们将用占位符替换所有变量,并将它们单独添加为参数。下面是:
?
1 2 3 4 5 6 7 8 9 10 11 12 | $comment_count = 3; $post_author = 16; $post_status = 'publish'; $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE comment_count < %d AND post_author = %d AND post_status = %s ", $comment_count, $post_author, $post_status ) ); |
占位符使用与以前相同的格式-%s用于字符串,%d用于整数,%f用于浮点。准备()方法以查询(带有占位符)作为其第一个参数,然后以与查询中显示的顺序相同的方式为占位符的值。
注意,即使占位符是在查询中使用的,如果占位符是字符串,也不需要将它们放在引号中,该方法将处理所有这些问题。
在某些情况下,您可能不知道传递给查询的变量的数量。幸运的是,您还可以使用具有数组的准备()方法作为第二个参数,而不是使用一个值列表:
?
1 2 3 4 5 6 7 8 9 10 | $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE comment_count < %d AND post_author = %d AND post_status = %s ", array( $comment_count, $post_author, $post_status ) ) ); |
疑难解答问题
当数据库介入时,找出某些东西不起作用的原因可能是一件痛苦的事。您是否传递了正确的数据,您是否错误地键入了列名,表名是否正确,等等。有几种方法可以帮助你自己。
您可以使用$wpdb->Show_error()来显示错误,使用$wpdb->隐藏_error()确保打开(或关闭)错误报告。
?
1 | $wpdb->print_error() will display errors from the most recent query, if there are any. |
实际使用
能够决定何时需要使用$wpdb是非常重要的。使用它来选择帖子几乎总是多余的,因为WP_Query类在这方面非常强大,因此它几乎总是一个更好的选择。
不使用wpdb
不要忘记,在使用WP_Query类、get_post()函数或任何其他函数时,将运行多个操作和筛选器。这使得您的代码更加模块化,如果您是插件或主题开发人员,这就是您想要的。
使用$wpdb,您将直接(或足够接近)与数据库交互,因此您的代码将变得更难与之交互。
我建议尽可能多地使用post表并随后使用WordPress循环,这完全是因为WP_Query的强大功能。虽然这不是我考虑过的事情,但我可能会使用自定义的POST类型来跟踪时间,并使用postmeta来保存时间数据。原因如下。
当您的项目以与POST相同的形式(即:在POST表中)时,编写前端代码所需的时间就会少得多。您可以使用循环,您可以自动分页您的项目,您可以访问模板层次结构(如果您创建了一个单一的timetracking.php,您刚刚创建了单个POST视图),依此类推。您的功能将很容易启用或禁用,而不会损害其他部分的网站。
使用wpdb一点
我经常看到代码使用wpdb根据一些复杂的条件检索帖子,后面跟着一个foreach循环来显示这些帖子。这是可行的,但我发现更优雅的解决方案是只在可能的情况下检索ID,并将它们提供给循环,如下所示:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | $post_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_author IN ( SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'age' AND 'meta_value' > 32 ) AND post_type = 'post' AND post_status = 'publish' " ); global $wp_query; $temp_query = $wp_query; $wp_query = null; $args = array( 'posts_per_page' => 8, 'post__in' => $post_ids, ); $wp_query = new WP_Query( $args ); if( have_posts() ) { while( have_posts() ) { the_post(); get_template_part( 'layout', 'post' ); } } $wp_query = $temp_query; wp_reset_postdate(); |
首先,我们找到帖子作者超过32岁的帖子ID。然后通过输入这些帖子ID和我们想要显示的帖子数量来创建一个新的WordPress查询。然后,我们循环遍历返回的帖子,并使用lay-post.php文件显示POST。
如果您想知道$temp_query的所有胡说八道是什么,我只是确保我们不会干扰常规WordPress循环。在所有页面上创建并填充$wp_query。我们希望确保我们的自定义小循环不会覆盖或取代它的位置。我们存储原始循环,然后在最后恢复它。
大量使用wpdb
有些情况下需要全面使用wpdb类。建立一个内部广告跟踪系统的多种广告类型与AB测试,其他这样的细节肯定需要一些wpdb魔术。每当您需要在数据库中创建自定义表时,您都需要依赖wpdb来提升数据。
如果是这样的话,那么很好地利用这个类将确保即使是高度专门化和自定义的代码也尽可能地保持可访问性和模块化。
总结性
正如我们台山网络公司所看到的,wpdb对于那些希望在WordPress站点、插件或主题中构建自定义功能的人来说是非常有用的伙伴。虽然你应该避免使用,如果你没有必要-如果你真的需要它,这是一个天赐。