繁体   English   中英

是否可以使用字符串变量作为if块中的整个条件(不使用eval())?

[英]Is it possible to use a string variable as the entire condition in an if block (without using eval() )?

作为背景,我正在编写解析csv文件的PHP代码,并对每个csv文件的每一行执行某些操作。 什么“东西”取决于行中的值。 使用“if”结构测试值很容易,但是,硬编码条件并不是最佳的,原因有两个:

  1. 有几百个可能的条件需要测试。 那就是开始。 将来会增加更多条件。

  2. 每个csv行不需要针对每个条件进行测试; 只要行的条件评估为真,就不需要评估其他条件。

理想情况下,对于我的情况,“if”条件将存储在postgres表中,逐个放入字符串变量,然后每个变量将由单个if结构(在某种循环内)测试,直到条件为止评估为真。

简化示例:

$arrayOne[3] = "foo";

// in practice, the value of this variable would not be hard-coded;
// it would come from a postgres table
$conditionString="\$arrayOne[3] == \"VANILLA\"";

if($conditionString) {
    // do something, then exit the loop this if statement would be
    // inside of in actual practice
}

这个问题基本上是在问

PHP - 如果条件在字符串内

有三个基本答案:

  1. 你可以使用eval(),但不要! 这是邪恶的! (同意)
  2. 硬编码所有条件(由于上述原因和其他原因而不是最佳的)
  3. 将条件存储在模式中(这就是我正在做的),然后解析并转换为php代码。

解决方案3通常是我正在寻找的,但第二部分似乎效率低下且不必要地复杂。 毕竟,为什么只需要存储然后评估你需要的单个字符串就更容易了,为什么要从众多字符串(顺便提一下,这会使postgres中的存储变得复杂)中构建php代码?

有没有办法做到这一点?

非常感谢到目前为止的答复。 ComFreek,特别感谢您的详细回复。 你建议的解决方案可能正是我所需要的,但坦率地说,如果是这种情况,我没有经验立即知道。 我肯定会花时间试图理解你在说什么。 希望它能解决我的问题。

如果没有,同时回答其他人提出的几个问题:

1)if条件通常不简单。 许多将包含多个复合AND和OR测试。 伪代码中的样本条件可能是:(field2 ==“BUY”AND(strpos(“REINVEST DIVIDEND”,field6)或strpos(“CASH MERGER,field6))AND field2!=”TTXY“AND field3> 0)。

2)CSV文件来自众多金融机构。 它们包含大致相同的信息,但每个都有唯一的数据,并且所有数据都包含在不同位置的数据。 而且他们以不同的方式表达数据。 在某些情况下,付款用负数表示; 在其他人中,以正数表示。 有些人有单独的存款和取款领域; 一些表示存款和取款,另一栏中有代码。 等等。 代码需要确定交易的性质(信用卡购买,支票,股票买卖,退休金,等等)然后,如果可以的话,分配正确的借方/贷方账号(从图表中帐户)到该交易。 总而言之,有数百种可能的条件,可能成千上万。 (如果有人想知道,代码可以确定特定csv文件来自的机构,并将仅针对与该机构相关的条件测试该文件中的事务。)

3)代码需要足够灵活(以换句话说,无需编写新代码)允许将来添加新测试。 对我来说,能够为postgres表添加一个新条件(这将是要检查的代码的另一个测试)是足够的灵活性。

试图回答Phil的问题和评论(我可能没有正确理解):

1)我知道preg_match是什么,但还没有真正探索它能做什么,所以它实际上可能是我的问题的答案。 我会检查一下。

2)目前,代码不对事务进行分组(也就是说来自单个csv文件的单行); 相反,它查看每一行,确定它是什么,然后在适当的postgres表中存储一个额外的数据,然后移动到下一行。 交易存在某些“类型”(比如信用卡购买),但它们从未被分组以进行进一步处理。

3)每个交易应满足唯一条件(尽管该条件可能很复杂)。

4)关于匹配整个字符串,除非我遗漏了某些东西(非常可能),否则就不那么简单了。 例如,假设某个交易是股票购买。 代码可以通过查看“action”字段包含单词“Buy”并且“quantity”字段大于零来确定(仅这些条件中的一个或另一个可能不足以确定该交易是股票购买),但“自动收报机”字段可以是数千个事先未知的字符串中的任何一个 - “GOOG”,“MSFT”,“KO”或其他。

再次感谢所有回复到目前为止。

简介 :为特定的比较类型构建可扩展的处理程序系统,并将相关数据存储在数据库中。

你需要

  • 众所周知的各种条件
  • 可注册处理程序的可扩展系统,用于处理特定类型的条件(例如EqualityHandlerStringLengthComparisionHandler
  • 每个处理程序都与记录的对象格式相关联

优点

  • 该系统具有高度可扩展性。 如果你需要比较类型X或Y,只需编写一个处理程序。 这实际上与浏览器或编辑器的插件系统相当。

  • 您不在数据库中存储代码。 存储相同类型比较的代码完全违反DRY原则( 不要重复自己 )。

  • 单元测试。 当你有一个包含这些代码的数据库时,我无法想象单元测试是如何工作的。 他们真的很痛苦。

缺点

  • 它需要您在实际开始评估数据之前编写一些代码。

    然而,这种类型的问题实际上是为OOP解决方案而哭泣! 它真的教你如何应用和使用OOP。 至少在我看来,看到如何只添加一个处理程序为您的应用程序提供全新的功能,这很有趣!

伪代码

class EqualityHandler implements Handler
  public function handle($handlerData, $data) {
    // checks for equality and returns true or false
    return true;
  }
}
// TODO Act like Java: EqualityHandler.class (pass type of class)
$app->registerHandler('EqualityHandler');

// loop all rows
foreach ($row as $csvFields) {

  foreach  (retrieveConditions($row) as $condition) {
    handleCondition($condition, $csvFields);
  }

}

function handleCondition($condition, $csvFields) {
  if ($app->getHandler($condition['type'])) {
    return $app->instantiateHandler($condition['type'])->handle($condition, $csvFields);
  }
  else {
    throw new HandlerNotFoundException('...');
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM