カート情報に任意のテキストを加えたい / 受注データにカスタムデータを追加する方法

EC-CUBEのシステム構造は非常に厄介なのですが、カート機能としてはすでに確立されすぎていて正攻法でいくとかなり安定したカスタマイズができるということもあって「覚えればOK」的な代物であります。いろいろ検索していたら商品詳細のページにオリジナルのフォームを作成してオリジナルのデータを格納する方法は比較的情報が少なかったのでご紹介。テストしてみたのは以下の環境。

  • EC-CUBE: 2.12.6
  • OS: CentOS 6.5
  • DBサーバー: MySQL 5.1.73
  • Apache/2.2.15

受注データにオリジナルの何らかのデータを追加したい場合は、EC-CUBEのDBテーブルのdtb_orderテーブルとdtb_order_tempにデータカラムを追加することになります。このテーブルは決済情報とかいろいろなデータが入ってきて他のプラグインが勝手にmemo01からmemo10まで恣意的に使ってしまうので、自分でカラムを追加した方がいいです。
ここでは、

  1. 商品詳細ページに新規でオリジナルのテキストエリアを作成して、
  2. その入力情報が受注完了時に受注データとして残る。
  3. 注文完了通知のメールにその情報を記載する。
  4. そのデータは管理画面の受注データ管理で見ることができる、編集することができる。

というところを目標にします。

テーブル名

  • dtb_order
  • dtb_order_temp

追加カラム名

  • addtext

テキストエリアのHTMLタグ
<textarea id="addtext" name="addtext"></textarea>

1. テーブルにカラムを追加する

以下2つのテーブルにカラムを追加します。
dtb_order
dtb_order_temp
カラムを追加する方法は何でもいいです。phpMyAdminを使ってもいいだろうしコマンドラインからDBにログインして作ってもいいです。この2つのテーブルに同じ名前のカラムを追加すればいいです。カラム名でデータの出し入れをしてくれるので場所はどこでもいいですが、カスタムカラムになるので最後の方がいいと思います。ここでは、addtextとでもしておきます。コマンドラインだと以下のようになるかと思います。
mysql> ALTER TABLE dtb_order ADD addtext TEXT DEFAULT NULL;
mysql> ALTER TABLE dtb_order_temp ADD addtext TEXT DEFAULT NULL;

2. 商品詳細ページにオリジナルのテキストエリアを作成

テンプレートの任意の場所にテキストフィールドを追加します。これは既存の<form></form>の間のどこかに追記してください。そうすると商品の受注データの1つとして一緒に値を運んでくれます。場所的には「カートに入れる」ボタンの手前とかそこら辺りになるかと思います。
[FILE]: data/Smarty/tmplates/default/products/detail.tpl
<textarea id="addtext" name="addtext"></textarea> ←これ追加
追加して保存するとテキストエリアができているので適当な値を入れて、カートに入れるボタンなどを押してください。そうすると押しても何も起きません。まだ値を受け取る準備ができていないからです。

3. テンプレートで作成したFormからデータの値を受けとって処理する

HTMLタグで作成したテキストエリアに値を入力すると、どこかでその値を受け取って処理しなくてはなりません。値を実際に受け取りファイルは以下になります。
[FILE]: data/class/pages/products/LC_Page_Products_Detail.php
345行目辺りで作成したインプットフィールドのnameで値を受けます。
lfInitParamというfunction内に規格や数量を受けるメソッドが書かれているので、それに追記します。

function lfInitParam(&$objFormParam) {

$objFormParam->addParam('規格1', 'classcategory_id1', INT_LEN, 'n', array('NUM_CHECK', 'MAX_LENGTH_CHECK'));
$objFormParam->addParam('規格2', 'classcategory_id2', INT_LEN, 'n', array('NUM_CHECK', 'MAX_LENGTH_CHECK'));
$objFormParam->addParam('数量', 'quantity', INT_LEN, 'n', array('EXIST_CHECK', 'ZERO_CHECK', 'NUM_CHECK', 'MAX_LENGTH_CHECK'));
$objFormParam->addParam('管理者ログイン', 'admin', INT_LEN, 'a', array('ALNUM_CHECK','MAX_LENGTH_CHECK'));
$objFormParam->addParam('商品ID', 'product_id', INT_LEN, 'n', array('EXIST_CHECK', 'ZERO_CHECK', 'NUM_CHECK', 'MAX_LENGTH_CHECK'));
$objFormParam->addParam('お気に入り商品ID', 'favorite_product_id', INT_LEN, 'n', array('ZERO_CHECK', 'NUM_CHECK', 'MAX_LENGTH_CHECK'));
$objFormParam->addParam('商品規格ID', 'product_class_id', INT_LEN, 'n', array('EXIST_CHECK', 'NUM_CHECK', 'MAX_LENGTH_CHECK'));

//追加データ
$objFormParam->addParam('追加テキスト', 'addtext', MTEXT_LEN, 'KVa', array('SPTAB_CHECK', 'MAX_LENGTH_CHECK')); ←これ追加

// 値の取得
$objFormParam->setParam($_REQUEST);
// 入力値の変換
$objFormParam->convParam();
// 入力情報を渡す
return $objFormParam->getFormParamList();
}

それから同ファイルの533行目あたりにでカートにデータを入れる作業を追加します。(かつてaction()だった関数が、doCart()になったのかな)
function doCart() {
$this->arrErr = $this->lfCheckError($this->mode,$this->objFormParam,
$this->tpl_classcat_find1,
$this->tpl_classcat_find2);
if (count($this->arrErr) == 0) {
$objCartSess = new SC_CartSession_Ex();
$product_class_id = $this->objFormParam->getValue('product_class_id');

$objCartSess->addProduct(
$product_class_id,
$this->objFormParam->getValue('quantity'),
$this->objFormParam->getValue('addtext') ←これ追加
);

SC_Response_Ex::sendRedirect(CART_URLPATH);
SC_Response_Ex::actionExit();
}
}

4. セッションに商品情報を渡す

230行目辺りに商品情報をセッション情報に受け渡す処理があります。ここにオリジナルのデータを入れ込みます。
このカートセッションに入れておくと買い物中はずっとそのデータを引っ張って歩いてくれます。なので、最後の買い物を完了するところまでここで引き渡したデータが引き継がれます。
[FILE]: data/class/SC_CartSession.php
// カートへの商品追加
function addProduct($product_class_id, $quantity,$addtext) { ←パラメーター追加
$objProduct = new SC_Product_Ex();
$arrProduct = $objProduct->getProductsClass($product_class_id);
$productTypeId = $arrProduct['product_type_id'];
$find = false;
$max = $this->getMax($productTypeId);
for ($i = 0; $i <= $max; $i++) { if ($this->cartSession[$productTypeId][$i]['id'] == $product_class_id) {
$val = $this->cartSession[$productTypeId][$i]['quantity'] + $quantity;
if (strlen($val) <= INT_LEN) { $this->cartSession[$productTypeId][$i]['quantity'] += $quantity;
}
$find = true;
}
}
if (!$find) {
$this->cartSession[$productTypeId][$max+1]['id'] = $product_class_id;
$this->cartSession[$productTypeId][$max+1]['quantity'] = $quantity;
$this->cartSession[$productTypeId][$max+1]['cart_no'] = $this->getNextCartID($productTypeId);
$this->cartSession[$productTypeId][$max+1]['addtext'] = $addtext; ←これ追加
}
}

300行目付近に
function adjustSessionProductsClass(&$arrProductsClass) {
$arrNecessaryItems = array(
'product_id' => true,
'product_class_id' => true,
'name' => true,
'price02' => true,
'point_rate' => true,
'main_list_image' => true,
'main_image' => true,
'product_code' => true,
'stock' => true,
'stock_unlimited' => true,
'sale_limit' => true,
'class_name1' => true,
'classcategory_name1' => true,
'class_name2' => true,
'classcategory_name2' => true,
'addtext' => true ←これ追加
);
//以下省略

ここまででカートセッションに出し入れができているはず。

5. データベースに書き込む準備

買い物が終わった時に受注データとして商品情報をデータベーステーブルに書き込むわけですが、その際にオリジナルのデータも一緒に書き込みます。
データは「確認画面で準備して」から書き込み処理をします。完了画面ではSC_CartSession.phpを呼び出して書き込み処理をしてます。100行目付近で追加テキストデータをカートの中から取り出しておきます。なんか強引に取り出したけどもっとスマートな書き方があるはず。(EC-CUBEなので)
data/class/pages/shopping/LC_Page_Shopping_Confirm.php
function action() {

$objSiteSess = new SC_SiteSession_Ex();

…省略

// カートの商品を取得
$this->arrShipping = $objPurchase->getShippingTemp($this->is_multiple);
$this->arrCartItems = $objCartSess->getCartList($this->cartKey);

//var_dump($this->arrCartItems); ←ここでカート内のデータをダンプしてみる

foreach ($this->arrCartItems as $num=>$arrItem) {
foreach ($arrItem as $key=>$value) {
if ($key=='addtext') {
$addtext = $value;
}
}
}
//print $addtext;

$addtextとして取り出したら、データベースに書き込む関数に渡してやります。dtb_orderテーブルにインサートする関数に引き渡すには、150行付近にある$objCartSess->calculateというメソッドにパラメーターを追加します。
$arrCalcResults = $objCartSess->calculate($this->cartKey, $objCustomer,
$arrOrderTemp['use_point'],
$objPurchase->getShippingPref($this->is_multiple),
$arrOrderTemp['charge'],
$arrOrderTemp['discount'],
$arrOrderTemp['deliv_id'],
$addtext ←これ追加
);

このメソッドに値を渡しておくとSC_CartSessionが値を引き取ってデータベースに格納してくれます。

6. 最後の最後でデータベースに書き込む

再びSC_CartSession.phpを開いて、600行付近にあるcalculateという関数を探します。ここで買い物の最終的な計算を行なっています。ですので、ここにまぎれてオリジナルのデータも追加してデータベースに書き込んでしまおうという魂胆です。この関数は、最後の最後で$results['カラム名']という変数に格納してあるデータをすべてdtb_orderに書き込んでくれます。returnする手前ぐらいでresultsという連想配列に値を書き込んでいます。
[FILE]: data/class/SC_CartSession.php
function calculate($productTypeId, &$objCustomer, $use_point = 0,
$deliv_pref = '', $charge = 0, $discount = 0, $deliv_id = 0,
$addtext ←これ追加
) {

$results = array();
$total_point = $this->getAllProductsPoint($productTypeId);

省略

$results['addtext'] = $addtext;

//var_dump($results);
return $results;
}

ここできてやっとできている感じなんですが、これを管理画面から触れるとかメールテンプレートに何するとか、まあ、きりがないですね。

参考: