eccube 2.11 Smartyの配列をソートできるようにする | φ(..)メモとして残しておこう…

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について調べとかないとアレかもです。
本とかみるのもいいかも。