EC-CUBE2.4、2.11、2.13からEC-CUBE3.0.1xへのデータ移行ツール公開
EC-CUBE Advent Calendar 2017 15日目の記事です。
15日目はEC-CUBE2系からEC-CUBE3.0.1x系へ移行するためのツールを公開します。このツールはエンジニアの方を対象にしています。
元々は、1つのツールで2.4、2.11、2.13の対応をしようと思っていましたが、意外とめんどくさいことが判明しましたのでそれぞれのバージョンにあったものをお使いください。
プログラムの説明
既存DBから情報を読み取り、3系のデータ構造に合わせてinsert文を作成するというものです。
移行対象テーブルは商品、受注、会員に関連するもののみとなりますのでそれ以外のテーブルは別途作成してみてください。
読み出し元DBはMySQL、PostgreSQL両方対応していますが、作成されるinsert文はMySQL専用となっていますので、PostgreSQLが必要な方はカスタマイズしてお使いください。
PHP5.3から動きます。
また、移行先がレンタルサーバ等の場合、一度に大量のデータを流すとエラーになるレンタルサーバもあります。そのため、受注データ関連のみのinsert文のみですがファイルを分割して作成するようにしています。商品データ等も同じように修正すれば対応可能です。
忘れてはいけないこと
2系から3系に移行した後、必ずAUTH_MAGICは2系で使用されていたものをお使いください。これがないと会員、管理者ともにログインできなくなります。
- AUTH_MAGICのそれぞれの場所
これらを3系の
app/config/eccube/config.yml
にあるauth_magicに設定してください。
以下、利用する前に以下の注意点を必ずお読みください。
※注意点
- カスタマイズされているデータベースには対応していません。ソースを見ればわかるように簡単なコードですので、適宜カスタマイズしてお使いください。
- こちらは必ず動作保証されているものではありません。また、データ構成によっては全て移行されない時がありますので、必ず検証をお願いします。
- こちらの移行ツールを使ったあとは必ずテストをしてください。
- マスタ系(mtb_xxx)は移行していませんが、必要であれば同じように作成すれば対応可能です。
- 3系から新たに用意されたカラムに対しての考慮まではしていません。
- プラグインとして提供されるようになったテーブルは対象外としています。
→2.11からの移行としてdtb_makerの移行だけサンプルとして用意しています。
なお、使用するEC-CUBE3ですが、本日時点のソースをcloneしたものを使います。 https://github.com/EC-CUBE/ec-cube
EC-CUBE2.4系からの移行
EC-CUBE2.4は3系とデータ構造は似ていますが、足りていない項目などがありますがそこは無視しています。
商品タグについては作成されたsql文に対して一部手動で変更する必要があります。
EC-CUBE2.11系からの移行
EC-CUBE2.11は商品規格のデータ構造が異なります。3系に変換時はそれぞれのテーブルを結合して対応していますが、もしかしたら漏れがあるかもしれません。
それ以外は2.4からの移行とほぼ同じです。商品タグについては作成されたsql文に対して一部手動で変更する必要があります。
EC-CUBE2.13系からの移行
3系はEC-CUBE2.13のデータ構造をベースとして作成されていますので、ほぼ同じです。ただし、複数配送時などの配送データが一部手直しする必要があります。
メルマガプラグインを利用している方も多いと思いますので、メルマガプラグインへの移行データも一応入っています。不要な方はその箇所を削除してください。
実行方法
それぞれのリポジトリにconfig.php
が入っていますので、環境に合わせてお使いください。
実行方法は、
./migration.sh
とターミナルから実行すれば使えます。
insert.sh
ファイルは、データをインポートするときにファイル数が多ければお使いください。seq 10
の箇所を作成されたファイル数と合わせるだけです。
以上がツールの注意点となります。基本的には他のテーブルも同じように作成すれば問題ありません。
データによっては潜在的なバグが含まれている可能性がありますので、十分気をつけてください。
本当はPostgreSQL版も用意したかったのですが、私がMySQLを利用することが多いため作成する時間がありませんでした。
不具合があったり、PostgreSQL版を用意したという方がいればpull requestを随時お待ちしております。
EC-CUBE3の商品一覧画面にカートボタンを追加させる方法
EC-CUBE Advent Calendar 2017 4日目の記事です。
4日目はEC-CUBE3の商品一覧画面にカートボタンを追加する内容を書きます。
EC-CUBE2系では商品一覧からカートに追加するボタンが存在していたのですが3系からは無くなっています。
3系からこの機能が無くなったのかというと実はソースを眺めてみると実装されており、少しカスタマイズをするだけで実現可能です。
というわけで3系の商品一覧画面でもカートボタンを表示するカスタマイズを紹介します。
使用するEC-CUBE3ですが、本日時点のソースをcloneしたものを使います。 https://github.com/EC-CUBE/ec-cube
デフォルトだと商品一覧画面は以下のようになります。(商品を一つ追加しています。)
この一覧画面に規格選択およびカートボタンを表示させます。今回デザインは全く気にしていません。
- src/Eccube/Resource/template/default/Product/list.twig
137行目から以下を追加します。
{% if Product.stock_find %} <!--▼買い物かご--> {% set form = forms[Product.id] %} <form name="form{{ Product.id }}" id="productForm{{ Product.id }}" action="{{ url('product_detail', {'id': Product.id}) }}" method="post"> <dl> {% if form.classcategory_id1 is defined %} {# 規格1 #} <dt> {{ form_label(form.classcategory_id1) }}: </dt> <dd> {{ form_widget(form.classcategory_id1) }} {{ form_errors(form.classcategory_id1) }} </dd> {# 規格2 #} {% if form.classcategory_id2 is defined %} <dt> {{ form_label(form.classcategory_id2) }}: </dt> <dd> {{ form_widget(form.classcategory_id2) }} {{ form_errors(form.classcategory_id2) }} </dd> {% endif %} {% endif %} <dt>個数:</dt> <dd> {{ form_widget(form.quantity) }} {{ form_errors(form.quantity) }} </dd> {{ form_rest(form) }} </dl> <div> <button type="submit" class="add-cart btn btn-primary btn-block prevention-btn prevention-mask" data-cartid="{{ Product.id }}">カートに入れる</button> </div> </form> <!--▲買い物かご--> {% else %} <div>ただいま品切れ中です</div> {% endif %}
これだけで規格がある商品は規格の選択、およびカートボタンが表示されるようになりました。
だたし、表示されるだけでカートボタンは正常に動作しません。 動作させるためにはJavaScriptの処理を追加させます。
45行目以降のscriptの中に以下を追加します。
eccube.productsClassCategories = { {% for Product in pagination %} "{{ Product.id|escape('js') }}": {{ Product.class_categories|json_encode|raw }}{% if loop.last == false %}, {% endif %} {% endfor %} }; $('.add-cart').click(function() { var data = $(this).data(); $('input[name="mode"]').val('add_cart'); $('#productForm' + data.cartid).submit() });
これを追加することでパーコレーターの規格1を選択すると、規格2が選択されるようになりました。
$('.add-cart').click(function() { var data = $(this).data(); $('input[name="mode"]').val('add_cart'); $('#productForm' + data.cartid).submit() return false; });
の処理でカートを追加するボタンを押すとカート画面へ遷移するようにしています。 [2018/06/25 追記] 最後にreturn false; を記述してください。
規格が複数あったとしても問題なく動作します。
これで商品一覧画面からカートへ追加する実装が可能となりました。EC-CUBE3では少しカスタマイズするだけで実現させたい機能が簡単に可能です。
動作しない、エラーが発生したという方はコメントしてくれれば確認します。
EC-CUBE3でページ管理から画面作成時にURLからuser_dataを無くす方法
EC-CUBE3にあるページ管理より新しいページを作成した場合、URLには必ずuser_data
が含まれます。
http://hogehoge/user_data/hoge
というようになります。
user_dataは別にあっても問題はありませんが、中には無くしてしまいたいという方もいると思います。以下のカスタマイズを行うことで実現可能となります。
EC-CUBE3.0.14を対象に説明します。
まず、FrontControllerProviderにあるuser_dataを定義しているルーティングの箇所をコメントアウトします。
// user定義 // $c->match('/'.$app['config']['user_data_route'].'/{route}', '\Eccube\Controller\UserDataController::index')->assert('route', '([0-9a-zA-Z_\-]+\/?)+(?<!\/)')->bind('user_data');
ページ作成時にuser_dataの定義がなくても動作するように、PageControllerとPageLayoutRepositoryを修正します。
- src/Eccube/Controller/Admin/Content/PageController.php
・120行目 // ファイル生成・更新 $templatePath = $app['eccube.repository.page_layout']->getWriteTemplatePath($editable); ↓ $templatePath = $app['eccube.repository.page_layout']->getWriteTemplatePath(false); ・156行目 $templatePath = $app['eccube.repository.page_layout']->getWriteTemplatePath($editable); ↓ $templatePath = $app['eccube.repository.page_layout']->getWriteTemplatePath(false); ・187行目 $templatePath = $app['eccube.repository.page_layout']->getWriteTemplatePath(true); ↓ $templatePath = $app['eccube.repository.page_layout']->getWriteTemplatePath(false);
というようにそれぞれ$app['eccube.repository.page_layout']->getWriteTemplatePath(false);
と変更します。
- src/Eccube/Repository/PageLayoutRepository.php
public function getReadTemplateFile($fileName, $isUser = false) { if ($isUser) { $readPaths = array( $this->app['config']['user_data_realdir'], ); } else { $readPaths = array( $this->app['config']['template_realdir'], $this->app['config']['template_default_realdir'], ); } ・ ・ ・
と記述されている箇所を
public function getReadTemplateFile($fileName, $isUser = false) { if ($isUser) { $readPaths = array( $this->app['config']['template_realdir'], $this->app['config']['user_data_realdir'], ); } else { $readPaths = array( $this->app['config']['template_realdir'], $this->app['config']['template_default_realdir'], ); } ・ ・ ・
と$this->app['config']['template_realdir'],
を263行目に追加します。
また、管理画面でのURL表記を変更するため、page_edit.twigも修正します。
- app/template/admin/Content/page_edit.twig
・59行目 {{ url('top') }}{{ app.config.user_data_route }}/{{ form_widget(form.url) }} ↓ {{ url('homepage') }}{{ form_widget(form.url) }}
こちらはuser_dataを表示上からなくしているだけです。
ここまで対応すればほぼ完了なのですが、FrontControllerProviderからuser_dataへルーティング定義を削除してしまったため、新たに定義してあげる必要があります。どこに定義するのかというと、index.phpで定義してあげます。
- html/index.php
// インストールされてなければインストーラにリダイレクト if (isset($app['config']['eccube_install']) && $app['config']['eccube_install']) { $app->initialize(); $app->initializePlugin(); if ($app['config']['http_cache']['enabled']) { $app['http_cache']->run(); } else { $app->run(); } } else { ・ ・ ・
と記載されている箇所を
// インストールされてなければインストーラにリダイレクト if (isset($app['config']['eccube_install']) && $app['config']['eccube_install']) { $app->initialize(); $app->initializePlugin(); // ページレイアウトのカスタマイズに伴う修正 $front = $app['controllers_factory']; // 強制SSL if ($app['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) { $front->requireHttps(); } $front->match('/{route}', '\Eccube\Controller\UserDataController::index')->assert('route', '([0-9a-zA-Z_\-]+\/?)+(?<!\/)')->bind('user_data'); $app->mount('', $front); if ($app['config']['http_cache']['enabled']) { $app['http_cache']->run(); } else { $app->run(); } } else { ・ ・ ・
というように新たにuser_data用のルーティング定義を行います。
以上の作業を行うことで、ページ管理から新たなページを作成した場合、URLにはuser_data
はなくなります。
必要な方には必要なカスタマイズだと思いますので、user_dataをURLから無くしてしまいたい!という方は是非ご利用ください。
EC-CUBE3でログイン成功時に直前まで見ていた画面へ戻る方法
EC-CUBE3ではログインする場合、EC-CUBE2とは違いログイン画面を経由させる必要があります。
また、ログイン成功後は必ずサイトのトップページへ戻ってしまいます。
サイトの作りにもよりますが、例えばログイン後は前に見ていた画面を表示して欲しいという要望があった場合、 以下のカスタマイズを行うことで実現可能となります。
EC-CUBE3.0.14を対象に説明します。
まず、MypageControllerにあるlogin関数を修正します。
- src/Eccube/Controller/Mypage/MypageController.php
/** * ログイン画面. * * @param Application $app * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response */ public function login(Application $app, Request $request) { if ($app->isGranted('IS_AUTHENTICATED_FULLY')) { log_info('認証済のためログイン処理をスキップ'); return $app->redirect($app->url('mypage')); } /* @var $form \Symfony\Component\Form\FormInterface */ $builder = $app['form.factory'] ->createNamedBuilder('', 'customer_login'); if ($app->isGranted('IS_AUTHENTICATED_REMEMBERED')) { $Customer = $app->user(); if ($Customer) { $builder->get('login_email')->setData($Customer->getEmail()); } } $event = new EventArgs( array( 'builder' => $builder, ), $request ); $app['eccube.event.dispatcher']->dispatch(EccubeEvents::FRONT_MYPAGE_MYPAGE_LOGIN_INITIALIZE, $event); $form = $builder->getForm(); // ログイン前の画面へ戻す $error = $app['security.last_error']($request); if (!$error) { // ログインエラーがなければ戻り先をセット $referer = $request->headers->get('referer'); if ($referer) { // refererチェック $referers = parse_url($referer); if ($referers['host'] == $request->getHost()) { // ホストが同一であればrefererをセット $requestStackUri = $app['request_stack']->getMasterRequest()->getUri(); if ($request->getUri() == $requestStackUri) { // ログイン画面遷移直前のuriをセット $app->setLoginTargetPath($referer); } else { // ログイン必須画面のuriをセット $app->setLoginTargetPath($requestStackUri); } } } } return $app->render('Mypage/login.twig', array( 'error' => $error, 'form' => $form->createView(), )); }
修正箇所は、
// ログイン前の画面へ戻す $error = $app['security.last_error']($request); if (!$error) { // ログインエラーがなければ戻り先をセット $referer = $request->headers->get('referer'); if ($referer) { // refererチェック $referers = parse_url($referer); if ($referers['host'] == $request->getHost()) { // ホストが同一であればrefererをセット $requestStackUri = $app['request_stack']->getMasterRequest()->getUri(); if ($request->getUri() == $requestStackUri) { // ログイン画面遷移直前のuriをセット $app->setLoginTargetPath($referer); } else { // ログイン必須画面のuriをセット $app->setLoginTargetPath($requestStackUri); } } } } return $app->render('Mypage/login.twig', array( 'error' => $error, 'form' => $form->createView(), ));
になります。ログイン前のrefererを取得し、ログイン成功時に直前まで見ていた画面へ戻すようにしています。ただし、ログインが必要な画面を直接指定された場合、refererを取得するとログインに成功してもrefererで指定した画面に遷移してしまうため、
$app['request_stack']->getMasterRequest()->getUri()
と本来指定されているURLを取得し、比較する事でログイン成功後の遷移先を変更するようにセットしています。
refererが取得できない環境は諦めてください。
あと、login.twigも変更する必要があります。以下抜粋です。
- src/Eccube/Resource/template/default/Mypage/login.twig
{% if app.session.flashBag.has('eccube.login.target.path') %} {% for targetPath in app.session.flashBag.peek('eccube.login.target.path') %} <input type="hidden" name="_target_path" value="{{ targetPath }}" /> {% endfor %} {% endif %}
こちらの変更箇所ですが、
{% for targetPath in app.session.flashBag.peek('eccube.login.target.path') %}
の部分となり、get
からpeek
へと変更しています。なぜpeek
に変更しているかというと、ログインエラー時にセットされていたtargepathの値が削除されてしまいますので、peek
に変更しています。
以上の対応でログイン成功後は、直前まで見ていた画面へ遷移するようになります。
必要な方には必要なカスタマイズだと思います。特にスマホだとログイン後にトップページへ遷移してしまうと離脱されてしまう可能性が高くなりますのでこちらを是非活用してください。
EC-CUBE3でPC、スマホ、タブレットの判定方法
EC-CUBE3.0.14からPCとスマホを判別するMobile Detectというライブラリが導入されています。
使い方は、PHP側からはShoppingService.phpに
// device type if ($this->app['mobile_detect']->isMobile()) { $DeviceType = $this->app['eccube.repository.master.device_type']->find(DeviceType::DEVICE_TYPE_SP); } else { $DeviceType = $this->app['eccube.repository.master.device_type']->find(DeviceType::DEVICE_TYPE_PC); }
とありますので参考になりますが、Twigから使う場合、以下の通りとなります。
{% if app['mobile_detect'].isMobile %} Mobile、Tablet {% else %} PC {% endif %}
- タブレットのみの判定
{% if app['mobile_detect'].isTablet %} Tablet {% else %} PC、スマホ {% endif %}
- スマホのみの判定
{% if app['mobile_detect'].isMobile and app['mobile_detect'].isTablet == false %} スマホ {% else %} PC、Tablet {% endif %}
レスポンシブデザインだと余り使いどころは無いかもしれませんがTwigでPCとスマホを判断したいという時に参考にしてください。
EC-CUBE3.0.13以下の方は独自でMoible Detectライブラリを導入する必要があります。
導入方法は以下のプルリクエストを参考にしてください。
モバイル種別判断用ライブラリの導入 · EC-CUBE/ec-cube@f0f5c70 · GitHub
composer.json
とApplication.php
にそれぞれ定義を追加し、EC-CUBEのルートディレクトリよりcomposer install
を実行すればインストールされます。
EC-CUBE3.0.14がリリース、さくらのレンタルサーバでEC-CUBE3.0.14をインストールした時にhtmlをURLに付けさせない方法
3月14日にEC-CUBE3.0.14がリリースされました。
EC-CUBE3.0.14で特徴的なものとしては、
- PHP7.1 対応
があります。
さくらのレンタルサーバはphp7.1がサポートされているため、 EC-CUBE3.0.14から安心して利用できるようになります。
そこで、XSERVERに引き続きさくらのレンタルサーバでhtmlをURLにつけさせない方法を説明します。
基本はXSERVERの時と全く同じです。
EC-CUBE3.0.11をXSERVERにインストールした時にhtmlを付けさせない方法 - AmidaikeBlog
※すでにDBが作成されている前提です。
レンタルサーバでは公開ディレクトリは固定されている事が多く変更する事は出来ないのですが、さくらのレンタルサーバの公開ディレクトリは、
/home/hoge/www
とwww
が公開ディレクトリになっています。
※hoge
の部分は適宜ご自身の環境と読み替えてください。
過去に説明した記事であれば、.htaccess
を色々とごにょごにょする事で対応してきましたが今回も、
インストール時にURLからhtmlを無くす | EC-CUBE 開発ドキュメント
こちらを参考にhtml
を外す方法を説明していきます。
EC-CUBE3.0.14のアップロード
EC-CUBE3.0.14を
EC-CUBEダウンロード | ECサイト構築・リニューアルは「ECオープンプラットフォームEC-CUBE」
こちらからダウンロードし、
FTP等で/home/hoge
直下にアップロードします。
EC-CUBE3.0.14の解凍
さくらのレンタルサーバへSSHでログイン後、アップロードされたディレクトリからEC-CUBEを解凍します。
unzip eccube-3.0.14.zip
解凍したEC-CUBEをwww配下にコピーします。
cd eccube-3.0.14 cp -pr . ../www/
ファイル配置場所の変更
公開ディレクトリまでカレントディレクトリを移動し、html
ディレクトリに存在する必要なファイルを公開ディレクトリ直下に移動させます。
cd cd /home/hoge/www mv html/in* . mv html/.htaccess . mv html/robots.txt .
→今回はweb.configは不要なため移動させていません。
.htaccessの削除、.htaccess.sampleのリネーム
移動した.htaccess
を削除し、public_html直下に存在している.htaccess.sample
に置き換えます。
rm .htaccess mv .htaccess.sample .htaccess
index.php、install.phpの書き換え
- index.phpの書き換え
vi index.php
を実行し、27行目のコメントアウトされている箇所を変更し、26行目をコメントアウトます。
//[INFO]index.php,install.phpをEC-CUBEルート直下に移動させる場合は、コメントアウトしている行に置き換える require __DIR__.'/../autoload.php'; //require __DIR__.'/autoload.php';
↓
//[INFO]index.php,install.phpをEC-CUBEルート直下に移動させる場合は、コメントアウトしている行に置き換える //require __DIR__.'/../autoload.php'; require __DIR__.'/autoload.php';
- install.phpの書き換え
vi install.php
を実行し、31行目のコメントアウトされている箇所を変更し、30行目をコメントアウトします。
//[INFO]index.php,install.phpをEC-CUBEルート直下に移動させる場合は、コメントアウトしている行に置き換える require __DIR__ . '/../autoload.php'; //require __DIR__ . '/autoload.php';
↓
//[INFO]index.php,install.phpをEC-CUBEルート直下に移動させる場合は、コメントアウトしている行に置き換える //require __DIR__ . '/../autoload.php'; require __DIR__ . '/autoload.php';
autoload.phpの変更
- autoload.phpの書き換え
vi autoload.php
を実行し、36行目のコメントアウトされている箇所を変更し、35行目をコメントアウトします。
//[INFO]index.php,install.phpをEC-CUBEルート直下に移動させる場合は、コメントアウトしている行に置き換える define("RELATIVE_PUBLIC_DIR_PATH", ''); //define("RELATIVE_PUBLIC_DIR_PATH", '/html');
↓
//[INFO]index.php,install.phpをEC-CUBEルート直下に移動させる場合は、コメントアウトしている行に置き換える //define("RELATIVE_PUBLIC_DIR_PATH", ''); define("RELATIVE_PUBLIC_DIR_PATH", '/html');
.htaccessの追加
公開ディレクトリをEC-CUBEルート直下にしたため、このままだと見せる必要のないディレクトリまで見えてしまいます。
そのため、以下の.htaccessファイルを各ディレクトリ直下に配置してください。
- .htaccessの内容
order allow,deny deny from all
この内容を
src
、tests
、vendor
ティレクトリ直下に配置します。(appディレクトリ直下には既に存在)
EC-CUBEのインストール
http://hoge.sakura.ne.jp とアクセスし、インストール作業が出来れば対応完了です。
以上がhtml
をURLから付けさせない方法となります。
インストール後もhtmlディレクトリを削除する事は可能ですが、非常にめんどくさいためインストール前に設定するのがオススメです。
この方法で上手く動かないという方はコメントください。
EC-CUBE3の入力チェック時のエラーメッセージで項目名を表示させる方法
EC-CUBE3では入力チェック時のエラーメッセージ表示が標準のままだと項目名が表示されておらず、表示させるためには少々手を加える必要があります。
そこで今回は項目名を表示させたいけど分からないという方のために項目名を表示する方法を説明します。
現在のエラーメッセージの表示は標準ではこのようになっています。
キャプチャを確認してもらうと分かる通り項目名が表示されておらず、何が入力されていないのか分かりづらいです。このエラーメッセージ表示を、
このように項目名を表示させるにはどうするかというと、
ECCUBEROOT/src/Eccube/Resource/template/default/Form/form_layout.twig
の59行目にある
<p class="errormsg text-danger">{{ error.message |trans }}</p>
を
<p class="errormsg text-danger">{{ form.vars.name|trans }} : {{ error.message |trans }}</p
に修正します。
※ECCUBEROOT : EC-CUBE3がインストールされているディレクトリ
この修正だけだとまだ不完全で、
とinput属性のnameがそのまま表示されてしまいます。この部分を日本語に表示させるには、
ECCUBEROOT/src/Eccube/Resource/locale/message.ja.yml
ファイルに以下の設定を追加します。(追加する場所はどこでも可能)
name01: 姓 name02: 名 kana01: セイ kana02: メイ ・ ・ ・
この内容を追加することで項目名が日本語表示されます。
入力チェックエラー発生時に英語表記されたら他の項目に対してもmessage.ja.yml
に
画面上に表示された値: 日本語名
と追加していくことで日本語に対応可能です。
エラーメッセージに項目名を表示させたいという方は是非お試しください。
既に本番環境を運用されている方でこの方法を適用しても項目名が表示されないという方は、ECCUBEROOT/app/cache/translator
ディレクトリを削除後に再度お試しください。