前回まででEC-CUBEの構造についての概要はご理解頂けたでしょうか?
今回はEC-CUBEに新規ページを追加したい場合の手順について書いていきたいと思います。
とはいってもEC-CUBEには新規ページ追加機能というものがあります。これは買い物の流れやサイトPRページといったような静的なページを作成する場合の機能になります。
よって、例えば今までの売れ行きから商品をランキング表示される「本日の売り上げランキング」のような動的なページを追加したい場合には、この機能を使って実現することができません。
では、そういう機能もったページを追加したい場合にはどうすればいいのか?
方法は1つではありません。
今回はその中の最も一般的ではないか?と個人的に思う方法をご紹介させて頂きます。
簡単に手順を述べると
1.公開側にファイル作成
2.非公開側に処理用のファイルを作成(拡張用と2つ)
3.テンプレートファイル作成
これだけです。
ここでは上の例を使って「本日のランキングページ」を追加してみましょう。対象のEC-CUBEのバージョンは2.4.4とします。
まずは、公開側にファイルを追加します。公開側であれば特にどこに作っても構いませんが、今回は
/shop_name/products/ranking.php
としましょう。
中の記述は以下のようにします。
[php]
// {{{ requires
require_once("../require.php");
require_once(CLASS_EX_PATH . "page_extends/products/LC_Page_Products_Ranking_Ex.php");
// }}}
// {{{ generate page
$objPage = new LC_Page_Products_Ranking_Ex();
register_shutdown_function(array($objPage, "destroy"));
$objPage->init();
$objPage->process();
[/php]
次に非公開側にもファイルを作成します。
/data/class_extends/page_extends/products/LC_Page_Products_Ranking_Ex.php
/data/class/pages/products/LC_Page_Products_Ranking.php
の2つです。
中の記述はそれぞれ以下のようにしてください。前回までに述べたようにここが処理部分になります。詳しい内容はまた後日解説するとして、今回はそういうものなんだと思ってコピペしてください。
[php]
LC_Page_Products_Ranking_Ex.php
// {{{ requires
require_once(CLASS_PATH . "pages/products/LC_Page_Products_Ranking.php");
/**
* LC_Page_Products_Ranking のページクラス(拡張).
*
* LC_Page_Products_Ranking をカスタマイズする場合はこのクラスを編集する.
*
*/
class LC_Page_Products_Ranking_Ex extends LC_Page_Products_Ranking {
// }}}
// {{{ functions
/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
}
/**
* Page のプロセス.
*
* @return void
*/
function process() {
parent::process();
}
/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
}
LC_Page_Products_Ranking.php
// {{{ requires
require_once(CLASS_PATH . "pages/products/LC_Page_Products_List.php");
/**
* ランキング のページクラス.
*
*/
class LC_Page_Products_Ranking extends LC_Page_Products_List {
/**
* Page を初期化する.
*
* @return void
*/
function init() {
parent::init();
$this->tpl_mainpage = ‘products/ranking.tpl’;
}
/**
* Page のプロセス.
*
* @return void
*/
function process() {
global $objCampaignSess;
$objView = new SC_SiteView();
$objCampaignSess = new SC_CampaignSession();
$conn = new SC_DBConn();
$objDb = new SC_Helper_DB_Ex();
//表示件数の選択
if(isset($_POST[‘disp_number’])
&& SC_Utils_Ex::sfIsInt($_POST[‘disp_number’])) {
$this->disp_number = $_POST[‘disp_number’];
} else {
//最小表示件数を選択
$this->disp_number = current(array_keys($this->arrPRODUCTLISTMAX));
}
// レイアウトデザインを取得
$layout = new SC_Helper_PageLayout_Ex();
$layout->sfGetPageLayout($this, false, DEF_LAYOUT);
if (!isset($_GET[‘mode’])) $_GET[‘mode’] = "";
// タイトル編集
$tpl_subtitle = "本日の売上ランキング";
$objQuery = new SC_Query();
$this->lfDispProductsList($this->disp_number);
if(isset($_POST[‘mode’]) && $_POST[‘mode’] == "cart"
&& $_POST[‘product_id’] != "") {
// 値の正当性チェック
if(!SC_Utils_Ex::sfIsInt($_POST[‘product_id’]) || !$objDb->sfIsRecord("dtb_products", "product_id", $_POST[‘product_id’], "del_flg = 0 AND status = 1")) {
SC_Utils_Ex::sfDispSiteError(PRODUCT_NOT_FOUND);
} else {
// 入力値の変換
$this->arrErr = $this->lfCheckError($_POST[‘product_id’]);
if(count($this->arrErr) == 0) {
$objCartSess = new SC_CartSession();
$classcategory_id = "classcategory_id". $_POST[‘product_id’];
$classcategory_id1 = $_POST[$classcategory_id. ‘_1’];
$classcategory_id2 = $_POST[$classcategory_id. ‘_2’];
$quantity = "quantity". $_POST[‘product_id’];
// 規格1が設定されていない場合
if(!$this->tpl_classcat_find1[$_POST[‘product_id’]]) {
$classcategory_id1 = ‘0’;
}
// 規格2が設定されていない場合
if(!$this->tpl_classcat_find2[$_POST[‘product_id’]]) {
$classcategory_id2 = ‘0’;
}
$objCartSess->setPrevURL($_SERVER[‘REQUEST_URI’]);
$objCartSess->addProduct(array($_POST[‘product_id’], $classcategory_id1, $classcategory_id2), $_POST[$quantity]);
$this->sendRedirect($this->getLocation(URL_CART_TOP));
exit;
}
}
}
$this->tpl_subtitle = $tpl_subtitle;
// 支払方法の取得
$this->arrPayment = $this->lfGetPayment();
// 入力情報を渡す
$this->arrForm = $_POST;
$this->lfConvertParam();
$objView->assignobj($this);
$objCampaignSess->pageView($objView);
}
/**
* モバイルページを初期化する.
*
* @return void
*/
function mobileInit() {
$this->init();
}
/**
* Page のプロセス(モバイル).
*
* FIXME スパゲッティ…
*
* @return void
*/
function mobileProcess() {
}
/**
* デストラクタ.
*
* @return void
*/
function destroy() {
parent::destroy();
}
/* 商品一覧の表示 */
function lfDispProductsList($disp_num) {
$objQuery = new SC_Query();
$objDb = new SC_Helper_DB_Ex();
$this->tpl_pageno = defined("MOBILE_SITE") ? @$_GET[‘pageno’] : @$_POST[‘pageno’];
$arrval = array();
$arrval_order = array();
$arrval_category = array();
// ▼対象商品IDの抽出
// 商品検索条件の作成(未削除、表示)
$where = "del_flg = 0 AND status = 1 ";
// 在庫無し商品の非表示
if (NOSTOCK_HIDDEN === true) {
$where .= ‘ AND (stock_max >= 1 OR stock_unlimited_max = 1)’;
}
// ▲対象商品IDの抽出
$objQuery = new SC_Query();
$select = "select odd.product_id
from dtb_order od, dtb_order_detail odd
where od.order_id = odd.order_id AND ‘"
.date("Y-m-d h:i:s",strtotime("-1 day"))
."’ < od.create_date AND od.create_date < ‘".date("Y-m-d 23:59:59")."’";
$ret = $objQuery->getAll($select);
//商品毎の販売数のカウント
$arrCountSale = array();
foreach($ret as $key => $value){
$product_id = $value["product_id"];
if(!$arrCountSale[$product_id]){
$arrCountSale[$product_id] = 1;
} else {
$arrCountSale[$product_id]++;
}
}
arsort( $arrCountSale, SORT_NUMERIC );
$i = 0;
$arrProduct_id = array();
foreach($arrCountSale as $key => $value){
if($i < $this->arrPRODUCTLISTMAX){
$arrProduct_id[] = $key;
} else {
break;
}
$i++;
}
$arrProduct_id = array_keys($arrCountSale);
// 行数の取得
$linemax = count($arrProduct_id);
$this->tpl_linemax = $linemax; // 何件が該当しました。表示用
// ページ送りの取得
$this->objNavi = new SC_PageNavi($this->tpl_pageno, $linemax, $disp_num, "fnNaviPage", NAVI_PMAX);
$strnavi = $this->objNavi->strnavi;
$strnavi = str_replace(‘onclick="fnNaviPage’, ‘onclick="form1.mode.value=\”.’\’; fnNaviPage’, $strnavi);
// 表示文字列
$this->tpl_strnavi = empty($strnavi) ? " " : $strnavi;
$startno = $this->objNavi->start_row; // 開始行
// ▼商品詳細取得
$col = <<< __EOS__
product_id
,product_code_min
,product_code_max
,name
,comment1
,comment2
,comment3
,main_list_comment
,main_image
,main_list_image
,price01_min
,price01_max
,price02_min
,price02_max
,stock_min
,stock_max
,stock_unlimited_min
,stock_unlimited_max
,point_rate
,sale_limit
,sale_unlimited
,deliv_date_id
,deliv_fee
,status
,product_flag
,del_flg
__EOS__;
$from = "vw_products_allclass_detail AS alldtl";
// WHERE 句
$where = ‘0=0’;
if (is_array($arrProduct_id) && !empty($arrProduct_id)) {
$where .= ‘ AND product_id IN (‘ . implode(‘,’, $arrProduct_id) . ‘)’;
} else {
// 一致させない
$where .= ‘ AND 0<>0’;
}
// 取得範囲の指定(開始行番号、行数のセット)
$objQuery->setLimitOffset($disp_num, $startno);
// 検索結果の取得
$this->arrProducts = $objQuery->select($col, $from, $where, $arrval_order);
// ▲商品詳細取得
$tmpProducts = array();
foreach($arrCountSale as $key => $item){
foreach($this->arrProducts as $item2){
if($item2[‘product_id’] == $key){
$tmpProducts[]=$item2;
break;
}
}
}
$this->arrProducts = $tmpProducts;
// 規格名一覧
$arrClassName = $objDb->sfGetIDValueList("dtb_class", "class_id", "name");
// 規格分類名一覧
$arrClassCatName = $objDb->sfGetIDValueList("dtb_classcategory", "classcategory_id", "name");
// 規格セレクトボックス設定
if($disp_num == 15) {
for($i = 0; $i < count($this->arrProducts); $i++) {
$this->lfMakeSelect($this->arrProducts[$i][‘product_id’], $arrClassName, $arrClassCatName);
}
}
}
}
[/php]
次にテンプレートファイルを作成します。
/data/Smarty/templates/default/products/ranking.tpl
テンプレートは今回の場合、一覧表示画面のものを流用しますので
/data/Smarty/templates/default/list.tpl
/data/Smarty/templates/default/products/以下にをコピーしてlist.tplをranking.tplにリネームしてもらえばOKです。
ここまででページの追加は完了です。
実際に
http://shop_name/products/ranking.php
にアクセスすれば表示されるようになっていると思います。
※ランキングページなので、その日に売上がないと当然商品は表示されません。