EC-CUBE プラグインの作り方 最近チェックした商品の履歴プラグイン 作成事例 Amazon
EC-CUBE プラグインの作り方 最近チェックした商品の履歴プラグイン 作成事例
EC-CUBE プラグインの作り方 最近チェックした商品の履歴プラグイン 作成事例 ECCUBE最近チェックした商品の履歴プラグインを作ってみました。
EC-CUBEは万能ではありません
Amazonまで高機能までとはいいませんがEC-CUBEでも同様の買い物サイトが構築できます。 さてEC-CUBEで最近みた商品履歴を表示するにはどうすればよいのでしょうか?
※じつはEC-CUBEの標準機能ではAmazonのような最近みた商品履歴を表示することができません。 しかしEC-CUBEにはプラグイン機能が存在しており、必要な機能を追加することが可能です。 今回は実際にプラグインを作成しながらEC-CUBEのカスタマイズ方法について学んでいきたいとおもいます。
まずはつかえるプラグインをさがしてみましょう!
オーナーズストア http://www.ec-cube.net/owners/ ECキューブの拡張プラグインが数多く公開されています。無料のプラグインにも結構いけているものがそろっています。もちろん履歴表示するプラグインも存在しています!! 『最近チェックした商品ブロック』 プラグインのダウンロード人気も高いし、コメント評価も高いし、安心してつかえそうです。 が。。 スマフォには対応していない、他のプラグインと競合するケースがあるというコメントが気になります。 プラグインの作成ってそんなに難しいのでしょうか? 自作してしまえば機能やデザインも自由自在ですし。。 今回はカスタマイズの勉強なのであえて自作していくことにします。
ためしにプラグインをつくってみましょう!
・プラグイン機能仕様書をチェックします plugin.pdf hook_point.pdf
・作成する仕様をきめます。
要件 | 仕様 |
---|---|
履歴のデータ保存方法 | 非会員向けを想定しているためDBには記録できませんのでcookieを利用します。 |
履歴データの保存タイミング | 商品詳細を表示したときにcookieに書き込みます。 |
履歴データの表示方法 | 最近みた履歴ブロックを作成して任意のページで表示可能とします。 ※cookieに保存しているためガラケーはすておき、PCとスマフォに対応します。 |
履歴の保存件数の設定 | プラグインの設定画面を利用することにします。 |
・プラグイン名をきめます。 RecentAccessBlock
・ファイル構成をきめます。
フォルダ | ファイル名 | 説明 |
---|---|---|
RecentAccessBlock | (メインディレクトリ) | |
logo.png | プラグインアイコン | |
plugin_info.php | プラグイン情報 | |
plugin_update.php | プラグインアップデート用クラス. | |
RecentAccessBlock.php | プラグインメインクラス | |
LC_Page_FrontParts_Bloc_RecentAccessBlock.php | プラグイン処理クラス | |
config.php | 設定画面メインクラス | |
LC_Page_Plugin_RecentAccessBlock_Config.php | 設定画面処理クラス | |
./block | (サブディレクトリ) | |
recent_access.php | プラグイン実行クラス | |
./media | (サブディレクトリ) | |
recent_access.css | PC用CSS | |
recent_access_sp.css | スマフォ用CSS | |
tit_bloc_recent_access.png | デザインアイコン | |
recent_access_config.css | 設定画面用CSS | |
./templates | (サブディレクトリ) | |
header.tpl | CSS読み込み切り替え用テンプレート | |
recent_access.tpl | PC用テンプレート | |
recent_access_sp.tpl | スマフォ用テンプレート | |
config.tpl | 設定画面用テンプレート |
ざっとこんな形でしょうか?
最低限必要なものだけ作成して動かしてみましょう
用意するファイルは2つだけです。 さっそく書いてみましょう。
<?php /** * ユーザーが最近見た商品表示プラグインの情報クラス. */ class plugin_info{ /** プラグインコード(必須):プラグインを識別する為キーで、他のプラグインと重複しない一意な値である必要があります */ static $PLUGIN_CODE = "RecentAccessBlock"; /** プラグイン名(必須):EC-CUBE上で表示されるプラグイン名. */ static $PLUGIN_NAME = "ユーザーが最近見た商品"; /** プラグインバージョン(必須):プラグインのバージョン. */ static $PLUGIN_VERSION = "0.1"; /** 対応バージョン(必須):対応するEC-CUBEバージョン. */ static $COMPLIANT_VERSION = "2.12.3"; /** 作者(必須):プラグイン作者. */ static $AUTHOR = "株式会社フォーミックス"; /** 説明(必須):プラグインの説明. */ static $DESCRIPTION = "ユーザーが最近見た商品を表示するブロックを追加します。(PC/スマホのみ)"; /** プラグイン作者URL:プラグイン毎に設定出来るURL(説明ページなど) */ static $AUTHOR_SITE_URL = "http://www.fourmix.co.jp/"; /** クラス名(必須):プラグインのクラス(拡張子は含まない) */ static $CLASS_NAME = "RecentAccessBlock"; /** ライセンス */ static $LICENSE = "LGPL"; } ? >
RecentAccessBlock.php (プラグインメインクラス)
<?php /* * 最近見た商品表示プラグイン * プラグインのメインクラス */ class RecentAccessBlock extends SC_Plugin_Base { // コンストラクタ public function __construct(array $arrSelfInfo) { parent::__construct($arrSelfInfo); } //インストール function install($arrPlugin) { //TODOインストール処理の実装 } // アンインストール function uninstall($arrPlugin) { //TODOアンインストール処理の実装 } //アップデート function update($arrPlugin) { // nop } //プラグインを有効 function enable($arrPlugin) { //TODO プラグインを有効にした処理の実装 } //プラグインを無効 function disable($arrPlugin) { //TODO プラグイン停止した処理の実装 } //処理の介入箇所とコールバック関数を設定 function register(SC_Helper_Plugin $objHelperPlugin) { //TODO プラグインインスタンス生成時処理の実装 } } ?>
処理については記述していないスケルトンコードの状態ですがインストールは可能です。 ためしにEC-CUBEで動かしてみますが、これらのファイルは 圧縮(tar形式かtar.gz形式)してひとまとめにしないとインストールすることができません。 windows環境であればlhaplusなどでファイルをRecentAccessBlock.tarにかためてください。 出来上がったファイルをEC-CUBE管理サイト:オーナーズストア>プラグイン管理よりプラグイン登録してみましょう。 処理は記述していないので動作はしませんがまずまず順調ですね。 ここで気になるのは。。 圧縮しないとEC-CUBEにインストールできない!!
なにかファイルを変更するたびに圧縮して管理サイトからプラグインをアップデートしないと変更が反映されないのは面倒ですよね。 デバックするにもひと手間となりますし。。 ソースを直接変更しながら実際の挙動を確認しつつ実装をすすめることはできないのでしょうか?
ファイル圧縮しないでプラグインを実装するには
プラグインをインストールした時点で、実行ソースは下記フォルダに展開されます。
/data/downloads/plugin/プラグイン名/xxxx.php
DBにもデータがinsertされます。 ・dtb_plugin(プラグイン情報) ・dtb_plugin_hookpoint(プラグイン内で利用しているフックポイント) 結局のところ展開されているphpソースが毎回実行されるので、開発中はソースを直接編集しながら作業をすすめて、完成した時点でtar.gz形式にアーカイブするほうが効率的です。 ただしインストール時にDBに追加されたデータや、EC-CUBE独自のキャッシュ情報については、 ソースを変更しただけでは実行結果には反映されてきませんので注意が必要です。 役立ちそうな対応方法を記載しておきます。
項目 | 役立ちそうな対応方法 |
---|---|
フックポイントの定義 | メインクラスのregisterメソッドに定義しますが実際にはdtb_plugin_hookpointテーブルのデータが利用される |
あまりおすすめできませんが、dtb_plugin_hookpointにデータを追記しdtb_plugin_plugin_id_seqをインクリメントでも対応できます | |
管理サイトのテンプレート | smartyのキャッシュをクリアしないと反映されません |
/data/Smarty/templates_c/admin/ 配下のファイルを削除すれば反映されます | |
mtb_xxxテーブルの値 | キャッシュされている/data/cache/mtb_xxx.serialファイルの値を使用する |
該当する/data/cache/mtb_xxx.serialファイルを削除 ※mtb_xxxデータ参照時にmtb_xxx.serialファイルが作成されるので削除してもOK | |
パラメータ設定 | mtb_constantsに保存されている値 ※mtb_xxx系のテーブルですが、mtb_constantsだけは特殊なうごきをします。 /data/cache/mtb_constants.phpにキャッシュされいます。 |
mtb_constantsにデータをinsertしたあとに、管理サイト:システム設定>パラメーター設定画面を開いてそのまま「この内容で登録する」ボタンをクリックでOK |
まずはプラグイン設定(管理サイト側)から作成していたいと思います。
EC-CUBEの管理サイトに機能を追加する
EC-CUBEの管理サイトで設定情報を登録しておく方法はいくつかあります。 実装コストの高い順にならべみました。
種類 | 操作 | 実装方法 |
---|---|---|
専用管理画面 | 新設メニュー | 専用管理画面を作成する |
プラグイン設定 | 管理サイト:オーナーズストア>プラグイン設定 | 主にdtb_pluginテーブルのfree_field1~4を更新 |
マスターデータ | 管理サイト:システム設定>マスターデータ管理 | プレフィクス(mtb_)のテーブルを作成(id,Value) |
パラメーター設定 | 管理サイト:システム設定>パラメーター設定 | mtb_constantsに設定値を保存(Key,Value) |
今回は「プラグイン設定」を作成してみることにします。
プラグイン設定をつくってみる
プラグイン設定は管理サイトのプラグイン管理から表示されるポップ画面となります。 必要な機能実装は、画面表示、データ更新となります。 設定データの保存先はdtb_pluginテーブルを利用することにします。 dtb_pluginテーブルはインストールされているプラグインを管理するためのテーブルでプラグインをインストールした際にレコードが1行追加されま す。フリー項目カラムはプラグインが自由に使える項目として提供されており最大4個まで値を保持できます。(free_field1~4) ※それ以上の設定情報を保存する場合は新規にテーブルを用意するなどが必要となります。 今回はfree_field1を表示商品数に利用します。
プラグイン設定で最低限必要なファイルは3つです。 前回おつたえした直接ファイルを更新する方法でやってみましょう。 プラグインインストールで作成されたフォルダ(/data/downloads/plugin/RecentAccessBlock)に 下記3つのファイルを作成します。(※templatesフォルダは作成してください。)
templates/config.tpl (smartyテンプレート)
<!--{include file="`$smarty.const.TEMPLATE_ADMIN_REALDIR`admin_popup_header.tpl"}--> <script type="text/javascript"> </script> <h2><!--{$tpl_subtitle}--></h2> <!--{foreach from=$arrErr item=error}--> <p class="red"><!--{$error}--></p> <!--{/foreach}--> <form name="form1" id="form1" method="post" action="<!--{$smarty.server.REQUEST_URI|h}-->"> <input type="hidden" name="<!--{$smarty.const.TRANSACTION_ID_NAME}-->" value="<!--{$transactionid}-->" /> <input type="hidden" name="mode" value="edit"> <table border="0" cellspacing="1" cellpadding="8" summary=" "> <tr > <td bgcolor="#f3f3f3">表示商品数</td> <td> <!--{assign var=key value="free_field1"}--> <input type="text" name="free_field1" value="<!--{$arrForm[$key]}-->" maxlength="4"> </td> </tr> </table> <div class="btn-area"> <ul> <li> <a class="btn-action" href="javascript:;" onclick="document.form1.submit();return false;"><span class="btn-next">この内容で登録する</span></a> </li> </ul> </div> </form> <!--{include file="`$smarty.const.TEMPLATE_ADMIN_REALDIR`admin_popup_footer.tpl"}-->
config.php (設定画面メインクラス)
<?php require_once PLUGIN_UPLOAD_REALDIR . 'RecentAccessBlock/LC_Page_Plugin_RecentAccessBlock_Config.php'; $objPage = new LC_Page_Plugin_RecentAccessBlock_Config(); register_shutdown_function(array($objPage, 'destroy')); $objPage->init(); $objPage->process(); ? >
LC_Page_Plugin_RecentAccessBlock_Config.php (設定画面処理クラス)
<?php // {{{ requires require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php'; /** * 商品詳細マトリクス表示の設定クラス */ class LC_Page_Plugin_RecentAccessBlock_Config extends LC_Page_Admin_Ex { var $arrForm = array(); /** * 初期化する. * @return void */ function init() { parent::init(); $this->tpl_mainpage = PLUGIN_UPLOAD_REALDIR ."RecentAccessBlock/templates/config.tpl"; $this->tpl_subtitle = "ユーザーが最近見た商品 設定画面"; } /** * プロセス.s * @return void */ function process() { $this->action(); $this->sendResponse(); } /** * Page のアクション. * @return void */ function action() { $objFormParam = new SC_FormParam_Ex(); $this->lnitParam($objFormParam); $objFormParam->setParam($_POST); $objFormParam->convParam(); $arrForm = array(); switch ($this->getMode()) { case 'edit': $arrForm = $objFormParam->getHashArray(); $this->arrErr = $objFormParam->checkError(); // エラーなしの場合にはデータを更新 if (count($this->arrErr) == 0) { // データ更新 $this->arrErr = $this->updateData($arrForm); if (count($this->arrErr) == 0) { $this->tpl_onload = "alert('登録が完了しました。');"; } } break; default: // プラグイン情報を取得. $plugin = SC_Plugin_Util_Ex::getPluginByPluginCode("RecentAccessBlock"); $arrForm['free_field1'] = $plugin['free_field1']; break; } $this->arrForm = $arrForm; $this->setTemplate($this->tpl_mainpage); } /** * デストラクタ. * @return void */ function destroy() { parent::destroy(); } /** * パラメーター情報の初期化 * @param object $objFormParam SC_FormParamインスタンス * @return void */ function lnitParam(&$objFormParam) { $objFormParam->addParam('表示商品数', 'free_field1', INT_LEN, 'n', array('EXIST_CHECK', 'MAX_LENGTH_CHECK', 'NUM_CHECK', 'ZERO_CHECK')); } /** * プラグイン情報の更新 * @param type $arrData * @return type */ function updateData($arrData) { $arrErr = array(); $objQuery =& SC_Query_Ex::getSingletonInstance(); $objQuery->begin(); // UPDATEする値を作成する。 $sqlval = array(); $sqlval['free_field1'] = $arrData['free_field1']; $sqlval['update_date'] = 'CURRENT_TIMESTAMP'; $where = "plugin_code = 'RecentAccessBlock'"; // UPDATEの実行 $objQuery->update('dtb_plugin', $sqlval, $where); $result = $objQuery->commit(); return $arrErr; } } ? >
ファイルを配置しただけで動作する
はたしてファイルを配置しただけで動作するのでしょうか? この状態で管理サイトをみてみると。。 プラグイン設定のリンクが有効になっています!! プラグイン設定リンクをクリックすると。。 設定画面がポップアップ表示されまました。 今回のソースはそんなに難しいものではありませんが、 すこし解説しましょう。
/templates/config.tpl (smartyテンプレート)の解説
form1の値をsubmitでPOSTするだけのsmartyテンプレートです。
<input type="text" name="free_field1" value="<!--{$arrForm[$key]}-->" maxlength="4">
EC-CUBEのデフォルト設定ではsmartyタグは{}ではなく<–{ }–>となりますが中身は普通のsmartyテンプレートです。 dtb_pluginテーブルを更新するパターンであればほぼこの形でおきまりといえます。 free_field1で利用しているブロックをインクリメントして増やせばfree_field2~4も動作するようになります。
config.php (設定画面メインクラス)の解説
※このファイルが存在すると、管理サイトでプラグイン設定のリンクが有効になります。 プラグイン設定のリンクがリクエストされたときにどのクラスを実行するかを記述します。
$objPage = new LC_Page_Plugin_RecentAccessBlock_Config();
このサンプルではLC_Page_Plugin_RecentAccessBlock_Config.phpを実行するように記述してあります。
LC_Page_Plugin_RecentAccessBlock_Config.php (設定画面処理クラス)の解説
クラスはお決まりのパターンとしてLC_Page_Admin_Exを継承してつくります。 各メソッドを簡単に説明すると。。 ■function init() テンプレートファイルの指定と、画面に表示するプラグイン名を記述しています。
$this->tpl_mainpage = PLUGIN_UPLOAD_REALDIR ."RecentAccessBlock/templates/config.tpl"; $this->tpl_subtitle = "ユーザーが最近見た商品 設定画面";
■function process() おきまりのソースです。
$this->action(); $this->sendResponse();
■function action() これもEC-CUBEのおきまりパターンです テンプレートではリクエストパラメータ(mode)に処理内容を指定されています
<input type="hidden" name="mode" value="edit">
POSTされたパラメータはSC_FormParam_Ex返して受け取ってバリデーションを行います。
$objFormParam = new SC_FormParam_Ex(); $this->lnitParam($objFormParam); $objFormParam->setParam($_POST); $objFormParam->convParam();
処理を分岐します(search/edit/confirm/confirm_return/complete/deleteなど)
switch ($this->getMode()) { case 'edit':
■function lnitParam リクエストパラメータをバリデーションするおきまりパターンです。 チェックしたい項目をキー毎に指定しています。
$objFormParam->addParam('表示商品数', 'free_field1', INT_LEN, 'n', array('EXIST_CHECK', 'MAX_LENGTH_CHECK', 'NUM_CHECK', 'ZERO_CHECK'));
※指定可能なバリデーションの種類や内容は/data/class/SC_CheckError.phpをのぞいてみてください。 ■function updateData($arrData) データを更新しています。
$objQuery =& SC_Query_Ex::getSingletonInstance(); : $objQuery->update('dtb_plugin', $sqlval, $where);
SQLを記述せずにクエリーを実行しています。
実は今回のソースにEC-CUBEの基本処理パターンがすべて含まれていた!
作成した設定画面は要件も単純で実装したコードも簡単ですが基本動作はひととり存在しております。 もっと難しい処理を実装する場合も、このパターンを応用すれば対応することができます。
- 1.アクセスのあったURLからクラスに処理を引き渡す。
- config.phpで処理クラスLC_系クラスをNewしてコールする
- 2.パラメータの値を取得する
- 処理クラスのactionメソッドでSC_FormParam_Exを利用してとりだします。
- 3.パラメータの値の入力チェックを行う
- 処理クラスにlnitParamメソッドを作成してaddParamでチェックする内容を定義します。
- 4.パラメータにより処理を分岐する
- 処理クラスのactionメソッドでmodeを利用して分岐
- 5.DBの値を参照・更新する
- 各SC系のクラスを利用できます
機能 SC系クラス名 プラグイン設定情報 SC_Plugin_Util_Ex マスタ系テーブル(mtb_xx) SC_DB_MasterData_Ex 商品系テーブル SC_Product_Ex 会員系テーブル SC_Customer_Ex
- 6.テンプレートを表示する
- LC_Pageクラスに$this->xxxxxで設定した変数を smartyテンプレートから呼び出す
まとめ
※オープンソースは言葉のとおり処理内容が公開されています。 今回の基本パターンを手掛かりにして実際のEC-CUBEの処理クラスを眺めてみてください。 /data/class/SC系のクラス /data/class/pages/機能名フォルダ/LC系のクラス おのずとカスタマイズの方法がみえてきますよ。
次回は処理のフックに挑戦します。。