【问题标题】:Matching "curly" quotes against standard quotes in DB query将“卷曲”引号与数据库查询中的标准引号匹配
【发布时间】:2019-04-24 04:03:12
【问题描述】:

我将文本存储在post_title 列中:

you’re

使用这个查询:

function ma_post_title_filter($where, &$wp_query) {
    global $wpdb;
    if ( $search_term = $wp_query->get( 'ma_search_post_title' ) ) {
        $search_term = sanitize_text_field($search_term);
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . $wpdb->esc_like( $search_term ) . '%\'';
    }
    return $where;
}

如果$search_termyou’re,它会工作并找到该列。但是当是you're时就不行了(因为是不同的单引号)。

如何改进查询,使you’reyou're 都与you’re 匹配?

到目前为止我已经尝试过什么

  1. $search_term 上使用str_replace()' 替换为。示例:str_replace('\'','’',$wpdb->esc_like( $search_term ))... 这种方法的问题是,如果存储的列是 you're,我们将永远无法匹配。
  2. '.$wpdb->posts.'.post_title 上执行AND REPLACE' 替换为...但似乎不起作用。

我知道理想的解决方案是将单引号的所有数据库实例调整为标准实例,但在我的情况下这是不可能的。

什么是正确的解决方案?

【问题讨论】:

  • 到目前为止我所尝试的部分很可爱。这里应该是标准的。 +1
  • 可能不适合,因为你不知道这是不是每次的搜索词,所以我删除了评论;)
  • 您是否尝试将 替换为 ',因为您的模式是 '.post_title LIKE \'%'
  • @forpas 什么时候更换?请参阅我的两个示例方法和说明为什么它不起作用。谢谢。
  • 你的模式是这样的:'.post_title LIKE \'%' 意味着你试图匹配',对吧?所以你申请str_replace('’', ''', $search_term)

标签: php mysql sql wordpress


【解决方案1】:

我会使用两次LIKE 语句,一次使用原始搜索词,第二次使用 替换'

您可以使用参数化查询。例如,使用wpdb::prepare()

$searchTerm = "You're"; //Don't sanitize using a function, this will by done with parameters.
// query
$where .= ' AND ('. $wpdb->posts .'.post_title LIKE %s OR '. $wpdb->posts .'.post_title LIKE %s)'; //Notice the double %s
//I suppose $where contains your whole query
$sth = $wpdb->prepare($where, '%' . $searchTerm . '%', '%' . str_replace('’', '\'', $search_term) . '%'); //This will associate the %s (a string) in the query by the value indicated in the function
$wpdb->query($sth);

%s 是查询中的placeholder,向$wpdb->prepare() 表明在这个地方会有一个字符串。

【讨论】:

  • 谢谢,但您能否通过示例来编辑您的答案,说明如何使用您的方法调整我的特定代码?
  • 好的,请稍等
  • @Cid 仅供参考,OP 正在使用 WordPress wpdb....
  • @GaryWoods 谢谢,我根据这种情况调整了答案
  • 是的,使用准备好的语句总是最好的方法,但是 Wordpress 让这很难做到。当涉及搜索查询时,原始问题中的函数由 WP 动态应用,因此实际执行在其他地方处理。
【解决方案2】:

你可以使用 MySQL RLIKE :

$where .= ' AND '. $wpdb->posts .'.post_title RLIKE \'.\*'. $wpdb->esc_like(str_replace(["’","'"],"['’]", $search_term) ) .'.\*\' ';

【讨论】:

  • OP 已经说过他们不能更改现有数据,但使用RLIKE 是个好主意;您应该编辑您的帖子以使您的代码更具可读性,并且应该得到一些支持。
【解决方案3】:

我想指出% 并不是唯一可以在LIKE 查询中使用的占位符。您也可以使用下划线_ 来表示单个字符。一种方法是用下划线替换某个类中的每个标点符号。这将允许“you're”匹配“you're”,反之亦然。 (当然,它也允许“youvre”匹配!)

<?php
function ma_post_title_filter($where, &$wp_query) {
    global $wpdb;
    $punct = ["’", "‘", "”", "“"];
    if ( $search_term = $wp_query->get( 'ma_search_post_title' ) ) {
        // escape any % or _ characters
        $search_term = $wpdb->esc_like($search_term);
        // replace desired punctuation characters with _
        $search_term = str_replace($punct, "_", $search_term);
        // do final escaping for safe queries
        $search_term = $wpdb->_real_escape($search_term);
        // this looks much neater with string interpolation vs concatenation
        $where .= " AND $wpdb->posts.post_title LIKE '%$search_term%'";
    }
    return $where;
}

在将值传递给LIKE 子句时,您应该使用wpdb::esc_like() 以确保任何用户提供的百分号或下划线都不会妨碍操作。 sanitize_text_field() 是在输出到 HTML 之前使用的,它不会使数据库查询的文本安全。这就是wpdb::_real_escape() 的用途。

【讨论】:

  • 感谢您提供的出色方法,但它不起作用。 $where 有错字吗?这是an example code,您可以使用它来测试它。我觉得这个问题很可能是一个错字,因为代码本身非常合乎逻辑!
  • 删除$wpdb-&gt;real_escape($search_term); 部分似乎至少允许代码运行。但是$string_term = "you're";仍然与标题为you’re的帖子不匹配。
  • 我没有办法对此进行测试,但我建议在代码的各个点打印出$search_term,并执行相同操作以查看$where 的样子。跨度>
  • 你运行的是什么版本的 Wordpress?
  • 我使用的是最新版本。
猜你喜欢
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 2011-02-19
  • 2015-07-30
  • 1970-01-01
  • 2011-01-30
相关资源
最近更新 更多