EC-CUBEカスタマイズ – 商品詳細ページにテキスト入力欄を追加を試す

EC-CUBEカスタマイズ – 商品詳細ページにテキスト入力欄を追加を試す

参考:EC-CUBEカスタマイズ - 商品詳細ページにテキスト入力欄を追加|ネットショップ構築&運営サポート - ビー・フレンド

例えば、ハンコの名前部分を入力してもらうとか、規格で管理できないほどの多量のサイズとかを入力してもらうようにできる。

参考ページの手順で導入してみたけれど、テキスト入力欄設定されていない商品をカートに入れることができない不具合があるみたい。あと、PostgreSQLの場合は、Viewを再生成する必要がある。

環境

  • EC-CUEB 2.4.4
  • PostgreSQL
  • データベース編集

    • テキスト入力欄を表示するか否かを判別するフラグ
      • 対象テーブル:dtb_products
      • 追加カラム:add_flg (データ型: integer)
    • テキスト入力欄(テキストボックス)
      • 対象テーブル:dtb_order_detail
      • 追加カラム:add_field (データ型: text)
    ALTER TABLE dtb_products ADD COLUMN add_flg integer;
    ALTER TABLE dtb_order_detail ADD COLUMN add_field text;

    ポイント

    pgsqlの場合はdtb_productsにカラムを追加したらviewの再生成が必要になる。

  • [EC-CUBE カスタマイズ日誌] 第 5 回 商品のサブ画像の数を増やしたい! | バシャログ。
  • EC-CUBE インストールディレクトリにある install/sql/create_view.sql を適宜変更して実行する。

    変更前

    CREATE VIEW vw_products_allclass_detail AS
        SELECT
            dtb_products.product_id,
            dtb_products."name",
                         ....略
            dtb_products.update_date,
            dtb_products.deliv_date_id,
            T4.product_code_min,

    変更後

    CREATE VIEW vw_products_allclass_detail AS
        SELECT
            dtb_products.product_id,
            dtb_products."name",
                         ....略
            dtb_products.update_date,
            dtb_products.deliv_date_id,
            dtb_products.add_flg,  ←追加
            T4.product_code_min,

    vw_products_allclass が vw_products_allclass_detail に依存しているので、vw_products_allclassを破棄してから vw_products_allclass_detailを破棄する。
    その後に vw_products_allclass_detail を作成、vw_products_allclass とする。
    PHP PgAdminでも出来ます。(viewの削除後に該当のSQLを実行)

    追記(2011-09-16):vw_products_nonclass が管理ページの商品管理>商品登録で使われているのでこちらもviewの再生成が必要。
    vw_product_classも念のため再生成した方がいいかも。

    商品詳細ページ

    1-1) [eccube]/data/Smarty/templates/default/detail.tpl
    ([eccube]/html/user_data/packages/default/detail.tpl)

              	<input name="add_field" class="box54" value="<!--{$add_field}-->" style="" type="text" />
    
    <!--{$add_field}--> を <!--{$arrForm.add_field.value|escape}-->に。

    元の変更後コードだと、フォーム内容が消えてしまうので修正。
    さらにエラーの場合はコメント&CSS変更させる。

    さらに、LC_Page_Products_Detail.php のソースコードの関係で、フォームチェックが商品詳細を読み込む前に行われているので、hidden を使ってフォームチェックを追加してあげる(元のコードをあまり変えたくないので苦肉の策)

              	<input name="add_field" class="box54" value="<!--{$arrForm.add_field.value|escape}-->" style="<!--{$arrErr.add_field|sfGetErrorColor}-->" type="text" />
              	<input type="hidden" name="add_flg_check" value="1" />
    
                    <!--{if $arrErr.add_field != ""}-->
                        <br /><span class="attention"><!--{$arrErr.add_field}--></span>
                    <!--{/if}-->

    こんな感じになる。

    2) [eccube]/data/class/pages/products/LC_Page_Products_Detail.php
    function process() {

    先ほど追加したhidden項目を lfCheckError(); で使うために内部変数に代入しておく。

    変更前

            // 規格選択セレクトボックスの作成
            $this->lfMakeSelect($tmp_id);
    
            // 商品IDをFORM内に保持する。
            $this->tpl_product_id = $tmp_id;

    変更後

            // 規格選択セレクトボックスの作成
            $this->lfMakeSelect($tmp_id);
    
            // 商品IDをFORM内に保持する。
            $this->tpl_product_id = $tmp_id;
    
            // FORMからテキスト入力欄フラグチェックを読み込む
            $this->add_flg_check = $_POST['add_flg_check'];

    function process() {
    case 'cart':

    2-2)

    $objCartSess->addProduct(array($_POST['product_id'], $classcategory_id1, $classcategory_id2, $add_field), $this->objFormParam->getValue('quantity'));

    修正箇所はモバイルプロセスにもある。モバイルでも行うには修正必須?

    2-3) function lfInitParam() {

    変更後

            $this->objFormParam->addParam("規格2", "classcategory_id2", INT_LEN, "n", array("NUM_CHECK", "MAX_LENGTH_CHECK"));
            $this->objFormParam->addParam("テキスト入力欄", "add_field", INT_LEN, "n", array("EXIST_CHECK", "MAX_LENGTH_CHECK"));
            $this->objFormParam->addParam("個数", "quantity", INT_LEN, "n", array("EXIST_CHECK", "ZERO_CHECK", "NUM_CHECK", "MAX_LENGTH_CHECK"));

    となっているが、テキスト入力欄の EXIST_CHECK があると、テキスト入力欄を設定されていない商品をカートに追加できない。function lfCheckError()でチェックするように変更する。
    また、INT_LEN では入力できる文字数が少なすぎるので、STEXT_LEN、SMTEXT_LEN、MTEXT_LEN、MLTEXT_LEN、LTEXT_LEN、LLTEXT_LEN あたりを使用する方が良さそう。

    再変更後

            $this->objFormParam->addParam("規格2", "classcategory_id2", INT_LEN, "n", array("NUM_CHECK", "MAX_LENGTH_CHECK"));
            //$this->objFormParam->addParam("テキスト入力欄", "add_field", INT_LEN, "n", array("EXIST_CHECK", "MAX_LENGTH_CHECK"));//EXIST_CHECKがあるとテキスト入力欄設定されていない商品が追加できないので EXIST_CHECK を削除する
            $this->objFormParam->addParam("テキスト入力欄", "add_field", STEXT_LEN, "n", array("MAX_LENGTH_CHECK"));//
            $this->objFormParam->addParam("個数", "quantity", INT_LEN, "n", array("EXIST_CHECK", "ZERO_CHECK", "NUM_CHECK", "MAX_LENGTH_CHECK"));

    2-4) function lfCheckError() {

    変更後

            if ($this->tpl_classcat_find2) {
                $objErr->doFunc(array("規格2", "classcategory_id2"), array("EXIST_CHECK"));
            }
    
            $objErr->doFunc(array("テキスト入力欄", "add_field"), array("EXIST_CHECK"));
    
            return $objErr->arrErr;

    となっているけど、これを

    再変更後

            if ($this->tpl_classcat_find2) {
                $objErr->doFunc(array("規格2", "classcategory_id2"), array("EXIST_CHECK"));
            }
    
            if ($this->add_flg_check) { // ←追加
                $objErr->doFunc(array("テキスト入力欄", "add_field"), array("EXIST_CHECK"));
            } // ←追加
            return $objErr->arrErr;

    とする。

    と、まぁ前半部分(カートページ [eccube]/data/class/helper/SC_Helper_DB.php まで)はこのくらいの修正で大丈夫かな。
    テキスト入力欄の場合は入力必須、その他の場合もカートに追加できるのまで確認済み。同じ商品の同じ規格でもテキスト入力欄を使えば別々の商品としてカートに追加されるので便利。


    以下メモ(編集中)

    参考ページの管理画面以下の作業は
    [eccube]/data/Smarty/templates/default/shopping/confirm.tpl
    を除いてうまくいかない部分が多いので書きなおして以下の作業を実行する。
    参考ページにほぼ習って書く。

    管理画面

    [eccube]/data/Smarty/templates/default/admin/products/product.tpl
    テンプレートなので表示される場所は好みの問題。
    変更前

                                        <tr class="fs12n">
                                            <td bgcolor="#f2f1ec" width="160">商品ステータス</td>
                                            <td bgcolor="#ffffff" width="557">
                                            <!--{html_checkboxes name="product_flag" options=$arrSTATUS selected=$arrForm.product_flag}-->
                                            </td>
                                        </tr>
    
                                        <!--{if $tpl_nonclass == true}-->

    変更後

                                        <tr class="fs12n">
                                            <td bgcolor="#f2f1ec" width="160">商品ステータス</td>
                                            <td bgcolor="#ffffff" width="557">
                                            <!--{html_checkboxes name="product_flag" options=$arrSTATUS selected=$arrForm.product_flag}-->
                                            </td>
                                        </tr>
    
                                        <!--フラグ設定-->
                                        <tr class="fs12n">
                                            <td bgcolor="#f2f1ec" width="160">フラグ設定</td>
                                            <td bgcolor="#ffffff" width="557">
                                                <label><input type="checkbox" name="add_flg" value="1" <!--{if $arrForm.add_flg == 1}-->checked="checked"<!--{/if}--> />テキスト入力欄を表示する</label>
                                            </td>
                                        </tr>
                                        <!--ここまで--> 
    
                                        <!--{if $tpl_nonclass == true}-->

    [eccube]/data/Smarty/templates/default/admin/products/confirm.tpl
    変更前

                                    <!--{if $tpl_nonclass == true}-->
                                    <tr>
                                        <td bgcolor="#f2f1ec" width="160" class="fs12n">商品コード</td>

    変更後

                                    <tr>
                                        <td bgcolor="#f2f1ec" width="160" class="fs12n">フラグ設定</td>
                                        <td bgcolor="#ffffff" width="557" class="fs12n">
                                            [テキスト入力欄]<!--{$arrDISP[$arrForm.add_flg]}--><br />
                                        </td>
                                    </tr>
    
                                    <!--{if $tpl_nonclass == true}-->
                                    <tr>
                                        <td bgcolor="#f2f1ec" width="160" class="fs12n">商品コード</td>

    [eccube]/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php
    参考ページのままでok?
    ※pgsqlの場合 view vw_products_nonclass を再生成しないと商品登録フォームで値が取れない。

    function lfRegistProduct($arrList) { 内の
    配列の添字を定義

    変更前

                                "sale_limit", "sale_unlimited", "deliv_date_id", "note");
            $arrList = SC_Utils_Ex::arrayDefineIndexes($arrList, $checkArray);

    変更後

                                "sale_limit", "sale_unlimited", "deliv_date_id", "note", "add_flg");
            $arrList = SC_Utils_Ex::arrayDefineIndexes($arrList, $checkArray);

    // INSERTする値を作成する。部分

    変更前

            $sqlval['creator_id'] = $_SESSION['member_id'];
            $arrRet = $this->objUpFile->getDBFileList();

    変更後

            $sqlval['creator_id'] = $_SESSION['member_id'];
            $sqlval['add_flg'] = $arrList['add_flg'];
            $arrRet = $this->objUpFile->getDBFileList();

    function lfConvertParam($array) { 内
    // スポット商品
    変更前

            $arrConvList['comment1'] = "a";
            $arrConvList['deliv_fee'] = "n";
    
            // 詳細-サブ

    変更後

            $arrConvList['comment1'] = "a";
            $arrConvList['deliv_fee'] = "n";
            $arrConvList['add_flg'] = "n";
    
            // 詳細-サブ

    受注管理(管理画面)

    [eccube]/data/Smarty/templates/default/shopping/confirm.tpl
    受注管理(管理画面)となっているけど、管理用ではない。参考ページのままでおk。
    コピペです。

    変更前

                  <li><!--{$arrProductsClass[cnt].class_name2}-->:<!--{$arrProductsClass[cnt].classcategory_name2}--></li>
                  <!--{/if}-->
                </ul>
             </td>
             <td class="pricetd">

    変更後

                  <li><!--{$arrProductsClass[cnt].class_name2}-->:<!--{$arrProductsClass[cnt].classcategory_name2}--></li>
                  <!--{/if}-->
    
                  <!--{ if $arrProductsDetails[cnt].add_field!="" }-->
                      テキスト入力欄:<!--{$arrProductsDetails[cnt].add_field}--><br />
                  <!--{/if}-->
    
              </ul>
             </td>
             <td class="pricetd">

    [eccube]/data/Smarty/templates/default/admin/order/edit.tpl

    参考ページの変更場所よりも以下を修正したほうが見やすいかな?
    さらに、管理受注画面で編集する処理が暫定となっているみたいなので、対応するために hidden項目を追加する。

    変更前

                                    <td width="215">
                                        <!--{$arrForm.product_name.value[$key]|escape}-->/<!--{$arrForm.classcategory_name1.value[$key]|escape|default:" (なし)"}-->/<!--{$arrForm.classcategory_name2.value[$key]|escape|default:" (なし)"}-->

    変更後

                                        <!--{if $arrForm.add_field.value[$key] !="" }-->
                                        <br />
                                        [備考欄]<!--{$arrForm.add_field.value[$key]|escape}-->
                                        <!--{/if}-->
                                        <input type="hidden" name="add_field[<!--{$key}-->]" value="<!--{$arrForm.add_field.value[$key]}-->" id="add_field_<!--{$key}-->">

    [eccube]/data/Smarty/templates/default/admin/order/disp.tpl
    受注管理>ステータス管理 の注文番号にリンクが貼られているが、その時に表示されるページもテンプレートを変更する必要がある。(2011/09/30追記)
    変更前

                                    <td width="215"><!--{$arrForm.product_name.value[$key]|escape}-->/<!--{$arrForm.classcategory_name1.value[$key]|escape|default:" (なし)"}-->/<!--{$arrForm.classcategory_name2.value[$key]|escape|default:"(なし)"}--></td>

    変更後

                                    <td width="215"><!--{$arrForm.product_name.value[$key]|escape}-->/<!--{$arrForm.classcategory_name1.value[$key]|escape|default:" (なし)"}-->/<!--{$arrForm.classcategory_name2.value[$key]|escape|default:"(なし)"}-->
                                                                        <!--{if $arrForm.add_field.value[$key] !="" }-->
                                        <br />
                                        [テキスト入力欄]<!--{$arrForm.add_field.value[$key]|escape}-->
                                        <!--{/if}--></td>

    [eccube]/data/class/pages/admin/order/LC_Page_Admin_Order_Edit.php

    function lfInitParam() { 内

    変更前

            $this->objFormParam->addParam("規格名2", "classcategory_name2");
            $this->objFormParam->addParam("メモ", "note", MTEXT_LEN, "KVa", array("MAX_LENGTH_CHECK"));

    変更後

            $this->objFormParam->addParam("規格名2", "classcategory_name2");
            $this->objFormParam->addParam("テキスト入力欄", "add_field");
            $this->objFormParam->addParam("メモ", "note", MTEXT_LEN, "KVa", array("MAX_LENGTH_CHECK"));

    ※参考ページではproduct_add_field となっているので注意。

    function lfGetOrderDetail($order_id) { 内

    変更前

            $col = "product_id, classcategory_id1, classcategory_id2, product_code, product_name, classcategory_name1, classcategory_name2, price, quantity, point_rate";

    変更後

            $col = "product_id, classcategory_id1, classcategory_id2, product_code, product_name, classcategory_name1, classcategory_name2, price, quantity, point_rate, add_field";

    ※ 参照ページでは add_field product_add_field となっているので注意

    ※さらに受注履歴編集をしてもテキスト入力欄が消えないようにするために以下の作業を追加
    function lfRegistData($order_id) {

    変更前

            $arrDetail = $this->objFormParam->getSwapArray(array("product_id", "product_code", "product_name", "price", "quantity", "point_rate", "classcategory_id1", "classcategory_id2", "classcategory_name1", "classcategory_name2"));

    変更後

            $arrDetail = $this->objFormParam->getSwapArray(array("product_id", "product_code", "product_name", "price", "quantity", "point_rate", "classcategory_id1", "classcategory_id2", "classcategory_name1", "classcategory_name2", "add_field"));

    変更前

                        // 数量が変更された商品
                        $arrStockData[$k]['product_id'] = $arrDetail[$i]['product_id'];
                        $arrStockData[$k]['classcategory_id1'] = $arrDetail[$i]['classcategory_id1'];
                        $arrStockData[$k]['classcategory_id2'] = $arrDetail[$i]['classcategory_id2'];

    変更後

                        // 数量が変更された商品
                        $arrStockData[$k]['product_id'] = $arrDetail[$i]['product_id'];
                        $arrStockData[$k]['classcategory_id1'] = $arrDetail[$i]['classcategory_id1'];
                        $arrStockData[$k]['classcategory_id2'] = $arrDetail[$i]['classcategory_id2'];
                        $arrStockData[$k]['add_field'] = $arrDetail[$i]['add_field'];

    変更前

                        // 新しく追加された商品 もしくは 違う商品に変更された商品
                        $arrStockData[$k]['product_id'] = $arrDetail[$i]['product_id'];
                        $arrStockData[$k]['classcategory_id1'] = $arrDetail[$i]['classcategory_id1'];
                        $arrStockData[$k]['classcategory_id2'] = $arrDetail[$i]['classcategory_id2'];

    変更後

                        // 新しく追加された商品 もしくは 違う商品に変更された商品
                        $arrStockData[$k]['product_id'] = $arrDetail[$i]['product_id'];
                        $arrStockData[$k]['classcategory_id1'] = $arrDetail[$i]['classcategory_id1'];
                        $arrStockData[$k]['classcategory_id2'] = $arrDetail[$i]['classcategory_id2'];
                        $arrStockData[$k]['add_field'] = $arrDetail[$i]['add_field'];

    変更前

            foreach ($arrPreDetail AS $key=>$val) {
                $arrStockData[$k]['product_id'] = $val['product_id'];
                $arrStockData[$k]['classcategory_id1'] = $val['classcategory_id1'];
                $arrStockData[$k]['classcategory_id2'] = $val['classcategory_id2'];

    変更後

            foreach ($arrPreDetail AS $key=>$val) {
                $arrStockData[$k]['product_id'] = $val['product_id'];
                $arrStockData[$k]['classcategory_id1'] = $val['classcategory_id1'];
                $arrStockData[$k]['classcategory_id2'] = $val['classcategory_id2'];
                $arrStockData[$k]['add_field'] = $val['add_field'];

    変更前

                $sqlval['classcategory_name2'] = $arrDetail[$i]['classcategory_name2'];
                $objQuery->insert("dtb_order_detail", $sqlval);

    変更後

                $sqlval['classcategory_name2'] = $arrDetail[$i]['classcategory_name2'];
                $sqlval['add_field'] = $arrDetail[$i]['add_field'];
                $objQuery->insert("dtb_order_detail", $sqlval);

    ※新規受注入力に対応するには(作業中)
    [eccube]/data/class/pages/admin/order/LC_Page_Admin_Order_Edit.php
    [eccube]/data/class/pages/admin/order/LC_Page_Admin_Order_ProductSelect.php
    [eccube]/data/Smarty/templates/default/admin/order/product_select.tpl

    あたりを編集する必要がありそう。
    ※携帯向けの対応


    追加カスタマイズ

    帳票出力

    [eccube]/data/class/SC_Fpdf.php
    function setOrderData() {

    変更前

              }
              $arrOrder[$i][1]  = number_format($data[0]);
              $arrOrder[$i][2]  = number_format($data[1]).$monetary_unit;

    変更後

              }
              if($this->arrDisp['add_field'][$i]){
                  $arrOrder[$i][0] .= $this->sjis_conv("\nテキスト入力欄: " . $this->arrDisp['add_field'][$i]);
              }
    
              $arrOrder[$i][1]  = number_format($data[0]);
              $arrOrder[$i][2]  = number_format($data[1]).$monetary_unit;

    function lfGetOrderDetail($order_id) {

    変更前

          $col = "product_id, classcategory_id1, classcategory_id2, product_code, product_name, classcategory_name1, classcategory_name2, price, quantity, point_rate";

    変更後

          $col = "product_id, classcategory_id1, classcategory_id2, product_code, product_name, classcategory_name1, classcategory_name2, price, quantity, point_rate, add_field";