eccube 2.11 Smartyの配列をソートできるようにする
Sorting arrays inside Smarty templates.
昨日、商品一覧ページの商品ソート(並べ替え)について書いたのですが、特定環境下で動かないという問題が発生したので、Smartyの配列データを無理矢理ソートしちゃうという荒業で対応することにしました。
基本的に、昨日書いたコードは
「price」= 「価格の安い順番」
「price_h」=「価格の高い順番」
なんてやる場合には、
「setProductsOrder()」でSQLのORDER BY句を生成して、ASCかDESCかで取得してくるというものです。
基本的にはこれでいいんだろうけど、取得してきたデータをSmartyのテンプレート内でソート処理したい場合はどうするか。
これはもう、Smarty本体のプラグインにそれを追加するしかないわけで…。
実際にSmartyのフォーラムでもそういう機能はないのか?ってやりとりがされてたりします。
Smartyはテンプレートエンジンだから…そういうのは必要ない…と思われてるから実装されていないんでしょうが、やっぱりあると便利な機能なわけで。
公式プラグインになっているのかどうかはさておき、EC-CUBEで使用しているSmartyの中にはそんなもん無いので、自分で実装します…
アボーン(´・ェ・`)
まずは「/data/module/Smarty/libs/plugins/」以下に、新規ファイル「modifier.sortby.php」を作って以下のコードを書きます。
<?php
function array_sort_by_fields(&$data, $sortby){
static $sort_funcs = array();
if (empty($sort_funcs[$sortby]))
{
$code = "\$c=0;";
foreach (explode(',', $sortby) as $key)
{
$d = '1';
if (substr($key, 0, 1) == '-')
{
$d = '-1';
$key = substr($key, 1);
}
if (substr($key, 0, 1) == '#')
{
$key = substr($key, 1);
$code .= "if ( \$a['$key'] > \$b['$key']) return $d * 1;\n";
$code .= "if ( \$a['$key'] < \$b['$key']) return $d * -1;\n";
}
else
{
$code .= "if ( (\$c = strcasecmp(\$a['$key'],\$b['$key'])) != 0 ) return $d * \$c;\n";
}
}
$code .= 'return $c;';
$sort_func = $sort_funcs[$sortby] = create_function('$a, $b', $code);
}
else
{
$sort_func = $sort_funcs[$sortby];
}
uasort($data, $sort_func);
}
// Modifier: sortby - allows arrays of named arrays to be sorted by a given field
function smarty_modifier_sortby($arrData,$sortfields) {
array_sort_by_fields($arrData,$sortfields);
return $arrData;
}
$smarty->register_modifier( "sortby", "smarty_modifier_sortby" );
?>
これで、Smartyの配列をforeachでループするときとかに、ソート機能が使えるようになります。
使い方はこんな感じ。
例えば、商品一覧ページのテンプレートの場合
商品コード(product_id)でソート
<!--{foreach item=item key=key from=$arrProducts|@sortby:"#product_id"}-->
<!--{$item.product_id}-->-<!--{$item.price02_min}-->
<!--{/foreach}-->
商品価格(price02_min)でソート
<!--{foreach item=item key=key from=$arrProducts|@sortby:"#price02_min"}-->
<!--{$item.product_id}-->-<!--{$item.price02_min}-->
<!--{/foreach}-->
という感じで、値の少ない順にソート出来ます。
では、値の大きい順にソートするには…ですが、
if (substr($key, 0, 1) == '-')
や
if (substr($key, 0, 1) == '#')
というコードを見てもわかるように
商品コード(product_id)でソート
<!--{foreach item=item key=key from=$arrProducts|@sortby:"-product_id"}-->
<!--{$item.product_id}-->-<!--{$item.price02_min}-->
<!--{/foreach}-->
商品価格(price02_min)でソート
<!--{foreach item=item key=key from=$arrProducts|@sortby:"-price02_min"}-->
<!--{$item.product_id}-->-<!--{$item.price02_min}-->
<!--{/foreach}-->
とやってソート出来ます。
スマーティ関係のファイルを作成…ということなので、割とEC-CUBEについて調べとかないとアレかもです。
本とかみるのもいいかも。