Php 高级基于标记的搜索字符串解析

Php 高级基于标记的搜索字符串解析,php,Php,我正在尝试使用标记进行高级搜索,这些标记可以将特定关键字与特定字段相关联,如: 搜索:测试消息状态:已关闭用户:john 想知道将字符串解析为一个漂亮数组的最佳方法是什么,如下所示: [搜索=>测试消息,状态=>已关闭,用户=>john] 目前我是这样做的: $parse = explode(':', $_REQUEST['q']); $parsed = []; foreach($parse AS $key => $value) { if($key == (count($parse)

我正在尝试使用标记进行高级搜索,这些标记可以将特定关键字与特定字段相关联,如:

搜索:测试消息状态:已关闭用户:john

想知道将字符串解析为一个漂亮数组的最佳方法是什么,如下所示:

[搜索=>测试消息,状态=>已关闭,用户=>john]

目前我是这样做的:

$parse = explode(':', $_REQUEST['q']);
$parsed = [];
foreach($parse AS $key => $value) {
  if($key == (count($parse) - 1))
   break;
  $next = explode(' ', $parse[($key + 1)]);
  $last = array_pop($next);
  $next = implode(' ', $next);
  $parse[($key + 1)] = $last;
  $parsed[$parse[$key]] = !empty($next) ? $next : $last;
}

这里有一个替代解决方案,但我可以肯定,如果我们可以使用regexp,这是最优雅的解决方案,我只是想不出模式:

$string = "search: test message status: closed user: john";
$pieces = explode(' ', $string);
$values = array();
$array = array();
foreach ($pieces as $piece) {
    if (strpos($piece, ":") !== false) {
        if (count($values)) {
            $array[$key] = join(" ", $values);
        }
        $key = rtrim($piece, ":");
        $values = array();
    } else {
        $values[] = $piece;
    }
}
$array[$key] = join(" ", $values);
var_dump($array);
输出

array
  'search' => string 'test message' (length=12)
  'status' => string 'closed' (length=6)
  'user' => string 'john' (length=4)
编辑

根据tntu的评论,下面是一个带有regex的版本:

$string = "search: test message status: closed user: john";
$matches = array();
preg_match_all('/(([a-z]+):([a-z0-9 ]+(?![a-z:])))+/is', $string, $matches);
$i = 0;
foreach ($matches[2] as $key) {
    if (isset($matches[3][$i])) {
        $array[$key] = trim($matches[3][$i]);
    } else {
        break;
    }
    $i++;
}

我认为如果你让你的客户提交一个包含已拆分参数的查询字符串会容易得多:yoursite.com?search=testmessage&status=closed&user=johnth这不是问题。我可以在提交时用JS进行上述解析。我想找到一种更好的方法将字符串解析为标记/值对。最好是苹果、谷歌等公司在电子邮件应用程序中的做法。一种在任何条件下都适用的方法。我不确定这个解决方案是否能很好地工作。您的用户是如何组成搜索字符串的?他们是手动输入的还是您的客户端代码从表单或其他东西生成的?他们是手动输入的。哦。。。等等所以你这里有工作代码。。。如果你的代码没有实际问题,除了你认为它可以做得更好/更干净之外,那么我认为这篇文章更适合:代码审查堆栈交换是一个供同行程序员代码审查的问答网站。/[a-z]+:[a-z0-9]+?![a-z:][+/isI我希望不会出现问题,因为我将使用全文索引查询mysql,只进行完全匹配和部分匹配,这是由于我拥有的可接受字符的限制。对于一个更宽松的接受角色的政策来说,事情可能会变得棘手。我计划添加基于js的输入验证,并在字符串无效时阻止提交或搜索。始终执行服务器端验证,因为js可能会受到攻击。在服务器端,我执行清理。除了字母数字、空格和冒号外,所有内容都被点画出来。没有风险。