簡體   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