(佐賀→熊本)マークアップエンジニアのググる生活

地方のWEB制作会社で働く、フロントエンドエンジニア。
HTML、CSS、JavaScript(jQuery)、PHP、Smary、EC-CUBE、WordPress、Movable Type等々で解らない時に、Googleで検索したら解決した話や、「閃いた!」などをほとんど自分用にメモとして残すブログです。

※URLがあったら元記事を参照推奨です!
※ほとんどの事は検証はしていますが、あくまでも参考程度にお願い致します!
※記載が不正確であったことにより生じたいかなる損害に関しても、当ブログは責任を負いかねます。自己責任でよろしくおねがいいたします。

カテゴリ: EC-CUBE

EC-CUBE 4系 が発表されましたね!
マスターアップは 10月とのことで、私もさっそくデモを試してみました。

3系からかなり進化していて、すごく乗り換えたいです...。
なかでも管理画面は見やすく、使いやすくなっており、
4系を操作したあと、3系を操作するとすごくイライラします(笑)

ということで、少しでも 3系を快適に使いたく、
管理画面をカスタマイズしてみたので紹介します。


確認は 3.0.16 で行っています。


サイドナビのCSSを改善

3系のデフォルト、見辛いですよね。
4系だとそれを反省して(?)、綺麗になっています。

なので、3系でも真似をして綺麗にしてみました。

eccube3admin_css

変更点は、
・子ナビのボーダーを取り、
・どの親の配下であるかわかりやすくするために背景色を白へ、
・開いてる親の文字色とウェイトを変更しわかりやすく、
・さらに現在アクティブであるナビを強調しました。

CSSはこんな感じに。

<style>
    #side > .nav li {
        transition: background-color .3s;
    }
    #side > .nav li a {
        transition: color .3s, font-weight .3s;
    }
    #side > .nav li a .cb {
        transition: color .3s;
    }
    #side > .nav li.active > a {
        color: #3F5467;
        font-weight: 700;
    }
    #side > .nav li.active > a .cb {
        color: inherit;
    }

    #side > .nav > li:not(:nth-child(6)):not(:nth-child(7)).active {
        background-color: #fff;
    }
    #side > .nav > li:not(:nth-child(6)):not(:nth-child(7)) > ul > li.active > a,
    #side > .nav > li:not(:nth-child(6)):not(:nth-child(7)) > ul > li.active > a:hover  {
        background-color: #3F5467 !important;
        color: #fff;
    }
    #side > .nav > li:not(:nth-child(6)):not(:nth-child(7)) > ul > li {
        border: none;
    }

    #side > .nav > li.active li.active {
        background-color: #fff;
    }
    #side > .nav > li > ul > li.active li.active > a,
    #side > .nav > li > ul > li.active li.active > a:hover  {
        background-color: #3F5467 !important;
        color: #fff;
    }
    #side > .nav > li > ul > li > ul {
        background-color: transparent !important;
    }
    #side > .nav > li > ul > li > ul > li {
        border: none;
    }
    #side > .nav > li > ul > li > ul > li > a:not(:hover) {
        background-color: transparent !important;
        opacity: 1;
    }
</style>

:not(:nth-child(6)) と :not(:nth-child(7)) は、
ナビゲーションの増減によって値が変わるのが注意です。
デフォルトの内容だとそのままで大丈夫です

上のCSSを dashboard.css の一番下に追記するか、
管理画面の default_frame.twig の <//head> 直前に書くとよいかと思います。


商品登録画面のアコーディオンをすべて開かせておく

個人的にどうして表示・非表示のアコーディオンになっているのかわからないのですが、
商品カテゴリやタグ、詳細な設定、フリーエリアなどなどがアコーディオンになっていて開閉できます。
基本的にページを表示したときはそれが閉じており、編集する場合はワンクリックが必要です。
商品が数個程度なら問題ないですが、数が増えてくるとドンドン煩わしくなってきます;;

そこで、編集ページを表示したときに全部開いている状態にしてみました。

<script>
  $(function() {
      // 最初から開ける
      $('#detail_wrap .toggle').click();
  });
</script>

この jQuery を管理画面の product.twig の {% endblock javascript %} 直前に追記します。


商品マスター、受注マスター、会員マスターの初期表示

2系でも同じ悩みがありましたが、商品・受注・会員のマスターの初期表示は、
最小限のフォーム欄と検索ボタンのみです。
一覧を表示させるには検索ボタンを押さなければなりません。
これも最初の数回は良くても、だんだんと面倒になってくる作業の一つです...。

4系では、これを不便に思っていたのか改善されておりましたが、
3系でも依然としてこの問題が残っていました。

3系でも検索ボタンを押さずに一覧を表示させたい!ということで、
PHP にちょっと追記してあげると解決できました。
当初は4系を参考にカスタマイズしようと試みましたが、ググってしてみると、
フォーラムに解決案がありました! → https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=18643&forum=10

追記するコードはたったこれだけ、
if (!$page_no) {
    $page_no = 1;
}

ファイルと場所は、
・CustomerController.php
・OrderController.php
・ProductController.php
の if (is_null($page_no) && $request->get('resume') != Constant::ENABLED) { の直前になります。

これでマスターのページを開いたときに一覧が表示されます!
ただ修正後、F5更新だとうまく行かなかったので、
一度だけ検索ボタンを押す必要があるみたいで、そこだけ注意が必要です。

以前 2.13系の記事を書きましたが、
今回はその 3系バージョンになります。

ググったところ、情報がなかったので・・・
手探りながらやってみました。

試したバージョンは 3.0.16 になります。

※データそのものが初期化されるので、
 運用中には絶対に実行しないでくださいm(_ _)m
 ※また自己責任でお願いいたします。



商品を初期化

TRUNCATE TABLE `dtb_product`;
ALTER TABLE `dtb_product` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_category`;
ALTER TABLE `dtb_product_category` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_class`;
ALTER TABLE `dtb_product_class` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_image`;
ALTER TABLE `dtb_product_image` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_stock`;
ALTER TABLE `dtb_product_stock` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_tag`;
ALTER TABLE `dtb_product_tag` AUTO_INCREMENT = 1;



カテゴリーを初期化

TRUNCATE TABLE `dtb_category`;
ALTER TABLE `dtb_category` AUTO_INCREMENT = 1;



規格を初期化

TRUNCATE TABLE `dtb_class_category`;
ALTER TABLE `dtb_class_category` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_class_name`;
ALTER TABLE `dtb_class_name` AUTO_INCREMENT = 1;



PhpMyAdminの場合?

詳しくないので解説できませんが、データにロックがかかっているために、
上のSQLだけでは実行できませんでした。
SET FOREIGN_KEY_CHECKS=0;
というのを先頭に添える必要があります。


まとめると...

SET FOREIGN_KEY_CHECKS=0;

TRUNCATE TABLE `dtb_product`;
ALTER TABLE `dtb_product` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_category`;
ALTER TABLE `dtb_product_category` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_class`;
ALTER TABLE `dtb_product_class` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_image`;
ALTER TABLE `dtb_product_image` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_stock`;
ALTER TABLE `dtb_product_stock` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_product_tag`;
ALTER TABLE `dtb_product_tag` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_class_category`;
ALTER TABLE `dtb_class_category` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_class_name`;
ALTER TABLE `dtb_class_name` AUTO_INCREMENT = 1;

TRUNCATE TABLE `dtb_category`;
ALTER TABLE `dtb_category` AUTO_INCREMENT = 1;
これを3系をインストール後に行うと、商品やカテゴリー・規格のが初期化され、
IDを1から始めることができました!


※データそのものが初期化されるので、
 運用中には絶対に実行しないでくださいm(_ _)m
 ※また自己責任でお願いいたします。

EC-CUBE 3.0.16 でカスタマイズしています。
受注CSVに利用ポイントと加算ポイントを追加しました。

カスタマイズ方法としては、
1. dtb_csv に利用ポイントと加算ポイントを挿入
2. プログラムに処理を追加
です。
3系になってからは、標準項目の追加なら、DBに値を追加するだけで出力してくれるので非常に便利でした。

ただプラグインの場合はそのプラグインがCSVの処理を入れてない場合 1. だけでは出力できないので、
プログラム側にカスタマイズが必要でした。
そこで今回は苦戦しました。またあまり正しくない方法で取り急ぎの対応…になります。


ググってみると、
https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=18139&forum=13
https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=19444&forum=11
https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=19318&forum=11
https://github.com/EC-CUBE/ec-cube/pull/1944
などなど、参考になりそうなトピックスがありました。


まずは、1. dtb_csv に利用ポイントと加算ポイントを挿入を実行。
SQLでサクッと行います。
INSERT INTO `dtb_csv` (`csv_id`, `csv_type`, `creator_id`, `entity_name`, `field_name`, `reference_field_name`, `disp_name`, `rank`, `enable_flg`, `create_date`, `update_date`) VALUES (NULL, '3', '1', 'Plugin\Point\Entity\Point', 'point', 'use', '利用ポイント', '', '1', '', '');
INSERT INTO `dtb_csv` (`csv_id`, `csv_type`, `creator_id`, `entity_name`, `field_name`, `reference_field_name`, `disp_name`, `rank`, `enable_flg`, `create_date`, `update_date`) VALUES (NULL, '3', '1', 'Plugin\Point\Entity\Point', 'point', 'add', '加算ポイント', '', '1', '', '');
`entity_name` は恐らく 'Plugin\Point\Entity\Point' であっていると思いますが、
`field_name` と `reference_field_name` とはダミーになります。
↑は、'Plugin\Point\Entity\Point' で定義されているファイルの中の変数を入れると思いますが、
適切なものが見当たりませんでしたので…
この辺アドバイスされたい…(>_<)


次に、2. プログラムに処理を追加
本来は新たに処理用のプラグインを作るようですが、今回は取り急ぎのため本体コードを編集します。
/src/Eccube/Controller/Admin/Order/OrderController.php が、
管理画面の受注画面をコントロールしているファイルになります。
exportOrder関数の中の、だいたい260行目に
$event = new EventArgs(
とあるので、その上に下記を追記します。
/src/Eccube/Controller/Admin/Order/OrderController.php$Customer = $Order->getCustomer();
// 会員のみ処理
if ($Customer) {
    if ($Csv->getDispName() === '利用ポイント') {
        // 利用ポイント取得
        $usePoint = $app['eccube.plugin.point.repository.point']->getLatestUsePoint($Order);
        $usePoint = abs($usePoint);
        $ExportCsvRow->setData($usePoint);
    }
    if ($Csv->getDispName() === '加算ポイント') {
        // 加算ポイント取得
        $addPoint = $app['eccube.plugin.point.repository.point']->getLatestAddPointByOrder($Order);
        $ExportCsvRow->setData($addPoint);
    }
} else {
    if ($Csv->getDispName() === '利用ポイント') {
        // $ExportCsvRow->setData(0);
    }
    if ($Csv->getDispName() === '加算ポイント') {
        // $ExportCsvRow->setData(0);
    }
}
まず会員であるかをチェックして、非会員の場合は空欄(場合によっては0を出力してもよいかも)にしています。
非会員でも加算ポイントを取得しようとするとエラーが出るので会員チェックは重要です。

次に 'eccube.plugin.point.repository.point' でポイントのリポジトリにアクセスできるので、
用意されている関数に $Order を渡すと利用ポイント取得、加算ポイント取得が取得できます。
取得できたポイントを $Csv->getDispName() が '利用ポイント' と '加算ポイント' との時に、
CSVにセットする、という感じになっています。


配送CSVも同じ作業でできました。

以上ですが、冒頭にも言いましたがこれは良い方法でないので、
参考程度が良いかと思います。

それにしてもSymfonyとSilexを勉強しないとついていけませんね...。

今回は 3.0.16 で確認しています。

{{ Product.getPrice02IncTaxMin|price }}
{{ Product.getPrice02IncTaxMax|price }}
などなど、twig や smarty などには便利な装飾子がありますが、

EC-CUBE3 の場合、 |price というのを独自に追加しているので、
それを付けるだけで、 number_format された値と、¥マークが付与された金額を表示することができます。

そこで半角なのを全角にしてみたいと思い、ソースコードを追ってみたところ、
まとめて管理してあるファイルを見つけたので下記のように編集するとうまくいきました。

// /src/Eccube/Twig/Extension/EccubeExtension.php

/**
 * Name of this extension
 *
 * @return string
 */
public function getPriceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',')
{
    $price = number_format($number, $decimals, $decPoint, $thousandsSep);

    // [カスタマイズ] \マークを全角に
    // $price = '¥ '.$price;
    $price = '¥'.$price;

    return $price;
}

サーチコンソールからの通知で、今更ながら初めて気が付きました。
EC-CUBE が標準提供している sitemap.php に相応しくない URL が含まれているなんて...。
今回は 2.13.4 と 2.13.5 のカスタマイズになります。

http://net-info-square.com/2015/08/22/post-60/
基本のやり方はググってみるとサクッと見つかりました。
ただしこちらは shopping だけだったので、ちょっと追記してみました。


// /data/class_extends/page_extends/LC_Page_Sitemap_Ex.php

/**
 * ブロック情報を取得する.
 *
 * @param  string $where  WHERE句
 * @param  array  $arrVal WHERE句の値を格納した配列
 * @return array  $arrPageList ブロック情報
 */
public function getPageData($where = '', $arrVal = '')
{
    $objQuery = SC_Query_Ex::getSingletonInstance();     // DB操作オブジェクト
    $sql = '';                      // データ取得SQL生成用
    $arrPageList = array();              // データ取得用

    // SQL生成(url と update_date 以外は不要?)
    $sql .= ' SELECT';
    $sql .= ' page_id';             // ページID
    $sql .= ' ,page_name';          // 名称
    $sql .= ' ,url';                // URL
    $sql .= ' ,filename';           // ファイル名称
    $sql .= ' ,header_chk ';        // ヘッダー使用FLG
    $sql .= ' ,footer_chk ';        // フッター使用FLG
    $sql .= ' ,author';             // authorタグ
    $sql .= ' ,description';        // descriptionタグ
    $sql .= ' ,keyword';            // keywordタグ
    $sql .= ' ,update_url';         // 更新URL
    $sql .= ' ,create_date';        // データ作成日
    $sql .= ' ,update_date';        // データ更新日
    $sql .= ' FROM ';
    $sql .= '     dtb_pagelayout';

    // where句の指定があれば追加
    if ($where != '') {
        // [カスタマイズ] http://net-info-square.com/2015/08/22/post-60/
        // [原案] $sql .= ' WHERE ' . $where;
        $sql .= ' WHERE NOT url LIKE \'%shopping%\' and NOT url LIKE \'%entry%\' and NOT url LIKE \'%regist%\' and NOT url LIKE \'%mypage%\' and NOT url LIKE \'%cart%\' and NOT url LIKE \'%complete\.php%\' and ' . $where;
    }

    $sql .= ' ORDER BY page_id';

    $arrPageList = $objQuery->getAll($sql, $arrVal);

    // URL にプロトコルの記載が無い場合、HTTP_URL を前置する。
    foreach ($arrPageList as $key => $value) {
        $arrPage =& $arrPageList[$key];
        if (!preg_match('|^https?://|i', $arrPage['url'])) {
            $arrPage['url'] = HTTP_URL . $arrPage['url'];
        }
        $arrPage['url'] = preg_replace('|/' . preg_quote(DIR_INDEX_FILE) . '$|', '/' . DIR_INDEX_PATH, $arrPage['url']);
    }
    unset($arrPage);

    return $arrPageList;
}

/data/class/pages/LC_Page_Sitemap.php ファイルに getPageData という関数があるので丸ごとコピーし、
/data/class_extends/page_extends/LC_Page_Sitemap_Ex.php にペースト。

$sql .= ' WHERE ' . $where;
のところに SQL を追記すると良いという具合です。
上記では、
/shopping/ 購入処理
/entry/ 会員登録
/regist/ 会員登録関連
/mypage/ マイページ
/cart/ カート
*/complete.php なんらかの完了ページ
を除外するようにしています。

これでサーチコンソールに怒られないかな?

EC-CUBE2 のままでは、PHP7 の恩恵を受けれないことから…、
ついに EC-CUBE3 を実務で使うことにしました。

プログラムがまったくもって新しくなっているので、
インストールの時点で数多くググることに...(>_<)

時間はかかりましたが、なんとかインストールしつつ、/html/ フォルダを URL から消したり、
テンプレートをカスタマイズできるようになりました。

そこで「レイアウト管理」にてブロックを設置できる場所を増やせないかと
ソースを追って、ちょっと追加してみたところ結構簡単に実装できたので、
メモしておきます!

バージョンは、EC-CUBE 3.0.15 になります。

#contents_top と #header の間に場所を設けたかったので、
#contents_over というのを作ることにしました。

まずは、PHP プログラムからです。

// /src/Eccube/Entity/PageLayout.php

// 配置ID
/** 配置ID: 未使用 */
const TARGET_ID_UNUSED = 0;
const TARGET_ID_HEAD = 1;
const TARGET_ID_HEADER = 2;
const TARGET_ID_CONTENTS_TOP = 3;
const TARGET_ID_SIDE_LEFT = 4;
const TARGET_ID_MAIN_TOP = 5;
const TARGET_ID_MAIN_BOTTOM = 6;
const TARGET_ID_SIDE_RIGHT = 7;
const TARGET_ID_CONTENTS_BOTTOM = 8;
const TARGET_ID_FOOTER = 9;
const TARGET_ID_CONTENTS_OVER = 10; // [カスタマイズ] レイアウト追加

まず、配置IDを追加します。
/src/Eccube/Entity/PageLayout.php の先頭に配置IDの定義があります。
0~9はすでに使用済みなので、10を追加しました。

// /src/Eccube/Entity/PageLayout.php

public function getFooterPosition()
{
    return $this->getBlocksPositionByTargetId(self::TARGET_ID_FOOTER);
}

// [カスタマイズ] レイアウト追加
public function getContentsOverPosition()
{
    return $this->getBlocksPositionByTargetId(self::TARGET_ID_CONTENTS_OVER);
}

同じく /src/Eccube/Entity/PageLayout.php の116行目ぐらいにて
ポジションを取得できる関数を用意する必要があるようですので、
フッターを参考に追加してみます。

// /src/Eccube/Entity/PageLayout.php

public function getFooter()
{
    return $this->getBlocksByTargetId(self::TARGET_ID_FOOTER);
}

// [カスタマイズ] レイアウト追加
public function getContentsOver()
{
    return $this->getBlocksByTargetId(self::TARGET_ID_CONTENTS_OVER);
}

同じく /src/Eccube/Entity/PageLayout.php の190行目ぐらいにて
IDを取得できる関数を用意する必要があるようですので、
こちらもフッターを参考に追加してみます。

PHP 側は以上です。

次は、管理画面のHTMLを追記します。

// /src/Eccube/Resource/template/admin/Content/layout.twig

{# [カスタマイズ] レイアウト追加 #}
<tr>
    <td id="position_{{ constant('Eccube\\Entity\\PageLayout::TARGET_ID_CONTENTS_OVER') }}" class="ui-sortable" colspan="3">
        {% for BlockPosition in TargetPageLayout.ContentsOverPosition %}
            <div id="detail_box__layout_item--{{ BlockPosition.Block.id }}" class="sort{% if loop.first %} first{% endif %}">
                <input type="hidden" class="name" name="name_{{ loop_index }}" value="{{ BlockPosition.Block.name}}" />
                <input type="hidden" class="id" name="id_{{ loop_index }}" value="{{ BlockPosition.Block.id }}" />
                <input type="hidden" class="target-id" name="target_id_{{ loop_index }}" value="{{ BlockPosition.target_id }}" />
                <input type="hidden" class="top" name="top_{{ loop_index }}" value="{{ BlockPosition.block_row }}" />
                {{ BlockPosition.Block.name }}
                <label class="anywherecheck">
                    (<input type="checkbox" class="anywhere" name="anywhere_{{ loop_index }}" value="1" {% if BlockPosition.anywhere == 1 %} checked="checked"{% endif %} />全ページ)
                </label>
            </div>
            {% set loop_index = loop_index + 1 %}
        {% endfor %}
    </td>
</tr>

/src/Eccube/Resource/template/admin/Content/layout.twig が管理画面のレイアウト管理のファイルです。
123行目ぐらいに TARGET_ID_CONTENTS_TOP 用の があるので、その をまるごと複製してから、
・TARGET_ID_CONTENTS_TOP を TARGET_ID_CONTENTS_OVER へ
・ContentsTopPosition を ContentsOverPosition へ
置き換えます。HTML は以上です。

次は、管理画面の JavaScript を追記します。

// /html/template/admin/assets/js/layout_design.js

{# [カスタマイズ] レイアウト追加 #}
$(document).ready(function(){
    var els = [
        '#position_0',
        '#position_1',
        '#position_2',
        '#position_3',
        '#position_4',
        '#position_5',
        '#position_6',
        '#position_7',
        '#position_8',
        '#position_9',
        '#position_10' // [カスタマイズ] レイアウト追加
    ];

/html/template/admin/assets/js/layout_design.js 40行目ぐらいに、
ID を配列で指定している箇所があるので、必要なIDを追記します。JavaScript は以上です。

最後に、管理画面の Css を追記します。

// /html/template/admin/assets/css/dashboard.css

/* [カスタマイズ] レイアウト追加 */
.design-layout td#position_10:before {content: "#contents_over"}

/html/template/admin/assets/css/dashboard.css 2899行目ぐらいに、
疑似要素の content に ID名を記述している箇所があるので追記します。

以上で完了です!

データベースの変更なしでこういった作業ができるようになっているので、
すごく進化しているな~!と感じることができるカスタマイズでした。

ただ管理画面はちょっと見ずらいと思うので、カスタマイズをどんどんやっていきたいですね。

EC-CUBEの3系が浸透してきてからは2系が、
各種レンタルサーバーのクイックインストールから
案内が消えていますが…
まだまだ弊社ではEC-CUBEの2系が現役で、
インストールしたり保守したりしています。

そこで最近の新しいサーバに2系をインストールしようとしたところ、
画面が真っ白に…ということがありました。
弊社ではXserverを利用しておりますので、その前提で…。

これは原因は三つあって(場合によっては二つかも)
・Xserverでは標準でPHPのバージョンが7を採用してる
・接続するMySqlのバージョンが不釣り合い
・EC-CUBEに入っている.htaccessが邪魔をしている
というのが上手くいかない原因です。



・Xserverでは標準でPHPのバージョンが7を採用してる

これは結構簡単なことですが、ヒントが少ないのでハマりポイントのひとつです。
EC-CUBEの2系はPHP5.6までしか対応できていないので、
PHP7だと完全に動きません。
https://www.ec-cube.net/news/detail.php?news_id=290
↑のように、PHP7に対応したバージョンもリリースされているようですが、
アルファーバージョン(テスト段階)ですので、
実際にクライアントワークではあまり使えないと判断しています。
なので、サーバのPHPのバージョンを7から5.6まで下げざるを得ません。
レンタルサーバだったらコントロールパネルからすぐに設定が見つかると思います。



・接続するMySqlのバージョンが不釣り合い
難しいことはわかりませんが、データーベースへ接続する際に、
バージョンによってプログラムが少し違うようです。
https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=16981&forum=2
↑の投稿のように、本体プログラムにすこし手を加えてあげないといけません。

// /data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php
// または
// /data/class_extends/db_extends/dbfactory/SC_DB_DBFactory_MYSQL_Ex.php

/**
 * 各 DB に応じた SC_Query での初期化を行う
 *
 * @param  SC_Query $objQuery SC_Query インスタンス
 * @return void
 */
public function initObjQuery(SC_Query &$objQuery)
{
    // [追記] MySqlのバージョンによって処理を分岐
    $val = $objQuery->getOne('select version()');
    if (strcmp($val,'5.7.5')) {
      $objQuery->exec('SET SESSION default_storage_engine = InnoDB');
    } else {
      $objQuery->exec('SET SESSION storage_enging = InnoDB');
    }
    
    $objQuery->exec("SET SESSION sql_mode = 'ANSI'");
}



・EC-CUBEに入っている.htaccessが邪魔をしている
サーバによると思いますが、EC-CUBEのファイルの中に標準で入っている
html/.htaccessが動作を邪魔している可能性があります。
そういうときは思い切ってそのファイルを削除すると上手くいきます。
そもそも念のために...という感じで入っているのでほとんどの場合問題が無いはずです。
またhtmlフォルダ直下以外の.htaccessは削除されない方がよいです。



間が空くと忘れてしまうので、これで忘れないはず…。

今回も2系の話になります。

EC-CUBEはSmartyというテンプレートエンジンを使用しています。
基本的にはurlなどの見た目通りの場所にtplが存在しているので、
作業の前にどこの階層のどのフォルダにあるな、ということが容易に想像することができます。

しかし、プラグイン等ではその当てがたまに外れることがあります。
特にファイルをいくつか複製する処理が入るタイプのものは、
同じ内容のtplファイルが3つぐらいサーバー上に生成される場合も…。

そのため、
編集したのに反映されない!
→そこのファイルじゃないよ…。
キャッシュファイルの影響かな?
→templates_c内のtpl.phpを削除しても微動だにせず。
という作業を繰り返す羽目になったり。

1つだけならどこを編集したらよいか、
すぐにわかりますが、複数だと非常に混乱します…。

そんなときに、どのファイルを編集するとよいかは、
templates_c内のtpl.phpファイルを見てみると本来のファイルパスが一目でわかります!

templates_c内のtpl.phpファイルをエディタで開くと、
phpのコメントで2行目に「compiled from」と書かれています。
~からコンパイル…とのことで、その横にファイルパスが書かれています。
つまりそのファイルパスのtplを元にしてtpl.phpを作ってますよといことです。

ということでそのファイルパスを辿って、編集するべきtplを簡単に特定することが可能になります!

これでもう迷わない…はず…。

ぐぐって出てくる情報でも基本的にはなるが…
・ログイン時に真っ白の画面にエラーコードだけになったり
・プラグインによっては参照してくれなかったり
などなど、よろしくないことになるので、自分用にまとめです。

2.13.5 で基本的に確認してますが、
2.13.x 系ならたぶんいいはず…。


■管理画面
[システム設定>パラメーター設定]
・TEMPLATE_NAME テンプレート名
・SMARTPHONE_TEMPLATE_NAME スマートフォンテンプレート名

これらの値を同一にする。
デフォルトの場合は"default"になり、
オリジナルの場合は"オリジナルのテンプレートコード"の名前になる。

これだけでもEC-CUBE標準で備わっているページは対応できるが、
追加したページの場合はスマートフォンでメインエリアが読み込まれなくなるので、
下記のコードが必要になる。


■SC_Display_Ex.php

/**
 * 端末種別を判別する。
 *
 * SC_Display::MOBILE = ガラケー = 1
 * SC_Display::SMARTPHONE = スマホ = 2
 * SC_Display::PC = PC = 10
 *
 * @static
 * @param          $reset boolean
 * @return integer 端末種別ID
 */
public static function detectDevice($reset = FALSE)
{
    return DEVICE_TYPE_PC;
}

extendsではない方では、ifで分岐してあるが、
必要ないのでストレートに PC のみを返却するように変更する。


これで大丈夫なはず・・・。

検索してもテキストかテキストエリアの拡張のみしか見当たらないあたり、
あまり需要がないのでしょうか…?

PDFを商品ごとにアップする必要がある案件を担当するにあたり、
右往左往しましたが、
ほとんど画像のアップロードを増やす要領で実現できたので、
メモします!

まずは、文字列(PDFファイル名)を保存する為の枠を作ります。
商品ページへの基本的な項目の追加は下記の記事がとてもわかり易いです。
[EC-CUBE] 2.13 商品詳細ページの項目追加(MySQL)
http://digipoke.com/archives/1668


・625行目辺り「商品詳細の SQL を取得する」に追加
までは上記の手順でちゃちゃっと済ませておきます。

追加の項目名が不明だと分かりづらいので、
以降は manual と表現します。

次に、商品登録ページに入力欄を設置しますが、
ここはテキストではなく、input[type="file"] 形式にします。
一覧-メイン画像の tr を複製し利用します。

<tr>
    <!--{assign var=key value="main_list_image"}-->
    <th>一覧-メイン画像<br />[<!--{$smarty.const.SMALL_IMAGE_WIDTH}-->×<!--{$smarty.const.SMALL_IMAGE_HEIGHT}-->]</th>
    <td>
        <a name="<!--{$key}-->"></a>
        <a name="main_image"></a> // ←ここは削除
        <a name="main_large_image"></a> // ←ここは削除
        <span class="attention"><!--{$arrErr[$key]}--></span>
        <!--{if $arrForm.arrFile[$key].filepath != ""}-->
        <img src="<!--{$arrForm.arrFile[$key].filepath}-->" alt="<!--{$arrForm.name|h}-->" /> <a href="" onclick="selectAll('category_id'); eccube.setModeAndSubmit('delete_image', 'image_key', '<!--{$key}-->'); return false;">[画像の取り消し]</a><br />
        <!--{/if}-->
        <input type="file" name="main_list_image" size="40" style="<!--{$arrErr[$key]|sfGetErrorColor}-->" />
        <a class="btn-normal" href="javascript:;" name="btn" onclick="selectAll('category_id'); eccube.setModeAndSubmit('upload_image', 'image_key', '<!--{$key}-->'); return false;">アップロード</a>
    </td>
</tr>

上のようなテンプレートの記述です。
・// ←ここは削除 は必要ないので削除。
・th の名前を変更
・名前下の画像の縦x横は .pdf のみなどアップロードできる拡張子を明記しておくと良いともいます。
・main_list_image を manual(先程作った枠の項目名)に置き換え(2箇所)

入力欄はこれで完成です。


次に、商品ページ(LC_Page_Admin_Products_Product.php)の機能を拡張します。
・lfInitFormParam()
・lfInitFile()
の関数にそれぞれ付け加えます。


lfInitFormParam() は、上の記事でも作業を行ったところですね。

// こういうのを追加していた場合
$objFormParam->addParam('取扱説明書', 'manual', STEXT_LEN, 'KVa', array('SPTAB_CHECK', 'MAX_LENGTH_CHECK'));

// 下記2行を追加(データの受け渡し用で使用)
$objFormParam->addParam('temp_manual', 'temp_manual', '', '', array());
$objFormParam->addParam('save_manual', 'save_manual', '', '', array());


lfInitFile() はアップロードファイルパラメーター情報の初期化する関数です。
アップロードファイルをプログラムに送りつける前に事前に枠を置いておくような感覚でしょうか。

$objUpFile->addFile('取扱説明書', 'manual', array('pdf'), IMAGE_SIZE, false, 0, 0, false);


これで、完了です。


実際に、PDFを選択し、アップロードすると、
/upload/temp_image/ フォルダに保存されます。
そのまま商品ページを保存すると、
/upload/save_image/ フォルダに保存されます。

また、データベース上でも確認してみると、
manual(先程作った枠の項目名)のところにPDFファイル名が入力されているはずです。


アップロードの機能は画像の仕組みをそのまま利用できるので、
非常に少ない追記で行うことができました。
途中でサムネイル生成の判定が入りますが、
main_image 系のみ反応するようなので、特に作業の必要がなく回避できるのはありがたかったです。


IMAGE_SIZE はシステム設定>パラメーター設定にあります。
初期値が 1MB だと思います。普通に足りないと思うので、
10MB ぐらいにしておくと、無難かと思われます。
また PDF だけ 10MB にしたい場合は、
引数の IMAGE_SIZE を 10000 にするとOKです。


確認や実際の表示は Aタグで開くようにしてあげると良いでしょう。





2017/11/24 追記
特に不具合は無かったのですが、
商品を複製する際に、「イメージの形式が不明です。」とエラーが出て処理が止まるようになってしまいました。
アップロード時のサムネイル生成は key 名で判定が入るので、カスタマイズ不要でしたが、
複製の際は別途機能を使うみたいなので、次のように追記する必要がありました。

/data/module/gdthumb.php

/*
* サムネイル画像の作成
* string $path
* integer $width
* integer $height
*/
function Main($path, $width, $height, $dst_file, $header = false) {
  // 追記
  if(strpos($path, '.pdf') !== false || strpos($path, '.PDF') !== false) {
    return array(1, false);
  }

  ~元々の処理~
}


このページのトップヘ