长话短说,我有一个报告系统,允许用户输入自定义逻辑。
例如,他们的逻辑可能是1 AND (2 OR 3) AND 4
。
逻辑中的每个数字代表一个过滤条件。如果过滤条件匹配,则会将该号码替换为true
,否则会将该号码替换为false
。
我想找到一种方法来验证上面的逻辑是否符合标准。所以我创建了以下代码并使用MySQL来检查它:
// The filter criteria...
$filters = array(
'1' => true,
'2' => false,
'3' => true,
'4' => true
);
// The users custom logic
$logic = '1 AND (2 OR 3) AND 4';
// Put brackets around each number so that 10 doesn't conflict with 1
$logic = preg_replace("/([0-9]+)/", "[\\1]", $logic);
// $logic now looks like: [1] AND ([2] OR [3]) AND [4]
// Go through each filter and replace the relevant number
foreach($filters AS $filter_id => $filter_bool) {
$logic = str_replace('[' . $filter_id . ']', $filter_bool, $logic);
}
// $logic now looks like: true AND (false OR true) AND true
// Check the query logic using MySQL
$match = $mysql->get_row("SELECT (" . $logic . ") AS result");
// Result
if ($match->result == 1)
echo 'Filters match!';
else
echo 'Failed!';
我的问题是,有没有办法让我在不使用MySQL的情况下验证逻辑?如果我有10,000条记录要验证,它必须进行10,000次MySQL调用以检查每一条。
希望我有意义:)提前谢谢!
答案 0 :(得分:1)
如果你有php 5.3,你可以尝试使用http://symfony.com/doc/current/components/expression_language/introduction.html#usage
答案 1 :(得分:0)
您需要将$logic
格式化为此
SELECT * FROM
booltest
WHERE1
= 1 AND(2
= 1或3
= 1)AND4
= 1
将此表与tinyint(1)一起用于BOOL,其中1 == true 0 == false
CREATE TABLE IF NOT EXISTS `booltest` (
`id` int(2) NOT NULL,
`1` tinyint(1) NOT NULL,
`2` tinyint(1) NOT NULL,
`3` tinyint(1) NOT NULL,
`4` tinyint(1) NOT NULL
);
和测试表
INSERT INTO `booltest` (`id`, `1`, `2`, `3`, `4`) VALUES
(1, 1, 0, 1, 1),
(2, 0, 0, 0, 1),
(3, 0, 0, 0, 1),
(4, 0, 0, 1, 0),
(5, 0, 1, 0, 0),
(6, 1, 0, 0, 0);
请参阅SqlFiddle
答案 2 :(得分:0)
感谢@valex和@deceze,我最终使用了eval。
我做了一个测试循环,我运行了1,000,000次(可能有点过分),看看哪个更快,eval
平均为13秒,其中MYSQL平均为92秒。哇!巨大的差异。
我的eval
代码:
$query = 'true AND (false OR true) AND true';
eval("if (" . $query . ") \$valid = 1; else \$valid = 0;");
if ($valid === 1)
echo 'Match!';
else
echo 'Failed!';
我必须向人们发出警告,有关PHP文档中有关使用eval
的信息。
eval()语言构造非常危险,因为它允许执行任意PHP代码。因此不鼓励使用它。如果您已经仔细验证除了使用此构造之外没有其他选择,请特别注意不要将任何用户提供的数据传递到其中,而不事先正确验证它。
确保在使用eval
之前清除并验证所有用户输入的代码。
现在必须这样做,但我希望将来找到更好的解决方案。