忽略 WordPress 查询中的“the”

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费额度!

以下是由 Jason Witt 发布的文章。 在这里,Jason 分享了一种方法,您可以认为这种方法非常简单,但事实证明它比您想要的要复杂一些。 幸运的是,借助 Jason 的代码和示例,它可以变得很容易。

最近,我需要创建一个自定义的 WordPress 查询,按字母顺序列出文章标题。 我从这样的基本查询开始。

$my_query = new WP_Query(array(
  'post_type'  => 'post',
  'orderby'    => 'title',
  'order'      => 'ASC'
));

我的结果是

从技术上讲,结果是按字母顺序排列的,但不是我想要的方式。 我希望如果标题以“the”开头,则忽略“the”,并改为按下一个单词进行字母排序。 期望的顺序应如下所示

“the”被称为 *首字母词*。 你知道:“A”、“An”和“The”,有时放在专有名词开头的东西。 如果您想国际化,可以包括“La”(西班牙语)和“Les”(法语)。 在经过大量搜索和梳理 WordPress Codex 之后,我找不到用于忽略首字母词的原生 WordPress WP_Query 解决方案。

我发现有两个非常有用的过滤器可以让我实现这一点,posts_fieldsposts_orderby。 通过一点 SQL 知识和 PHP 技巧。 我能够获得期望的结果。

也许不出所料,这是一个非常普遍的需求。 想象一个音乐库。 将所有以“The”开头的乐队都归类到“T”下会不必要地造成混淆。 相反,它应该是这样的

如何操作

让我与您分享我是如何做到的,以便您可以在任何需要对 WordPress 查询进行字母排序并忽略首字母词的 WordPress 项目中使用它。

在您的 `functions.php` 文件中,添加以下两个函数。

function wpcf_create_temp_column($fields) {
  global $wpdb;
  $matches = 'The';
  $has_the = " CASE 
      WHEN $wpdb->posts.post_title regexp( '^($matches)[[:space:]]' )
        THEN trim(substr($wpdb->posts.post_title from 4)) 
      ELSE $wpdb->posts.post_title 
        END AS title2";
  if ($has_the) {
    $fields .= ( preg_match( '/^(\s+)?,/', $has_the ) ) ? $has_the : ", $has_the";
  }
  return $fields;
}

function wpcf_sort_by_temp_column ($orderby) {
  $custom_orderby = " UPPER(title2) ASC";
  if ($custom_orderby) {
    $orderby = $custom_orderby;
  }
  return $orderby;
}

第一个函数 wpcf_create_temp_column 将在查询时创建一个名为“title2”的虚拟表列。 它使用文章的标题填充表列。 如果标题包含首字母词“The”,则将其删除。

第二个函数 wpcf_sort_by_temp_column 创建一个新的自定义 orderby。 它使用 ASC 顺序按虚拟表列“title2”对文章进行排序。

要让这些函数在 *您的* 查询中发挥作用,您只需将它们添加到我之前提到的过滤器中即可。

add_filter('posts_fields', 'wpcf_create_temp_column');
add_filter('posts_orderby', 'wpcf_sort_by_temp_column');

现在,您的查询将按字母顺序对文章标题进行排序,同时忽略首字母词“The”。 如果您想添加其他要忽略的首字母词,您只需将它们包含到 wpcf_create_temp_column 函数中的 $matches 变量中,并用管道字符分隔即可。

$matches = 'A|An|The|La|Les';

现在假设您有多个按标题排序的 WordPress 查询,但您不想将这些过滤器应用于这些查询。 通过在 `functions.php` 文件中添加过滤器,它们将影响您网站上的每个查询,因此您可能不希望这样做。 更不用说它可能会通过使用不必要的过滤器来影响您网站的性能。 以下是如何将这些过滤器应用于特定查询。

首先从 `functions.php` 文件中删除 add_filter 函数。 然后在具有所需查询的模板文件中,像这样放置 add_filter 函数以及 remove_filter 函数。

add_filter('posts_fields', 'wpcf_create_temp_column'); // Add the temporary column filter
add_filter('posts_orderby', 'wpcf_sort_by_temp_column'); // Add the custom order filter

$query = new WP_Query(array('post_type' => 'post')); // Your custom query

remove_filter('posts_fields','wpcf_create_temp_column'); // Remove the temporary column filter
remove_filter('posts_orderby', 'wpcf_sort_by_temp_column'); // Remove the temporary order filter 

if (have_posts()) : while ($query->have_posts()) : $query->the_post(); // The query output

  the_title(); 
  echo '<br/>';

endwhile; endif; wp_reset_postdata();

在上面的代码中,您正在添加过滤器、执行查询,然后立即删除过滤器。 通过将查询代码包装在过滤器中,您可以将这些过滤器隔离到该特定查询。

排序愉快!