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

  • 有数百种可能的条件需要测试。这只是开始。将来会增加更多条件。
  • 不需要为每个条件测试每个csv行;只要行的条件评估为真,就无需评估其他条件。

  • 理想情况下,对于我的情况,“if”条件将存储在postgres表中,一个接一个地放入字符串变量中,然后每个变量将由单个if结构(在某种类型的循环内)进行测试,直到出现一个条件评估为true。

    简化示例:
    $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 - if condition inside string

    有三个基本答案:
  • 您可以使用eval(),但不要!太邪恶了! (同意)
  • 对所有条件进行硬编码(由于上述及其他原因而并非最佳)
  • 将条件存储在架构中(这是我正在做的事情),然后解析并转换为php代码。

  • 解决方案3通常是我要寻找的,但是第二部分似乎效率低下并且不必要地复杂。毕竟,为什么在存储和评估所需的单个字符串似乎要容易得多的情况下,为什么要从众多字符串(顺便说一句,个未知数)构建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)关于匹配整个字符串,除非我(非常可能)缺少某些内容,否则就不是那么简单。例如,假设给定的交易是购买股票。该代码可以通过查看“操作”字段包含单词“购买”并且“数量”字段大于零来确定(仅这些条件中的一个或另一个可能不足以确保交易是购买股票) ),但“ticker”字段可以是预先未知的数千个字符串中的任何一个-“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('...');
      }
    }
    

    关于php - 是否可以在if块中使用字符串变量作为整个条件(不使用eval())?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21054275/

    10-16 18:24