【问题标题】:PHP way to execute SQL LIKE matching without a database query?无需数据库查询即可执行 SQL LIKE 匹配的 PHP 方法?
【发布时间】:2009-02-18 21:01:51
【问题描述】:

我想将输入字符串与我的 PHP 页面进行匹配,就像 SQL (MySQL) 中的 LIKE 命令完成的匹配一样,以保持其他搜索的一致性。由于(我见过但不理解)一些 PHP 语法包括 SQL 命令,我想知道这是否可能?

这样做的原因是我现在正在搜索关键字与数据库中存储在序列化数组中的字段,我必须在 PHP 中取消序列化并根据数组的结构进行搜索。我不能对表进行查询,只需要查询的匹配能力。否则我需要找到一个替代的匹配例程,这将是不一致的。我不能回去重新构建数据库,因为这在规范中没有预料到。是的,我需要一个丑陋的 hack,但我正在寻找最优雅的。

如果不可能,我可以使用任何将用户键入的文本作为关键字与存储文本匹配的建议。

编辑(澄清):我的主要问题是我没有彻底掌握 LIKE 命令的工作原理(只是复制代码),并且由于关键字暗示某种程度的模糊性,我希望保留这种模糊性,如果我切换到正则表达式。我对正则表达式更好,只是对喜欢不太好。我的查询是“LIKE 'matchme%'”

【问题讨论】:

  • 从用户的角度看查询如何?是否允许他们输入通配符,例如“%”,还是只能输入纯文本?
  • 用户提供文本,我在幕后添加通配符。我确实使用了 1%。喜欢'文本%'
  • 老兄 - LIKE 是确定性的。这是字符串搜索。在数据库中进行。
  • Matt,它作为序列化数组存储在数据库中。我不知道为什么,但它就在他的文字中。
  • OIS:是的,我现在明白了。我的错。谢谢!

标签: php sql pattern-matching full-text-search sql-like


【解决方案1】:

更新

根据 tomalak 的评论和 OIS 使用 preg_grep 的绝妙想法,这可能更像是您的最终解决方案。

<?php

function convertLikeToRegex( $command )
{
    return "/^" . str_replace( '%', '(.*?)', preg_quote( $command ) ) .  "$/s";
}

function selectLikeMatches( $haystack, $needle )
{
    return preg_grep( convertLikeToRegex( $needle ), $haystack );
}

$likeClauses = array(
    '%foo'
    ,'foo%'
    ,'%foo%'
);

$testInput = array(
    'foobar'
    ,'barfoo'
    ,'barfoobaz'
);

foreach ( $likeClauses as $clause )
{
    echo "Testing $clause:";
    echo '<pre>';
    print_r( selectLikeMatches( $testInput, $clause ) );
    echo '</pre>';
}

下面是原帖

这符合你的追求吗?

<?php

function convertLikeToRegex( $command )
{
    return "/^" . str_replace( '%', '(.*?)', $command ) .  "$/s";
}

$likeClauses = array(
    '%foo'
    ,'foo%'
    ,'%foo%'
);

$testInput = array(
    'foobar'
    ,'barfoo'
    ,'barfoobaz'
);

foreach ( $testInput as $test )
{
    foreach ( $likeClauses as $clause )
    {
        echo "Testing '$test' against like('$clause'): ";
        if ( preg_match( convertLikeToRegex( $clause ), $test ) )
        {
            echo 'Matched!';
        } else {
            echo 'Not Matched!';
        }
        echo '<br>';
    }
    echo '<hr>';
}

【讨论】:

  • 为什么不将所有正则表达式的东西封装在一个函数中:“Like(haystack, needle)”?这样,您的函数调用更具可读性,并且没有人会弄乱函数从外部工作的方式。另外,$command 需要用 "\Q" 和 "\E" 转义,否则它会在某些时候失败。
  • 另外,替换不需要使用惰性点,也不需要捕获组。
  • @BaileyP:我认为 convertLikeToRegex() 不需要是一个单独的函数。除了 selectLikeMatches() 之外,我看不到结果没有真正的用途。我之前已经 +1 了。
  • Q 海报有一个带有文本的数组,并获取一个搜索字符串。他为 sql 搜索添加 % 或为正则表达式搜索添加 ^/$。从类似 sql 的搜索字符串转换为正则表达式搜索字符串正在解决核心问题,即在数组中搜索文本。
  • @BailyP:1)这如何再次解决原来的问题? 2)这对你来说很优雅吗?
【解决方案2】:

其实你需要的是preg_grep

$arr = array("tstet", "duh", "str");
$res = preg_grep("#st#i", $arr); //i for case insensitive
var_dump($res);

结果

array(2) {
  [0]=>
  string(5) "tstet"
  [2]=>
  string(3) "str"
}

编辑:

用户提供文本,我添加 幕后的通配符。我确实使用 一 %。喜欢'文本%'

这是您在正则表达式中指定的方式

"#st#i"  regex is the same as in sql "%st%"
"#^st#i" regex is the same as in sql "st%"
"#st$#i" regex is the same as in sql "%st"

另外,请记住在您从第三方获得的任何文本上使用 preg_quote。 $正则表达式 = "#" 。 preg_quote($text) 。 “#一世”; $res = preg_grep($regex, $arr);

【讨论】:

    【解决方案3】:

    我认为您需要preg_match,但这与 LIKE 的行为并不完全相同。

    <?php // The "i" after the pattern delimiter indicates a case-insensitive search 
    if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
        echo "A match was found."; 
    } else {
        echo "A match was not found."; } 
    ?>
    

    【讨论】:

    • 不需要使用正则表达式,我会使用更快的strpos()。
    【解决方案4】:

    您的意思是您希望能够检查输入字符串是否为 LIKE var% ?

    你可以使用 strpos(haystack, needle) 来匹配 %var%。

    if( strpos($source, "var") == 0 ) echo "matches var%";
    if( strlen($source) - (strpos($source, "var")) == strlen("var") ) echo "matches %var";
    

    这太丑了。实际上可能不是最优雅的。

    【讨论】:

    • 第一个测试应该是 === 0,因为如果 var 不在 $source strpos 中,则返回 false,即 == 0 但不是 === 0。
    • %var 是 substr($source,-strlen("var")) == "var"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2023-04-09
    • 2015-07-10
    • 1970-01-01
    相关资源
    最近更新 更多