そうです、よく見るあの機能です。
最近みた商品をcookieに保存して表示させる機能です。
EC-CUBEでも搭載はすぐできるようなので紹介したいと思います。
色々サイトを拝見してましたが2.11系でしっくりこなかったので、ちょこっと我流が入っています。
なので若干「??」みたいな処理をしてるかもしれません。。。
※ユーザー画面のコーディングは割愛いたします。
機能の要件
- 商品一覧、詳細に商品の履歴を表示
- 表示件数は5件を想定(縦表示)
- 縦表示なので上から順に表示
- 商品の表示は重複しない
- クッキー保存期間は一ヶ月
こんなもんかな。
商品詳細で閲覧履歴の表示・cookie保存の処理の設定をします
作業ファイル:
/data/class/pages/products/LC_Page_Products_Detail.php
// ログイン判定 if ($objCustomer->isLoginSuccess() === true) { //お気に入りボタン表示 $this->tpl_login = true; $this->is_favorite = SC_Helper_DB_Ex::sfDataExists('dtb_customer_favorite_products', 'customer_id = ? AND product_id = ?', array($objCustomer->getValue('customer_id'), $product_id)); } // ここから // 商品閲覧履歴取得(最近見た商品) $this->Get_ItemHistory($product_id); // ここまで255行目あたりログイン判定のしたあたりに、「商品閲覧履歴取得」のソースを挿入。
/** * 最近みた商品の情報を取得 (2012/2/8 対応) * * @return array * @setcookie array */ function Get_ItemHistory($product_id) { $cnt = 0; // ページを再読み込み後に表示 if (isset($_COOKIE['product'])) { //要素を逆順に指定 $DispAry = $_COOKIE['product']; $reverseAry = array_reverse($DispAry); foreach ($reverseAry as $name => $value) { $objQuery = new SC_Query(); $objProduct = new SC_Product_Ex(); // 商品情報取得 $arrRet = $objProduct->getCommodityDetail($value); $this->arrItemHistory[$cnt] = $arrRet; $cnt = $cnt+1; } } //クッキーに重複項目がないか判定処理 $duplicateFlg = true; if (isset($_COOKIE['product'])) { foreach ($_COOKIE['product'] as $name => $value) { if($value == $product_id){ $duplicateFlg = false; } } } //重複がない場合クッキーに設定 if($duplicateFlg){ $dispnum = 5;//履歴表示件数 if($cnt == 0){ setcookie('product[' .$cnt .']', $product_id,time()+60*60*24*30 );// 有効期限30日 //setcookie('product[' .$cnt .']', time()+60);// 有効期限1分 }else{ $cookie_array = $_COOKIE['product']; $cookie_array[] = $product_id; //表示件数を超えた場合は一つ削除 if(count($cookie_array) > $dispnum){ array_shift($cookie_array); } foreach ($cookie_array as $key => $val) { setcookie('product[' .$key .']', $val,time()+60*60*24*30 );// 有効期限30日 //setcookie('product[' .$key .']', $val,time()+60);// 有効期限1分 } } } }LC_Page_Products_Detail.php の一番下に上記ソースを追加。
簡単に流れとポイントを説明しますと
1)cookieに保存したデータを読み込み、商品情報を取得
読み込んだ配列はarray_reverse()で、配列を逆順にしています。smarty側で処理をしても良かったのですが、データ出力時の処理だと何かあった時に忘れてしまうのでここで処理を入れてます。
商品情報を取得する時にはgetCommodityDetail()で取得してます。
getDetail()でもいいのですが、今後データの取得が似ている
コンテンツ(こんな商品買ってる人は、とか?)を作成する予定なので、SC_Product.phpに関数を作成しました。
※特に必要ないなあと思ったら「getDetail()」に変更しちゃってください。
2)クッキーに重複項目がないか判定
重複してたらfalse。falseの場合、次のクッキーに設定する処理は行われません。
3)重複がない場合クッキーに設定
cookieを配列にして設定する処理なのですが、5件までという制限があるので、array_shift()の関数を使用して、
配列をcountして$dispnumより多かったら、先頭を1つ削除するように制御してます。
以上です。
商品一覧で閲覧履歴を表示させる処理をします
作業ファイル:
/data/class/pages/products/LC_Page_Products_List.php
//カート処理 $target_product_id = intval($this->arrForm['product_id']); if ( $target_product_id > 0) { // 商品IDの正当性チェック if (!SC_Utils_Ex::sfIsInt($this->arrForm['product_id']) || !SC_Helper_DB_Ex::sfIsRecord("dtb_products", "product_id", $this->arrForm['product_id'], "del_flg = 0 AND status = 1")) { SC_Utils_Ex::sfDispSiteError(PRODUCT_NOT_FOUND); } // 入力内容のチェック $arrErr = $this->lfCheckError($target_product_id, $this->arrForm, $this->tpl_classcat_find1, $this->tpl_classcat_find2); if (empty($arrErr)) { $this->lfAddCart($this->arrForm, $_SERVER['HTTP_REFERER']); SC_Response_Ex::sendRedirect(CART_URLPATH); exit; } $js_fnOnLoad .= $this->lfSetSelectedData($this->arrProducts, $this->arrForm, $arrErr, $target_product_id); } // 商品閲覧履歴取得(最近見た商品) $this->Get_ItemHistory();178行目あたりカート処理のしたあたりに、「商品閲覧履歴取得」のソースを挿入。
/** * 最近みた商品の情報を取得 (2012/2/8 対応) * * @return array * @setcookie array */ function Get_ItemHistory($product_id) { $cnt = 0; // ページを再読み込み後に表示 if (isset($_COOKIE['product'])) { //要素を逆順に指定 $DispAry = $_COOKIE['product']; $reverseAry = array_reverse($DispAry); foreach ($reverseAry as $name => $value) { $objQuery = new SC_Query(); $objProduct = new SC_Product_Ex(); // 商品情報取得 $arrRet = $objProduct->getCommodityDetail($value); $this->arrItemHistory[$cnt] = $arrRet; $cnt = $cnt+1; } } }LC_Page_Products_List.php の一番下に上記ソースを追加。
一覧はクッキーに保存しているデータを呼び出すだけです。
SC_Product.phpにgetCommodityDetail()の関数を追加する
※この項目は、「商品詳細で履歴の表示・cookie保存の処理をします」でgetCommodityDetail()を設定した時に必要な処理です。getDetail()を設定ている場合は必要ありません
getDetail()、alldtlSQL()を流用します。
それぞれの関数をコピーし、関数名などを変更してSC_Product.phpの下に貼り付けます。
/** * 商品詳細を取得する. (2012/2/8 対応) * * @param integer $productId 商品ID * @return array 商品詳細情報の配列 */ function getCommodityDetail($productId) { $objQuery =& SC_Query_Ex::getSingletonInstance(); $result = $objQuery->select("*", $this->commoditySQL("product_id = ? AND del_flg = 0"), "product_id = ?", array($productId, $productId)); return $result[0]; } /** * 商品詳細の SQL を取得する. * * @param string $where 商品詳細の WHERE 句 * @return string 商品詳細の SQL */ function commoditySQL($where = "") { $where_clause = ""; if (!SC_Utils_Ex::isBlank($where)) { $where_clause = " WHERE " . $where; } /* * point_rate, deliv_fee は商品規格(dtb_products_class)ごとに保持しているが, * 商品(dtb_products)ごとの設定なので MAX のみを取得する. */ $sql = <<< __EOS__ ( SELECT 0 ,dtb_products.product_id ,dtb_products.name ,dtb_products.status ,dtb_products.comment1 ,dtb_products.comment2 ,dtb_products.comment3 ,dtb_products.main_list_comment ,dtb_products.main_list_image ,dtb_products.main_comment ,dtb_products.del_flg ,T4.product_code_min ,T4.product_code_max ,T4.price01_min ,T4.price01_max ,T4.price02_min ,T4.price02_max ,T4.stock_min ,T4.stock_max ,T4.stock_unlimited_min ,T4.stock_unlimited_max ,T4.point_rate ,T4.deliv_fee ,T4.class_count ,dtb_maker.name AS maker_name FROM dtb_products JOIN ( SELECT product_id, MIN(product_code) AS product_code_min, MAX(product_code) AS product_code_max, MIN(price01) AS price01_min, MAX(price01) AS price01_max, MIN(price02) AS price02_min, MAX(price02) AS price02_max, MIN(stock) AS stock_min, MAX(stock) AS stock_max, MIN(stock_unlimited) AS stock_unlimited_min, MAX(stock_unlimited) AS stock_unlimited_max, MAX(point_rate) AS point_rate, MAX(deliv_fee) AS deliv_fee, COUNT(*) as class_count FROM dtb_products_class $where_clause GROUP BY product_id ) AS T4 ON dtb_products.product_id = T4.product_id LEFT JOIN dtb_maker ON dtb_products.maker_id = dtb_maker.maker_id ) AS alldtl __EOS__; return $sql; }
commoditySQL()で取得したいデータの内容を変更します。
上記の内容は、必要そうなデータのみ残してます。
何が削除されてるかは、alldtlSQL()と見比べてみてください。
ユーザー画面に「最近みた商品」のブロックを追加します
管理画面から、「デザイン管理」⇒「PC」⇒「ブロック設定」を選択し、ブロックを追加します。

こんな感じで。
ソースはとりあえず、
<!--{section name=cnt loop=$arrItemHistory}--> <div> <img src="/upload/save_image/<!--{$arrItemHistory[cnt].main_list_image}-->" /> <!--{$arrItemHistory[cnt].product_id}--> <!--{$arrItemHistory[cnt].name}--> </div> <!--{/section}-->といれておきます。
ブロックを登録したらレイアウト設定に戻り、「商品一覧ページ」「商品詳細ページ」に「最近見た商品」ブロックを追加します。「メイン」のしたあたりで良いのではないでしょうか。
あとは、実際にページを見て表示されているか確認します。
表示されていたら、あとはご自由にレイアウトしてください。
おつかれさまです。
⇒13)Smartyのdebug(デバッグ)について-hetemlのサーバでEC-CUBE(2.11.4)を使ってみる
⇒hetemlのサーバでEC-CUBEインストール~公開までの道のり
トップページでも表示できるようにしたいのですが、
ご教授いただけますと幸いです。
>naoさん
こんにちわ!コメントありがとうございます。
トップページに表示させる場合ですが
「最近みた商品」をブロック化してしまうのが良いと思います。
(カテゴリーや利用ガイドのような形)
この記事のやり方も一応ブロックにしていますが、
LC_Page_Products_List.php
LC_Page_Products_Detail.php
にしかGet_ItemHistory()の関数を書いていませんので
他のページでは商品データを取得できません。
時間を見て、ブロック化の作成の仕方はアップしたいと思います。