当术语具有特殊字符时转义WP_QUERY TAX_QUERY

时间:2015-03-09 作者:Philip Downer

这是我的问题。我有一个自定义的帖子类型,并将自定义分类附加到该类型。这种分类法允许管理员提供搜索建议,以确保在用户搜索时找到帖子。该分类法还用于前端,以使用这些建议自动完成搜索字段。

系统工作正常,除非术语包含正斜杠、空格或其他“特殊”字符。

<?php
$keyword = \'Ski-in%2FSki-out\';//Submitted via $_GET
$keyword = urldecode($keyword); // (string)\'Ski-in/Ski-out\'

$taxQuery = new WP_Query(array(
    \'post_type\' => \'ml_properties\',
    \'tax_query\' => array(
        \'relation\' => \'OR\',
        array(
            \'taxonomy\' => \'mc_tax_lifestyle\',
            \'field\' => \'name\',
            \'terms\' => array($keyword),
            \'operator\' => \'IN\'
        )
    )
));
?>
我已经考虑过使用WordPress提供的转义功能,但在这方面没有任何运气。我原以为这是一个简单的问题,但要么我的谷歌浏览器不够强大,要么我就是运气不好。

我也证实了Ski-in/Ski-out 是存储在MySQL中的精确字符串。我已经考虑过使用esc_attr(), $wpdb->esc_like()esc_sql() 但都没有效果。

也许我错过了一些明显的东西?

1 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

我不确定这是否是一个bug,但需要进一步调查。我已经对name a中的字段tax_query, 每当一个术语名称有一个特殊字符或有多个单词时tax_query 从SQL查询中排除

测试1我在这里使用了两个术语,你的术语Ski-in/Ski-out 还有我测试网站上的一个术语Uit die koskas. 现在,如果我按如下方式运行自定义查询

$taxQuery = new \\WP_Query(array(
    \'post_type\' => \'post\',
    \'tax_query\' => array(
        array(
            \'taxonomy\' => \'category\',
            \'field\' => \'name\',
            \'terms\' => \'Ski-in/Ski-out\',
            \'operator\' => \'IN\'
        )
    )
));
?><pre><?php var_dump($taxQuery->request); ?></pre><?php    
thevar_dump() 请求的一部分给了我这个

string(254) "SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID 
FROM wp_posts  
WHERE 1=1  
AND ( 
      0 = 1
    ) 
AND wp_posts.post_type = \'post\' 
AND (wp_posts.post_status = \'publish\' 
OR wp_posts.post_status = \'private\') 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0, 4"
Thetax_query 未附加到SQL查询

测试2如果您使用一个没有特殊字符的单词术语,则查询可以工作。在这里,我用一个叫做Ongekategoriseerd

$taxQuery = new \\WP_Query(array(
    \'post_type\' => \'post\',
    \'tax_query\' => array(
        array(
            \'taxonomy\' => \'category\',
            \'field\' => \'name\',
            \'terms\' => \'Ongekategoriseerd\',
            \'operator\' => \'IN\'
        )
    )
));
?><pre><?php var_dump($taxQuery->request); ?></pre><?php
这为我提供了正确的SQL查询

string(378) "SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  
INNER JOIN wp_term_relationships 
ON (wp_posts.ID = wp_term_relationships.object_id) 
WHERE 1=1  
AND ( 
      wp_term_relationships.term_taxonomy_id 
IN (1)
    ) 
AND wp_posts.post_type = \'post\' 
AND (wp_posts.post_status = \'publish\' 
OR wp_posts.post_status = \'private\') 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC 
LIMIT 0, 4" 
我还不确定这是故意的还是bug,但在此期间,您可以查看WP_Query 源代码,并查看tax_query 是构建。我也会在不久的将来调查此事

更新1我很快浏览了WP_Query 上班前上课。课程快结束时,WP_Query 进行一些向后兼容性测试,从eye value来看,这似乎是所有操作都失败的地方,而这反过来又会导致在SQL查询中附加join子句失败。

我找不到有关此问题的trac票证,如果有,任何人都有链接,请随时更新我的答案或在评论中发布。

解决方法

如果需要并且必须使用术语名称,则应使用get_term_by(). 然后,您可以使用术语名称来获取术语对象,并使用其中的术语ID来在tax_query

更新2找到它,问题不在WP_Query 本身(看看这些类,真是一团糟)。WP_Query 使用WP_Tax_Query 构建tax_query. 检查do_action 在中调用parse_tax_query 中的方法WP_Query

$this->tax_query = new WP_Tax_Query( $tax_query );
很好,移动到WP_Tax_Query 班此类具有以下方法,transform_query 将单个查询从一个字段转换为另一个字段。这就是当你设置field 参数到name

使用field 设置为name, 该名称已使用sanitize_title_for_query

$terms = "\'" . implode( "\',\'", array_map( \'sanitize_title_for_query\', $query[\'terms\'] ) ) . "\'";
这将删除斜杠并将空白转换为hypens。这意味着Ski-in/Ski-out 已转换为ski-inski-outUit die koskas 已转换为uit-die-koskas. 由于您的术语名称无效,以下查询将获取术语id及其子项,

$terms = $wpdb->get_col( "
    SELECT $wpdb->term_taxonomy.$resulting_field
    FROM $wpdb->term_taxonomy
    INNER JOIN $wpdb->terms USING (term_id)
    WHERE taxonomy = \'{$query[\'taxonomy\']}\'
    AND $wpdb->terms.{$query[\'field\']} IN ($terms)
" );
失败并返回空数组

array(0) {
}
结论:这里的卫生设施是错误的,应该用一种更合适的方法来代替,这种方法允许使用单个空格和斜杠。拥有name 字段,如果无法正确使用术语名称。这种卫生设施杜绝了name a中的字段tax_query 在上述情况下。

如前所述,如果需要使用术语名,最好的方法可能是在使用get_term_by() 从术语中获取ID,然后在tax_query

更新3

感谢@manifestphil在评论中,有changeset #31346 就在这个疯狂的消毒问题上。希望在将来的版本中修复此问题

结束

相关推荐

Disable escaping html

我在用SyntaxHighlighter Evolved 突出显示代码示例。E、 g。[csharp] string s = \"text\"; List<int> numbers = new List<int>(); [/csharp] 当我第一次保存它时,没关系,但编辑wordpress时,文本会更改为[csharp] string s = &quot;text&quot;; List&lt;int&am