わかりました、最初に、TL;DR で申し訳ありません...
第二に、私が達成したいことについてのいくつかの文脈。
特定のファイルを処理し、定義された一連のルールに基づいて新しいファイルを生成するスクリプトがあります。ファイルの各行には値があり、スクリプトは値を評価し、その値と一般的なルールに基づいて他の値を生成します。生成されたファイルには、元の値と生成された値が csv 形式で含まれています。
例えば:
入力ファイル:
row1value
row2value
出力ファイル:
"row1value","generatedValue1","generatedValue2","generatedValue3"
"row2value","generatedValue1","generatedValue2","generatedValue3"
たとえば、ソース ファイルの各行にコロンで区切られた値があり、目的は値をコロンで分割し、各サブ値を列に入れることだとします。これは、「前」と「後」がどのように見えるかです。
入力ファイル:
a:b:c
some:random:value
出力ファイル:
"a:b:c","a","b","c"
"some:random:value","some","random","value"
行を生成するには、次のようにします。
function generateRow ($key) {
// $key is the value for the current row being processed from the source file
// $row is the array that will contain the columns to be inserted to the output file
$row = array();
// generate the column values
$row = explode(":",$key);
// make the original value ($key) the first column
array_unshift($row, $key);
// return the array. some other function will fputcsv it
return $row;
}
別の例として、ソース ファイルに次のような値の行が含まれている場合があります。
[prefix]:[url]
出力ファイルの列の値は次のようになります。
- column1 = 完全な元の値 (常にこれになります)
- 列 2 =
[prefix]
- column3 = [URL]
- column4 = URL のドメインの [url] を解析します
- column5 = ファイル拡張子の解析 [url]
だから私はこれらのことをするために書いgenerateRow()
ています。
よし、これで全部揃った。それはすべて光沢があり、うまく機能しています。独自のファイルを受け取り、定義されたルールに基づいて列を含む新しいファイルを生成する新しい「プロセス」を作成する要求を受け取ります。私が実際に何を望んでいるかを皆さんがより簡単に理解できるように、これを文脈に入れるためのバックストーリーとしてこれらすべてを提供したかっただけです.
generateRow()
したがって、「問題」は、現状では、「プロセス」が仕様に基づいて書き出すコーダー (私) によって作成されていることです。これは、私や PHP を知っている他の人にとって特に難しいことではありません。しかし、特定の利害関係者が自分でこのようなものを作成することを担当したいという点で、これは「ユーザーフレンドリー」ではありませんが、彼らはコーダーではありません.
したがって、私の仕事は、基本的に の Web インターフェイスを提供することですgenerateRow()
。したがって、基本的には、以前に選択したアイテムに基づいてフォーム要素と可能なオプションを動的に生成するフォームを作成する必要があります。つまり、表現エンジンです。または述語エンジン。またはルールビルダー。正直なところ、これらの用語のどれが最も正確であるかは 100% 確信が持てませんが、私は多くのグーグル検索と読書を行ってきました。
したがって、たとえば、フォームはユーザーに条件または代入式を作成するように求めることから始まります。
[ドロップダウン:if|設定]
IF:ユーザーが「if」をクリックすると、別のドロップダウンが表示され、チェック対象の「変数」のリストが表示されます。たとえば、システムは、他の列、ソース ファイルの任意の列 (キーを含む)、インポート ファイル名、またはユーザーが以前に作成した任意のカスタム変数 (以下の「設定」を参照) への参照を選択として使用できます。フォームには「アクション」ドロップダウンが表示され、「設定されている」、「設定されていない」、「より大きい」、「正規表現」などを表示します。ユーザーが「設定されている」または「設定されていない」などを選択すると、他のフィールドは出力されません。ただし、ユーザーがたとえば「より大きい」を選択すると、別のドロップダウンが表示され、「変数」のリストから選択するか、値を入力する入力フィールドが求められます。
IF column1 "is set" /* check if column1 is set */
IF column1 contains "foobar" /* check if column1 contains "foobar" */
If column1 regex "^[a-z]+$" /* check if column1 contains only letters */
これが定義されると、ユーザーはその中に「set」式を追加できます。簡単にするために、条件をネストしたり、AND | OR を使用して複合条件を作成したりする必要はないと思います。
SET:したがって、ユーザーがこのオプションを選択すると、フォームは代入式の作成をガイドします。最初のドロップダウンには、出力ファイルの列など、ユーザーが値を割り当てることができる変数、または一時変数が保持されるため、他の式で参照できます。例:
SET [column1] [=] ["foobar"]
SET [column2] [=] [column1]
SET [column1] [regex] [userVar1] ["^[^:]+"]
SET [userVar1] [explode] [key] [":"]
それが「最良の」提示方法であるかどうかはわかりませんが、うまくいけば、アイデアが得られることを願っています.
次に、これらの式を保存してから、それらを評価するための PHP コードを記述します。基本的にそれらを実際のphpコードに変換します。その部分に関しては、実際には問題ないと思います。インタープリターパターンを使用するだけです。
しかし、私が助けを必要としているのは、「マッピング」/「ビルダー」部分の表現全体です。実際、可能性のある表現の「マッピング」を肉付けできれば、「ビルダー」の部分もスイングできると思います。
そうそう、私の質問の核心はここにあります。可能な表現をどのようにマッピングするかです。現在、私はそれをxmlとして構造化/マッピングしようとして遊んでいますが、可能なすべてのパスをハードコーディングするだけで、その方法を把握できないようです。まず、私にはこれは効率が悪いように思えます。よりスマートな方法があるはずです。おそらく簡単に拡張することはできません...「プロセス」#1のルールセットには、描画する2つのソースファイル列と生成する5つの出力ファイル列があるとしましょう..そして「プロセス」#2は1と4ですか?ユーザーが設定できる可変量のユーザー定義変数の説明についてはどうですか。
それで、この種のことを行う方法を説明するヒントやリンクを持っている人はいますか? または、プレハブ(php)ソリューションがあればさらに良いですが、まだ何かを見つけることができませんでした..
編集:これは私が今いる場所の例です。うまくいけば、私の問題をよりよく理解できるようになります。
たとえば、マップ (xml) をハードコーディングした場合、次のようになります。
<expressions>
<expression type='if'>
<variable name='column1'>
<operator type='isset'></operator>
<operator type='notset'></operator>
<operator type='equals'>
<variable name='column1' />
<variable name='column2' />
<variable name='column3' />
</operator>
<operator type='greaterThan'>
<variable name='column1' />
<variable name='column2' />
<variable name='column3' />
</operator>
<operator type='lessThan'>
<variable name='column1' />
<variable name='column2' />
<variable name='column3' />
</operator>
</variable>
<variable name='column2'>
<operator type='equals'>
<variable name='column1' />
<variable name='column2' />
<variable name='column3' />
</operator>
<operator type='greaterThan'>
<variable name='column1' />
<variable name='column2' />
<variable name='column3' />
</operator>
<operator type='lessThan'>
<variable name='column1' />
<variable name='column2' />
<variable name='column3' />
</operator>
</variable>
</expressions>
カップルのメモ:
- 任意の数の
variable
ノードがあります。ソースファイルの列ごとに 1 つ、出力ファイルの列名ごとに 1 つ、ユーザーがその場で作成する変数ごとに 1 つ、などです。 - 可変数の
operator
タイプがあります。3つの例を示しましたが、これまでに20ほど思いついたものがあります - 一部の
operator
タイプでは、追加のフォーム フィールドをフォームに出力する必要があることに注意してください。たとえば、「if [column1] [isset]」対「if [column1] [greaterThan] [column2]」 - この
expression
ノードは、「if」式がどのようになるかを示しています。またexpression
、異なる構造を持つ「セット」タイプのノードもありますが、原理的には同じように機能します。たとえば、「[set] [column2] [equals] [column1]」または「[set] [column1] [regex] [sourceColumn1] [input value (regex)]」という式が存在する可能性があります。
そのため、今はパスをたどって、ツリーを下っていく利用可能なものに基づいてメニューを動的に構築することができます。
しかし、ご覧のとおり、繰り返しが多いように見えます。また、新しいもの (新しいオペレーターなど) をミックスに投入するのはピタリです。ここでの質問は、これをより適切に構成するにはどうすればよいかということです。それとも、それは不可能であり、唯一の解決策はすべての可能性をハードコーディングすることですか?