絶対必要!EC-CUBEの毎回行うカスタマイズをピックアップ。

絶対必要!EC-CUBEの毎回行うカスタマイズをピックアップ
数年ぶりに夏風邪をひいてしまい、これが老いかと感じています。
さて、最近EC-CUBEのカスタマイズ案件が続きましたので、
毎回必ず発生するカスタマイズをまとめましたので紹介します。
(EC-CUBEのバージョンは2.13)

商品情報に項目を追加 発生率:☆☆☆☆☆

EC-CUBEは色々なジャンルのECサイトに対応できますが、
ショップに専門性を持たせたい場合に独自の商品情報を持たせる必要が出てきます。

今回はYoutube貼り付け用のIDを入力する欄を用意します。
まずはphpMyAdmin等のツールを使って、データベースに項目を追加します。
商品情報に関するデータはdtb_productsというテーブルに入るので、
Youtube貼付け用のIDを保存する「Youtube」というカラムを追加します。
商品情報に項目を追加
これでDBの設定ができたので、次に管理画面に入力欄を表示させます。
場所はどこでも良いので、他の部分を参考に追加します。
/data/Smarty/templates/admin/products/product.tpl

<tr>
  <th>Youtube</th>
  <td>
    <span class="attention"><!--{$arrErr.youtube}--></span>
    <input type="text" name="youtube" value="<!--{$arrForm.youtube|h}-->" maxlength="<!--{$smarty.const.STEXT_LEN}-->"
      style="<!--{if $arrErr.youtube != ""}-->background-color: <!--{$smarty.const.ERR_COLOR}-->;<!--{/if}-->"
      size="60" class="box60" />
    <span class="attention"> (上限<!--{$smarty.const.STEXT_LEN}-->文字)</span>
  </td>
</tr>

確認画面にも追加します。
/data/Smarty/templates/admin/products/confirm.tpl

<tr>
  <th>Youtube</th>
  <td>
    <!--{$arrForm.youtube|h}-->
  </td>
 </tr>

次にclassファイルを編集して、入力内容をDBに保存するようにします。
/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php
lfInitFormParam内の350行目当たりにYoutubeの項目を追加します。

 ・
 ・
$objFormParam->addParam('temp_main_large_image', 'temp_main_large_image', '', '', array());
//Youtubeを追加
$objFormParam->addParam('Youtube', 'youtube', STEXT_LEN, 'KVa', array('SPTAB_CHECK', 'MAX_LENGTH_CHECK'));

addParamの内容は追加する項目の種類によって内容が異なるので、
他の項目を参考にしてください。

  • 項目名
  • キー名(DBのカラム名)
  • 入力する値の上限(一部)
    STEXT_LEN:50文字
    MTEXT_LEN:200文字
    LTEXT_LEN:99999文字
    URL_LEN:URLの文字列、1024文字
  • 入力文字列の変換(一部)
    K:半角カナ から 全角カナへ
    C:全角かな から 全角カナへ
    V:濁点の文字を一文字に
    a:全角英数字 を 半角英数字に
  • 入力内容のチェック(一部)
    NUM_CHECK:数字のみでなければエラー
    MAX_LENGTH_CHECK:文字数が指定より大きければエラー
    EXIST_CHECK:必須入力でなければエラー
    SPTAB_CHECK:スペース、タブ、改行のみの場合エラー

1000行目付近のlfRegistProductにも追加します。

// 配列の添字を定義
$checkArray = array('name', 'status',
  'main_list_comment', 'main_comment',
  'deliv_fee', 'comment1', 'comment2', 'comment3',
  'comment4', 'comment5', 'comment6',
  'sale_limit', 'deliv_date_id', 'maker_id', 'note', ‘youtube');
$arrList = SC_Utils_Ex::arrayDefineIndexes($arrList, $checkArray);
// INSERTする値を作成する。
 ・
 ・
 ・
$sqlval['maker_id'] = $arrList['maker_id'];
$sqlval['note'] = $arrList['note'];
//Youtubeを追加
$sqlval[’youtube'] = $arrList[‘youtube'];

これでDBへ保存できるようになりました。
最後に商品詳細ページのHTMLへ、表示したい部分に追加します。
/data/Smarty/templates/default/products/detail.tpl

<!--★Youtube★-->
<div>
  <iframe src="https://www.youtube.com/embed/<!--{$arrProduct.youtube|h}-->" width="560" height="315"
  frameborder="0" allowfullscreen="allowfullscreen"></iframe>
</div>

注意すべき点として、商品CSVで扱う項目は今回追加した商品情報とは別になります。
ですのでCSVに対応しようとすると別の作業が必要になります。

ログイン判定 発生率:☆☆☆☆☆

ログインしている時だけ表示させたいものもありますよね、
このカスタマイズも必ずと言って良いほど発生します。
実装するには、まず全ページ共通で使用するclassファイルを編集します。
/data/class/pages/LC_Page.php
init()の一番最後に下記を追加します。

// ログイン判定
$objCustomer = new SC_Customer_Ex();
if ($objCustomer->isLoginSuccess() === true) {
  $this->tpl_login = true;
}

あとは追加したい.tplファイルに追加するだけです。

<!--{if $tpl_login}-->
  ログイン中です。
<!--{else}-->
  ログインしていません。
<!--{/if}-->

メーカーに画像追加 発生率:☆☆☆☆★

メーカーにはメーカー名とURLを設定することができます。
しかし画像を追加することができません。
ですのでメーカー画像を追加、表示させたい場合はカスタマイズが必要になります。

メーカー情報に関するデータはdtb_makerというテーブルに入るので、
メーカー画像のパスを保存するimage_keyというカラムを追加します。

DBに画像パスのカラムを追加したら、管理画面のメーカー登録のclassファイルを編集します。
/data/class/pages/admin/products/LC_Page_Admin_Products_Maker.php
action()内のswitch文の前に、ファイルをアップロードする為の設定をします。
またsetHiddenFileListは一時的にhiddenパラメータに情報を保持するためのものです。

//maker_idを変数にセット
$maker_id = $objFormParam->getValue('maker_id');
//画像登録
$this->objUpFile = new SC_UploadFile_Ex(IMAGE_TEMP_REALDIR, IMAGE_SAVE_REALDIR);
$this->objUpFile->addFile('メーカー画像', 'maker_image', array('gif','jpeg','jpg','png'), IMAGE_SIZE, false, 240, 240);
$this->objUpFile->setHiddenFileList($_POST);
// モードによる処理切り替え
switch ($this->getMode()) {

更に編集処理(case ‘edit’)の中に、アップロードされたファイルを画像保存用のディレクトリに保存し、そのパスをDBに保存します。

// POST値の引き継ぎ
$arrParam = $objFormParam->getHashArray();
//画像保存
if($arrParam['image_key']) {
  //ファイルの存在チェック
  $this->arrErr = $this->objUpFile->checkExists($arrParam['image_key']);
  //画像保存用のディレクトリに保存
  $this->arrErr[$arrParam['image_key']] = $this->objUpFile->makeTempFile($arrParam['image_key']);
  $this->objUpFile->moveTempFile();
  $filename = $this->objUpFile->getDBFileList();
  $arrParam['image_key'] = $filename['maker_image'];
  //保存できた場合、画像情報を追加して取得
  if(!$arrParam['image_key']) {
    $maker = $objMaker->getMaker($maker_id);
    if($maker['image_key']) {
      $arrParam['image_key'] = $maker['image_key'];
    }
  }
} else {
  unset($arrParam['image_key']);
}
// 登録実行
$res_maker_id = $this->doRegist($maker_id, $arrParam, $objMaker);

メーカー画像の情報がDBへ保存されている場合、画像パスを取得するようにします。

$this->arrForm = $objFormParam->getFormParamList();
$this->arrFile = $this->objUpFile->getFormFileList(IMAGE_TEMP_URLPATH, IMAGE_SAVE_URLPATH);
if($maker_id && $maker['image_key']) {
  $this->arrFile['maker_image']['filepath'] = IMAGE_SAVE_URLPATH. $maker['image_key'];
}
// メーカー情報読み込み
$this->arrMaker = $objMaker->getList();

次にメーカー情報を取得するclassにメーカー画像を取得するように変更します。
getList()で取得しているので、カラムにimage_keyを追加するだけです。
/data/class/helper/SC_Helper_Maker.php

$objQuery =& SC_Query_Ex::getSingletonInstance();
$col = 'maker_id, name, image_key';
$where = '';

以上でclassの変更は終わりです。
後はtplファイルを変更すれば画像を追加できるようになります。
/data/Smarty/templates/admin/products/maker.tpl

画像をpostできるようにenctypeを追加します。

<form id="form1" action="?" enctype="multipart/form-data" method="post" name="form1">

またhidden値も加えます。

<input type="hidden" name="image_key" value="maker_image" />

編集時のメーカー画像と、メーカー画像をアップロードする為のinputタグを追加します。
(ついでに画像の取り消しボタンも加えています。)

<tr>
  <th>メーカー画像</th>
  <td>
    <!--{if $arrFile.maker_image.filepath != ""}-->
      <img src="<!--{$arrFile.maker_image.filepath}-->" width="100" alt="">
        <a href="" onclick="eccube.setModeAndSubmit('delete_image', 'image_key', 'maker_image'); return false;">
          [画像の取り消し]
        </a><br />
    <!--{/if}-->
    <input type="file" name="maker_image" />
  </td>
</tr>

最後に一覧に画像を表示させるようにします。

<td>
  <!--{if $arrMaker[cnt].image_key}-->
    <img src="<!--{$smarty.const.IMAGE_SAVE_URLPATH}--><!--{$arrMaker[cnt].image_key|h}-->" width="60" alt="">
  <!--{/if}-->
</td>

以上でメーカー画像の確認、登録ができるようになりました。
先ほど追加した画像削除の処理はswitch文に追加することで可能になります。

case 'delete_image':
  // エラーチェック
  $this->arrErr = $this->lfCheckError($objFormParam, $objMaker);
  if (!SC_Utils_Ex::isBlank($this->arrErr['maker_id'])) {
    trigger_error('', E_USER_ERROR);return;
  }
  if (count($this->arrErr) <= 0) {
    // POST値の引き継ぎ
    $arrParam = $objFormParam->getHashArray();
    $arrParam['image_key'] = NULL;
    // 登録実行
    $res_maker_id = $this->doRegist($maker_id, $arrParam, $objMaker);
    if ($res_maker_id !== FALSE) {
      // 完了メッセージ
      $this->tpl_onload = "alert('登録が完了しました。');";
      $this->objUpFile->deleteFile($arrParam['image_key']);
      SC_Response_Ex::reload();
    } else {
      $this->arrErr['maker_id'] = '登録に失敗しました。';
    }
  }
  break;

カテゴリ画像も同様に行えば、画像を追加することが出来るようになります。

関連商品の相互管理 発生率:☆☆☆☆★

EC-CUBEでは関連商品の登録を行うことができます。
商品[A]の関連商品として商品[B]という商品を登録すれば、ユーザへ商品の訴求機会を増やすことができます。

ただしこの場合、[B]の関連商品として[A]は登録されておらず再度登録を行う必要があります。
これを解決するために一方の登録を行うと、お互いに関連商品として登録されるようにカスタマイズを行います。

関連商品の登録は、/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php
lfInsertRecommendProducts()で行います。
$sqlval[‘product_id’]が登録元商品、$sqlval[‘recommend_product_id’]が登録先商品なので、
これを逆にして再度insertを実行するだけです。

$sqlval['update_date'] = 'CURRENT_TIMESTAMP';
$objQuery->insert('dtb_recommend_products', $sqlval);
//関連商品に登録された商品にも追加
$sqlval['recommend_product_id'] = $product_id;
$sqlval['product_id'] = $arrList[$keyname];
$objQuery->insert('dtb_recommend_products', $sqlval);
$sqlval['product_id'] = $product_id;
$rank--;

登録はこれでいいのですが、削除した際にも相互削除を行う必要があります。
lfInsertRecommendProducts()の最初に全て削除を行っているので、
同様に登録先も削除します。

// 一旦関連商品を全て削除する
$objQuery->delete('dtb_recommend_products', 'product_id = ?', array($product_id));
$objQuery->delete('dtb_recommend_products', 'recommend_product_id = ?', array($product_id));

以上で完了です。
ただこのカスタマイズでは相互登録が自動で行われるので、
最初のように一方だけ関連商品として登録ができなくなるので注意が必要です。

商品の並び順 発生率:☆☆☆★★

商品一覧のソートは新着順、価格順が用意されていますが、
他の項目で並び替えを行いたい場合があります。

.tplファイル(/data/Smarty/templates/default/products/list.tpl)の
javascript:fnChangeOrderby(‘xxxx’)に渡す値によって、
/data/class/pages/products/LC_Page_Products_List.php
のlfGetProductsList()内のswitch文が実行されます。
カスタマイズも難しくなく、必要なソートを新たに追加するだけです。

// 販売価格が高い順
case 'price_high':
  $objProduct->setProductsOrder('price02', 'dtb_products_class', 'DESC');
  break;

またsqlを生成することで、独自のソート機能も作成することができます。
下記は購入数順のソートになります。

// 購入数順
case 'popular':
  $col = 'count(T2.product_id) as order_count';
  $from = "dtb_order_detail AS T2";
  $where = 'T2.product_id = alldtl.product_id';
  $sub_sql = $objQuery->getSql($col, $from, $where);
  $objQuery->setOrder("sort_status DESC, ($sub_sql) DESC");
  break;

いかがでしたでしょうか。
EC-CUBEがあればECサイトに必要な機能の全てが揃うというわけではありませんが、カスタマイズを行うことで使いやすくもなりますし、オープンソースであるため独自のショップを比較的安価で始めることができます。

独自の構成をしているので最初は慣れないかもしれませんが、上記のカスタマイズを参考に少しずつでも改善を行えば徐々に理解も深まってくると思います。