将简单规则与PHP代码分开

时间:2010-09-20 15:23:33

标签: php

目前我有一些PHP根据线性格式的其他自变量的值设置单个变量,如下所示:

$result = 0;

if ($var1 == 'X') {
  $result += 10;
}

if ($var2 < 10) {
  $result += 15;
}
elseif ($var2 > 50) {
  $result -= 50;
}

// more of the same

但是,我希望能够以类似编程的方式表达这些规则,主要是因为不知道如何编程的人可以添加/编辑规则,还因为我可能想要使用Python或Perl脚本中的相同规则,无需使用多种语言维护副本。我可以编写自己的简单语言(因为想要更好的单词)和解析器,但我更喜欢使用现有的解决方案,因为这可以节省工作并增加其他人知道如何在其中编写规则的可能性。

这类任务是否有合理/明显的选择?

4 个答案:

答案 0 :(得分:1)

我认为你不需要语言/解析器。您可以创建表达式构建器(类似于创建电子邮件过滤器规则的方式)并将结果存储在数据库中。这也将允许其他语言访问存储的规则。

用户会在满意之前添加比较,然后输入关联的分配规则。

答案 1 :(得分:1)

设计一些伪语言并将其转换为PHP代码。

$var1 == 'X': +10
$var2 < 10:   +15
$var2 > 50:   -50

现在您可以使用PHP Tokenizer来解析它并将其转换为真正的PHP代码。然后你应该缓存生成的代码并将其作为PHP文件包含。

这是一个非常快速和脏的实现,使用我自己的TokenStream类(但您可以轻松地将其移植到本机标记器):

<?php
    $code =<<<'EOC'
$var1 == 'X': +10

$var2 < 10:   +15
$var2 > 50:   -50
EOC;

    require '../tokenstream/src/TokenStream.php';

    $tokenStream = new TokenStream('<?php ' . $code);
    $code = '';
    foreach ($tokenStream as $i => $token) {
        if ($token->is(T_OPEN_TAG)) {
            $code .= '<?php $result = 0;' . PHP_EOL . 'if (';
        }
        elseif ($token->is(T_WHITESPACE) && preg_match("[\r\n]", $token->content)) {
            $code .= ';' . $token . 'if (';
        }
        elseif ($token->is(T_COLON)) {
            $code .= ') $result += ';
        }
        else {
            $code .= $token;
        }
    }
    $code .= ';';

    echo '<pre>', htmlspecialchars($code), '</pre>';

真的很快又脏。你可以执行任意代码。为了更好的实现,您需要实现一个状态机,我现在没有时间;)

脚本输出:

<?php $result = 0;
if ($var1 == 'X') $result +=  +10;

if ($var2 < 10) $result +=    +15;
if ($var2 > 50) $result +=    -50;

答案 2 :(得分:0)

您可以使用Chain of ResponsibilityCommand模式。

还有PHPRules,它允许您以语言无关的格式指定规则。

答案 3 :(得分:0)

我将构建一个简单的解析,并使用制表符分隔的文本文件来存储值。

相关问题