スマートに再帰を処理する最良の方法は何ですか?
質問
Smartyで再帰を処理するいくつかの方法を見つけました。ほとんどの場合、テンプレートを自分自身に含めることに基づいていますが、これはとんでもないリソースの無駄遣いのようです。 SmartyでMessjuが解決策の1つを見つけましたが、それはちょうど良いように思えましたが、smartyの最新バージョンではサポートされておらず失敗します:(
質問する人のために:私が賢く印刷したいのは、エントリの配列によって定義されるディスカッションスレッドです。エントリに1つ以上の回答がある場合、それらは配列内のそのエントリの子としてリストされ、以下同様になります。
array(
array(
'id'=>0,
'headline'=>"My parent headline",
'body' =>"My parent body",
'children'=>array(
array(
'id'=>1,
'headline'=>"My firstChild headline",
'body' =>"My firstChild body",
'children'=>array()
),
array(
'id'=>2,
'headline'=>"My secondChild headline",
'body' =>"My secondChild body",
'children'=>array()
)
)
),
);
ネストされた配列には任意の深さがあり、各エントリには任意の数の子があります。私にとって、これは純粋な表示ロジックであると考えているため、テンプレートの範囲内でやりたいことです。テンプレートの外部でHTMLまたは何らかのHTMLプレースホルダーを処理する必要はありません。
smartyにこれをネストされたリストとして印刷させたい:
<ul>
<li>
<h1>My parent headline</h1>
<p>My parent body</p>
<ul>
<li>
<h1>My firstChild headline</h1>
<p>My firstChild body</p>
</li>
<li>
<h1>My secondChild headline</h1>
<p>My secondChild body</p>
</li>
</ul>
</li>
</ul>
これは非常にケースバイケースの問題である可能性があることに気づき始めているので、万能の解決策が欲しいのですが、これを特に処理するためのスマートなプラグインを書くだけだと思います。
方法はありますか
解決
&quot;再帰を理解するには、まず再帰を理解する必要があります...&quot;
冗談です。これはあなたが望むことをするはずです:
<?php
/*
* Smarty plugin
* ————————————————————-
* File: function.recurse_array.php
* Type: function
* Name: recurse_array
* Purpose: prints out elements of an array recursively
* ————————————————————-
*/
function smarty_function_recurse_array($params, &$smarty)
{
if (is_array($params['array']) && count($params['array']) > 0) {
$markup = '';
$markup .= '<ul>';
foreach ($params['array'] as $element) {
$markup .= '<li>';
$markup .= '<h1>' . $element['headline'] . '</h1>';
$markup .= '<p>' . $element['body'] . '</p>';
if (isset($element['children'])) {
$markup .= smarty_function_recurse_array(array('array' => $element['children']), $smarty);
}
$markup .= '</li>';
}
$markup.= '</ul>';
return $markup;
} else {
return 'not array';
}
}
ファイルをsmarty / pluginsフォルダーに配置します。 Smartyに配列を割り当て、次のようにテンプレートで呼び出します:
{recurse_array array=$data}
Smartyのカスタム関数を作成するための素晴らしいチュートリアルを次に示します。
この例が基礎となるデータ構造に依存していることに注意してください。また、異常に長いまたは深くネストされたデータのセットは、本当に遅い可能性があることに注意してください。複雑さを管理し、物事を十分に文書化しておくと、大丈夫です。がんばって!
他のヒント
Smarty 3では、{function}を使用してこれを行うことができます。次のコードは、必要な出力を生成します。
{function name=printList}
<ul>
{foreach $items as $item}
<li>
<h1>{$item['headline']}</h1>
<p>{$item['body']}</p>
{if $item['children']}
{call name=printList items=$item['children']}
{/if}
</li>
{/foreach}
</ul>
{/function}
{call name=printList items=$comments}
詳細については、ドキュメントをご覧ください。
サイドノート:何かが複雑または再帰的だからといって、それがテンプレートの中に入れられないという意味ではありません。神のために、HTML ul-li構造は自然に再帰的であり、非表示にするか別の場所に移動することにより(テンプレートとしては複雑すぎるため)、アプリケーションに余分な複雑さを導入しています。
smarty用のカスタム関数/修飾子/プラグインの作成を検討することをお勧めします。 関数が使用するテンプレートを定義するとともに、配列をカスタム関数に渡します。単純な場合は、特定の場所にテキストを挿入するだけで、関数内でテンプレートを読み込み、PHPでregexes / str_replace / ...を使用してテンプレートを操作します
または、smartyテンプレートを使用せずにPHPで直接実行します。必要なのはh1、ul、li、pタグであり、レイアウトを変更するにはCSSを使用します。
または、Smartyでファイルを開いたり閉じたりするオーバーヘッドが懸念される場合は、90%のケースでレベルの量を見積もって、それらの90%をカバーするテンプレートを作成します。残りの部分では、テンプレート自体を含めて再帰を使用します...
最善の方法は、やらないことです。
スマートはシンプルなはずです。これは聞こえません。