简体   繁体   English

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

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

As background, I'm writing php code that parses csv files and does something with each row of each csv file. 作为背景,我正在编写解析csv文件的PHP代码,并对每个csv文件的每一行执行某些操作。 What that "something" is depends on the values in the row. 什么“东西”取决于行中的值。 It's easy to test the values with an "if" structure, however, hardcoding the conditions is not optimal for two reasons: 使用“if”结构测试值很容易,但是,硬编码条件并不是最佳的,原因有两个:

  1. there are several hundred possible conditions to be tested. 有几百个可能的条件需要测试。 That's just to begin with. 那就是开始。 More conditions will be added in the future. 将来会增加更多条件。

  2. Each csv row does not need to be tested for each condition; 每个csv行不需要针对每个条件进行测试; as soon as a condition for a row evaluates to true, no further conditions need be evaluated. 只要行的条件评估为真,就不需要评估其他条件。

Ideally, for my situation, the "if" conditions would be stored in a postgres table, put into a string variable one by one, and then each variable would tested by a single if structure (inside a loop of some kind) until a condition evaluates to true. 理想情况下,对于我的情况,“if”条件将存储在postgres表中,逐个放入字符串变量,然后每个变量将由单个if结构(在某种循环内)测试,直到条件为止评估为真。

Simplified example: 简化示例:

$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
}

This question was essentially asked at 这个问题基本上是在问

PHP - if condition inside string PHP - 如果条件在字符串内

There were three basic answers: 有三个基本答案:

  1. You could use eval(), but DON'T! 你可以使用eval(),但不要! It's evil! 这是邪恶的! (agreed) (同意)
  2. Hard-code all the conditions (not optimal for reasons provide above and others) 硬编码所有条件(由于上述原因和其他原因而不是最佳的)
  3. Store the conditions in a schema (which is what I'm doing) and then parse and convert to php code. 将条件存储在模式中(这就是我正在做的),然后解析并转换为php代码。

Solution 3 is generally what I'm looking for, but second part seems inefficient and unnecessarily complex. 解决方案3通常是我正在寻找的,但第二部分似乎效率低下且不必要地复杂。 After all, why build up php code from numerous strings (of an unknown number, by the way, which complicates storage in postgres) when it seems so much easier to just store and then evaluate the single string you need? 毕竟,为什么只需要存储然后评估你需要的单个字符串就更容易了,为什么要从众多字符串(顺便提一下,这会使postgres中的存储变得复杂)中构建php代码?

Is there a way to do that? 有没有办法做到这一点?

Many thanks for the responses so far. 非常感谢到目前为止的答复。 ComFreek, thanks to you in particular for the detailed response. ComFreek,特别感谢您的详细回复。 The solution you suggest may be just what I need, but frankly, I don't have the experience to know immediately if that's the case. 你建议的解决方案可能正是我所需要的,但坦率地说,如果是这种情况,我没有经验立即知道。 I'll definitely spend time trying to understand what you're saying. 我肯定会花时间试图理解你在说什么。 Hopefully, it will solve my problem. 希望它能解决我的问题。

In case it doesn't, and in the meantime, to answer a few questions others asked: 如果没有,同时回答其他人提出的几个问题:

1) the if conditions will not usually be simple. 1)if条件通常不简单。 Many will contain multiple and compound AND and OR tests. 许多将包含多个复合AND和OR测试。 A sample condition, in pseudo-code, might be: ( field2=="BUY" AND ( strpos("REINVEST DIVIDEND", field6) OR strpos("CASH MERGER, field6) ) AND field2!="TTXY" AND field3>0 ). 伪代码中的样本条件可能是:(field2 ==“BUY”AND(strpos(“REINVEST DIVIDEND”,field6)或strpos(“CASH MERGER,field6))AND field2!=”TTXY“AND field3> 0)。

2) The CSV files come from numerous financial institutions. 2)CSV文件来自众多金融机构。 They contain much the same information, but each has unique data, and all of them have the data in different locations. 它们包含大致相同的信息,但每个都有唯一的数据,并且所有数据都包含在不同位置的数据。 What's more they express the data differently. 而且他们以不同的方式表达数据。 In some, a payment is indicated by a negative number; 在某些情况下,付款用负数表示; in others, by a positive number. 在其他人中,以正数表示。 Some have separate fields for deposits and withdrawals; 有些人有单独的存款和取款领域; some indicate deposits and withdrawals with a code in another column. 一些表示存款和取款,另一栏中有代码。 And so on. 等等。 The code needs to determine the nature of the transaction (credit card purchase, check, stock buy or sell, retirement contribution, and on and on) and then, if it can, assign the correct debit/credit account numbers (from a chart of accounts) to that transaction. 代码需要确定交易的性质(信用卡购买,支票,股票买卖,退休金,等等)然后,如果可以的话,分配正确的借方/贷方账号(从图表中帐户)到该交易。 Altogether, there are hundreds of possible conditions, likely to become thousands. 总而言之,有数百种可能的条件,可能成千上万。 (In case anyone is wondering, the code can determine the institution a particular csv file comes from and will test the transactions in that file only against conditions relevant to that institution.) (如果有人想知道,代码可以确定特定csv文件来自的机构,并将仅针对与该机构相关的条件测试该文件中的事务。)

3) The code needs to be flexible enough to easily (in other words, without having to write new code) allow for new tests to be added in the future. 3)代码需要足够灵活(以换句话说,无需编写新代码)允许将来添加新测试。 For me, being able to add a new condition to a postgres table (which will then be another test for the code to check) is sufficient flexibility. 对我来说,能够为postgres表添加一个新条件(这将是要检查的代码的另一个测试)是足够的灵活性。

To try to answer Phil's questions and comments (which I may not be understanding correctly): 试图回答Phil的问题和评论(我可能没有正确理解):

1) I know what preg_match is, but haven't really explored what it can do, so it may in fact be the answer to my problem. 1)我知道preg_match是什么,但还没有真正探索它能做什么,所以它实际上可能是我的问题的答案。 I'll check it out. 我会检查一下。

2) currently, the code does not group transactions (which is to say a single row from a single csv file); 2)目前,代码不对事务进行分组(也就是说来自单个csv文件的单行); rather, it looks at each row, determines what it is, then stores it an additional data in appropriate postgres tables, then moves to the next row. 相反,它查看每一行,确定它是什么,然后在适当的postgres表中存储一个额外的数据,然后移动到下一行。 There are certain "types" of transactions (say credit card purchases) but they're never grouped for further processing. 交易存在某些“类型”(比如信用卡购买),但它们从未被分组以进行进一步处理。

3) Each transaction should satisfy one and only condition (though that condition may be complex). 3)每个交易应满足唯一条件(尽管该条件可能很复杂)。

4) With regard to matching the entire string, unless I'm missing something (very possible), it's not that simple. 4)关于匹配整个字符串,除非我遗漏了某些东西(非常可能),否则就不那么简单了。 For example, let's say a given transaction is a stock purchase. 例如,假设某个交易是股票购买。 The code can determine that by seeing that "action" field contains the word "Buy" AND the "quantity" field is greater than zero (one or the other of these conditions alone might not be enough to be certain the transaction is a stock purchase), but the "ticker" field could be any of thousands of strings that aren't known in advance--"GOOG", "MSFT", "KO" or whatever. 代码可以通过查看“action”字段包含单词“Buy”并且“quantity”字段大于零来确定(仅这些条件中的一个或另一个可能不足以确定该交易是股票购买),但“自动收报机”字段可以是数千个事先未知的字符串中的任何一个 - “GOOG”,“MSFT”,“KO”或其他。

Again, thanks to all for the responses so far. 再次感谢所有回复到目前为止。

Summary : build an extensible system of handlers for specific comparision types, and store related data in the database. 简介 :为特定的比较类型构建可扩展的处理程序系统,并将相关数据存储在数据库中。

You need : 你需要

  • Well-known types of conditions 众所周知的各种条件
  • An extensible system of registerable handlers which deal with specific types of conditions (eg EqualityHandler , StringLengthComparisionHandler ) 可注册处理程序的可扩展系统,用于处理特定类型的条件(例如EqualityHandlerStringLengthComparisionHandler
  • Each handler is associated with a documented object format 每个处理程序都与记录的对象格式相关联

Advantages : 优点

  • The system is highly extensible. 该系统具有高度可扩展性。 If you ever need comparison type X or Y, just write a handler. 如果你需要比较类型X或Y,只需编写一个处理程序。 This is really comparable with a plugin system of a browser or editor. 这实际上与浏览器或编辑器的插件系统相当。

  • You don't store code in the database. 您不在数据库中存储代码。 Storing code for equal types of comparison is totally against the DRY principle ( Don't repeat yourself ). 存储相同类型比较的代码完全违反DRY原则( 不要重复自己 )。

  • Unit tests. 单元测试。 I cannot imagine how unit tests would work when you have a database containing those codes. 当你有一个包含这些代码的数据库时,我无法想象单元测试是如何工作的。 They would be really painful. 他们真的很痛苦。

Disadvantages : 缺点

  • It requires you to write some code before you can actually start evaluating your data. 它需要您在实际开始评估数据之前编写一些代码。

    However, this type of problem is virtually crying for an OOP solution! 然而,这种类型的问题实际上是为OOP解决方案而哭泣! It really teaches you how OOP can be applied and used. 它真的教你如何应用和使用OOP。 At least in my opinion, it is fun to see how only adding one handler gives your application whole new functionalities! 至少在我看来,看到如何只添加一个处理程序为您的应用程序提供全新的功能,这很有趣!

Pseudo code : 伪代码

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