提问请到论坛发帖,WordPress啦!主站上不再回复与文章内容无关的问题。
插件通过hook钩子(动作钩子和过滤器钩子)来扩展WordPress的功能。钩子能够改变WordPress的运行方式。有时插件需要执行自定义查询,这比在WordPress中加上动作钩子或是过滤器钩子要复杂得多。下面这篇文章介绍了自定义查询的相关信息,以及插件开发者怎样执行自定义查询。 注意:
背景知识介绍定义在本文中,查询指的是WordPress用来在主循环中寻找即将显示在页面上的日志列表的数据库查询(本文中的“数据库查询”即一般类型的数据库查询)。默认情况下,WordPress查询会查找属于当前页面的日志,无论是某一篇日志,或是静态页面、类别存档、日期存档、搜索结果、feed以及博客所有日志列表;查询日志限制在一定数量内(可以在WordPress后台的“设置”中设定),所有日志按时间逆序排列(最近发表的日志排在列表的最上方)。插件可以用自定义查询来改变日志排列顺序。例如:
WordPress默认运行方式修改WordPress中的默认查询前,我们需要了解WordPress的默认运行方式。查询语句概览中简要描述了WordPress生成博客页面的过程以及插件对该过程的修改。 执行自定义查询现在我们可以开始执行自定义查询了。接下来我们会用几个例子来说明怎样修改查询,开始时的例子比较简单,之后会慢慢过度到相对复杂的例子。 日志排列顺序与总数限制在第一个例子中,我们假设目前有一个glossary插件,网站/博客管理员可通过该插件将日志归入“glossary”类别(由插件保存在全局变量$gloss_category中)。我们希望达到的效果是:访问者访问glossary类别存档时看到的会是按字母顺序排列而不是按时间顺序排列的日志,是glossary类别下的所有日志而不是由网站管理规定显示数量的日志。 此时我们需要用以下两种方法来修改查询: 1. 为查询的ORDER BY语句加上一个过滤器钩子,将glossary类别下的日志列表改为字母顺序排列。过滤器钩子名为'posts_orderby',过滤SQL语句中ORDER BY后的内容。 2. 为查询的LIMIT语句加上一个过滤器钩子,解除日志的数量限制。过滤器钩子名为'post_limits',过滤SQL语句中包括包括LIMIT关键字在内关于日志数量限制的内容。 在上面两种方法中,过滤器函数都只会在我们浏览glossary类别时执行查询修改(用is_category函数进行逻辑操作)。因此,接下来我们需要编写如下代码:
add_filter('posts_orderby', 'gloss_alphabetical' );
add_filter('post_limits', 'gloss_limits' );
function gloss_alphabetical( $orderby )
{
global $gloss_category;
if( is_category( $gloss_category )) {
// alphabetical order by post title
return "post_title ASC";
}
// not in glossary category, return default order by
return $orderby;
}
function gloss_limits( $limits )
{
global $gloss_category;
if( is_category( $gloss_category )) {
// remove limits
return "";
}
// not in glossary category, return default limits
return $limits;
}删除某类别日志这里我们继续以glossary插件为例,这次我们希望能够禁止glossary类别下的日志出现在指定的页面上(主页与非类别存档页)以及feed中。要达到预期效果,首先要添加一个'pre_get_posts'动作钩子,该动作钩子能够探测当前访问者所请求的页面类型,之后根据页面类型删除glossary类别下的日志。根据查询说明(存储在$wp_query->query_vars中)中的规定,我们还可以在某个类别索引号前加上一个符号“-”以删除该类别。因此,修改后的代码如下:
add_action('pre_get_posts', 'gloss_remove_glossary_cat' );
function gloss_remove_glossary_cat( $notused )
{
global $wp_query;
global $gloss_category;
// Figure out if we need to exclude glossary - exclude from
// archives (except category archives), feeds, and home page
if( is_home() || is_feed() ||
( is_archive() && !is_category() )) {
$wp_query->query_vars['cat'] = '-' . $gloss_category;
}
}插件表中的关键字查找这个例子中我们假设目前有一个地域标签插件,插件为每一篇日志贴上一个或多个城市、州、乡村的标签。该插件将所有标签存在自备的数据库表中;我们假设数据库表名在全局变量$geotag_table中且表名具有geotag_post_id, geotag_city, geotag_state, geotag_country字段。我们希望在这个例子中,每当有人进行关键字查找时(WordPress默认关键字查找范围仅限于日志标题和正文),都能够查找到内容中带有插件表字段关键字的日志。 因此,我们需要通过多种方式来修改之前用于查找日志的SQL查询(在查找页面上例外):
结果代码显示如下:
add_filter('posts_join', 'geotag_search_join' );
add_filter('posts_where', 'geotag_search_where' );
add_filter('posts_groupby', 'geotag_search_groupby' );
function geotag_search_join( $join )
{
global $geotag_table, $wpdb;
if( is_search() ) {
$join .= " LEFT JOIN $geotag_table ON " .
$wpdb->posts . ".ID = " . $geotag_table .
".geotag_post_id ";
}
return $join;
}
function geotag_search_where( $where )
{
if( is_search() ) {
$where = preg_replace(
"/\(\s*post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"(post_title LIKE \\1) OR (geotag_city LIKE \\1) OR (geotag_state LIKE \\1) OR (geotag_country LIKE \\1)", $where );
}
return $where;
}
function geotag_search_groupby( $groupby )
{
global $wpdb;
if( !is_search() ) {
return $groupby;
}
// we need to group on post ID
$mygroupby = "{$wpdb->posts}.ID";
if( preg_match( "/$mygroupby/", $groupby )) {
// grouping we need is already there
return $groupby;
}
if( !strlen(trim($groupby))) {
// groupby was empty, use ours
return $mygroupby;
}
// wasn't empty, append ours
return $groupby . ", " . $mygroupby;
}
自定义存档这部分我们仍然以地域标签插件为例。首先假设我们需要用插件来激活类似于www.example.com/blog?geostate=oregon形式的自定义永久链接,让WordPress查找与“oregon”州名相符合的日志并显示在页面上。 要实现以上效果,插件必须进行以下操作:
|
|||

