getResourcesでの複数テンプレート変数によるソート  【解決済み】

質問全般・改善要望
afactdesign
メンバー
メンバー
記事: 11
登録日時: 2011年11月03日(木) 15:44

getResourcesでの複数テンプレート変数によるソート

投稿記事by afactdesign » 2012年2月14日(火) 06:26

皆様お世話になっております。

表題の件に関しまして、現在作成しているウェブサイトをMODX 2.2にて制作しておりますが、あるコンテンツ群をgetResources で表示する際に、複数のテンプレート変数でソートを行いたいのですが、どなたか方法をご存じの方はいらっしゃいますでしょうか?
ドキュメントによると、&sortbyTV というプロパティはありますが、これは&sortby のようにJSON配列を受け付けることができないようで、四苦八苦しております。
できれば、例えば
第1ソートキー tv.tv1: DESC
第2ソートキー tv.tv2: ASC
第3ソートキー tv.tv3: ASC
といった形で出力をさせたいと思っております。
これを、getResources で実現する方法、もしくはそれが無理な場合、他のスニペットやプラグインなどで実現する方法があれば、ご教授いただければ助かります。
最悪自作スニペットで対応をするべきなのでしょうが、恥ずかしながらどのようにしてデータベースからコンテンツ内容とテンプレート変数の内容をレコード化して取りだせばいいのかがわからず・・・。
皆様のお力添えをいただければ幸せです。

使用しているMODXは2.2.0 pl2-ja、getResourcesは最新の1.4.2を使用しています。
何とぞよろしくお願い申し上げます。
sama55
メンバー
メンバー
記事: 816
登録日時: 2009年8月03日(月) 08:16

Re: getResourcesでの複数テンプレート変数によるソート

投稿記事by sama55 » 2012年2月14日(火) 14:47

http://rtfm.modx.com/display/ADDON/getResources
Calls without a &tpl property specify will just output an array listing of each resulting Resource and their fields.

※これが解決の糸口になりそうな気がしましたが、どうでしょうね。
 ・ラッパースニペットを一つ作る
 ・API(runSnippet)でgetResourceをコール(データを配列で取得)
 ・PHPのソートで頑張る(笑)
 ・プレースホルダに送ったり、パースチャンクしたりして編集して結果を返す

他には、xPDOQueryで低レベルコーディングしてしまう手もありそうですが結構面倒そうです。いずれにしても、sortbyTV でマルチソートできないのだとしたら、自前スニペの作成やAPIを使ったコーディングは避けては通れない気がしました。Evoではwhere引数で指定した文字列がクエリー文にそのまま載る特性を利用して、ORDER BY句を無理やりつなげちゃう荒技(笑)が使えたと薄っすら記憶してますが、PDOが介在するRevoでは期待薄・・・

こういうニーズは結構あるようですね。
http://forums.modx.com/index.php?topic=53371.0
http://forums.modx.com/thread/43669/i-w ... n-an-array

ご参考までに
最後に編集したユーザー sama55 on 2012年2月17日(金) 08:15 [ 編集 1 回目 ]
afactdesign
メンバー
メンバー
記事: 11
登録日時: 2011年11月03日(木) 15:44

Re: getResourcesでの複数テンプレート変数によるソート

投稿記事by afactdesign » 2012年2月16日(木) 23:57

sama55さん、ご教示ありがとうございます。
トライ&エラーを繰り返していて返信が遅くなってしまい、申し訳ございません。

結論からいいますと、お教えいただきましたrunSnippetを利用するアプローチで解決することができました。
本当にありがとうございます。

ただTplを設定しないgetResources が返してくるのは実は配列のように見せかけた文字列(もしくはrunSnippetが配列でも文字列として戻り値を設定するのかもしれません)だったので、配列に整形し直してからarray_multisort にてソートを行い、結果をチャンクをテンプレートとして出力、という形を取りました。

ソースをある程度お見せするべきか、とも思ったのですが結構長くなっているのでひとまずは割愛させていただきます。
ご助力頂き、本当にありがとうございました。
sama55
メンバー
メンバー
記事: 816
登録日時: 2009年8月03日(月) 08:16

Re: getResourcesでの複数テンプレート変数によるソート

投稿記事by sama55 » 2012年2月17日(金) 08:31

afactdesignさん
getResources Tpl変数無しの件ご報告ありがとうございます(なるほどです)。
・・・にしても、さすがです。 ;)
afactdesign
メンバー
メンバー
記事: 11
登録日時: 2011年11月03日(木) 15:44

Re: getResourcesでの複数テンプレート変数によるソート  【解決済み】

投稿記事by afactdesign » 2012年2月17日(金) 09:08

sama55さん
こちらこそアイデアをいただけて本当に助かりました、ありがとうございます :D
getResources Tplナシの出力、なぜか<pre>Array ( [id] => '..... )</pre> をすべて文字列で返してくる(しかも改行やインデントまできっちりと)ので、ReplaceだのEplodeだのでえらく長くなってしまいました(汗)加えて自分がデザイナー上がりなので、多分かなり力技な書き方になってしまっているのだとは思います。
英語フォーラムでは似たニーズをご紹介いただいていましたので、やはりプログラムを掲載させていただこうと思います。
綺麗なコーディングができておらず、恐縮ですが(汗)
ささやかながら少しでも同様のニーズを持った方々の助けになれば幸いです。

コード: 全て選択

<?
//リソースの取りだし
$grparam = array('parents'=>$parents,'limit'=>99,'includeTVs'=>1);
$stockstr = $modx->runSnippet('getResources', $grparam);

//文字列→配列変換
$stockstr = str_replace('</pre>', '', str_replace("<pre>\nArray\n(", '', $stockstr));
$stockarrtmp = explode(')', $stockstr);
$stockarr = array();
foreach ($stockarrtmp as $value){
   $valtmp = str_replace('[id] => ', '', substr($value, strpos($value, '[id]')));
   $id = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[pagetitle] => ', '', substr($valtmp, strpos($valtmp, '[pagetitle]')));
   $pagetitle = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[longtitle] => ', '', substr($valtmp, strpos($valtmp, '[longtitle]')));
   $longtitle = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[menuindex] => ', '', substr($valtmp, strpos($valtmp, '[menuindex]')));
   $menuindex = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[menutitle] => ', '', substr($valtmp, strpos($valtmp, '[menutitle]')));
   $menutitle = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[tv.price] => ', '', substr($valtmp, strpos($valtmp, '[tv.price]')));
   $price = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[tv.height] => ', '', substr($valtmp, strpos($valtmp, '[tv.height]')));
   $height = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[tv.width] => ', '', substr($valtmp, strpos($valtmp, '[tv.width]')));
   $width = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   $valtmp = str_replace('[tv.tall] => ', '', substr($valtmp, strpos($valtmp, '[tv.tall]')));
   $tall = str_replace("  ", '', str_replace("\n", '', substr($valtmp, 0, strpos($valtmp, '['))));
   
   //pagetiltle: 商品名 longtitle: ブランド名
   $stockarr[] = array(
      'id' => $id,
      'pagetitle' => $pagetitle,
      'longtitle' => $longtitle,
      'menuindex' => $menuindex,
      'menutitle' => $menutitle,
      'price' => $price,
      'height' => $height,
      'width' => $width,
      'tall' => $tall);
}
array_shift($stockarr);

//配列のソート

$pagetitle = array();
$longtitle = array();
$price = array();
$height = array();
$width = array();
$tall = array();

//ソート用配列の準備
foreach($stockarr as $key => $row){
   $pagetitle[$key] = $row['pagetitle'];
   $longtitle[$key] = $row['longtitle'];
   $price[$key] = $row['price'];
   $height[$key] = $row['height'];
   $width[$key] = $row['width'];
   $tall[$key] = $row['tall'];
}

$sortby = htmlentities(strip_tags($_GET['sort']));
$sortdir = htmlentities(strip_tags($_GET['dir']));
switch($sortby){
   case "brand":
      if($sortdir == 'desc'){
         array_multisort($longtitle, SORT_DESC,
                     $pagetitle, SORT_DESC $stockarr);
      }else{
         array_multisort($longtitle, SORT_ASC,
                     $pagetitle, SORT_ASC, $stockarr);
      }
      break;
   case "price":
      if($sortdir == 'desc'){
         array_multisort$price, SORT_DESC,
                     $pagetitle, SORT_ASC,
                     $longtitle, SORT_ASC, $stockarr);
      }else{
         array_multisort($price, SORT_ASC,
                     $pagetitle, SORT_ASC,
                     $longtitle, SORT_ASC, $stockarr);
      }
      break;
   case "size":
      if($sortdir == 'desc'){
         array_multisort($width, SORT_DESC,
                     $height, SORT_DESC,
                     $tall, SORT_DESC,
                     $longtitle, SORT_ASC,
                     $pagetitle, SORT_ASC, $stockarr);
      }else{
         array_multisort($width, SORT_ASC,
                     $height, SORT_ASC,
                     $tall, SORT_ASC,
                     $longtitle, SORT_ASC,
                     $pagetitle, SORT_ASC, $stockarr);
      }
      break;
   default:
      if($sortdir == 'desc'){
         array_multisort($pagetitle, SORT_DESC,
                     $longtitle, SORT_DESC $stockarr);
      }else{
         array_multisort($pagetitle, SORT_ASC,
                     $longtitle, SORT_ASC, $stockarr);
      }
      break;
}

//配列の表示
$output = '';
foreach($stockarr as $key => $row){
   //プレースホルダーの作成
   $modx->setPlaceholder('id',$row['id']);
   $modx->setPlaceholder('pagetitle',$row['pagetitle']);
   $modx->setPlaceholder('longtitle',$row['longtitle']);
   $modx->setPlaceholder('menuindex',$row['menuindex']);
   $modx->setPlaceholder('menutitle',$row['menutitle']);
   $modx->setPlaceholder('price',$row['price']);
   $modx->setPlaceholder('height',$row['height']);
   $modx->setPlaceholder('width',$row['width']);
   $modx->setPlaceholder('tall',$row['tall']);

   $output .= $modx->getChunk($tpl);
}

return $output;
?>