小田原ワーケーション(小田急電鉄)様の導入事例を公開しました。
地域の”体験”をひとつのサイトで”探す・予約する・決済する”まで一貫して提供するモール型EC。
EC-CUBEの柔軟性で実現した、その舞台裏をご紹介します。
Blog
ブログ
小田原ワーケーション(小田急電鉄)様の導入事例を公開しました。
地域の”体験”をひとつのサイトで”探す・予約する・決済する”まで一貫して提供するモール型EC。
EC-CUBEの柔軟性で実現した、その舞台裏をご紹介します。
今回は、弊社が手掛けた ECサイトのカスタマイズ事例 をご紹介します。
「こんなことできるの?」と思った方、ぜひお気軽にご相談ください。
【1】URLのスラッグ対応
サイトのSEO対策として、商品やカテゴリのURLスラッグをカスタマイズするニーズが増えています。弊社では、商品IDではなく、意味のあるカテゴリ名やキーワードを使用することで、検索エンジンにとって親しみやすいURL構造を実現しました。これにより、
SEO効果の向上とユーザーの利便性が高まりました。
【2】独自クーポンの作成
多くのECサイトでは、特定の条件を満たした顧客にクーポンを配布することが求められます。弊社では、購入金額や会員ランク、特定のカテゴリー購入者向けに、独自のクーポン発行機能を実装しました。これにより、マーケティング施策を柔軟に展開することが可能になり、顧客満足度を向上させています。
【3】独自購入オプションの追加
商品購入時に必要なオプションをカスタマイズできる機能を追加しました。例えば、ギフトラッピングやメッセージカードなど、顧客のニーズに合わせた購入オプションを自由に設定することができ、よりパーソナライズされたショッピング体験を提供しています。
【4】セット商品の販売
セット商品を販売するためのカスタマイズも承りました。特定の商品をセットにして割引価格で提供することで、顧客の購買意欲を刺激し、売上を大幅にアップさせることができました。セット商品には、在庫管理や価格設定など、細かな部分の調整も可能です。
【5】外部レビューとの連携
商品レビューを外部のレビューサイトと連携させることで、信頼性を向上させました。これにより、リアルな口コミをサイト上で紹介できるようにしました。
【6】アンケート作成機能
顧客からのフィードバックを集めるため、アンケート作成機能を導入しました。特定のキャンペーンや商品に対する意見を簡単に収集でき、マーケティング戦略の改善や新商品開発に役立っています。
【7】BtoB向けクローズドサイト機能
法人向け(BtoB)の取引を行うための、クローズドサイト機能も導入しました。全てのページ(会社概要や規約ページを除く)は、ログインしないと閲覧できない設定にすることで、取引先専用の環境を構築しました。
「この機能、うちでも使える?
こういう悩みを解決したいけど、どうしたら?」
そんなお悩みをお持ちでしたら、ぜひJoolenにご相談ください。
お問い合わせはこちら
SEO観点におけるURLについて調べていると
URLのクエリパラメータに関するベストプラクティスとして以下の内容が載っていました。
同じパラメータを 2 回使用しないようにします。Googlebot はどちらかの値を無視する可能性があります。
推奨: ?type=candy,sweet
非推奨: ?type=candy&type=sweet (引用)
参考:URL のクエリ パラメータに関するベスト プラクティス
Eccubeで複数選択可の項目を検索すると、 「?type[]=candy&type[]=sweet」 のような、
上記で非推奨とされる「同じパラメータを複数回使用しているURL」になります。
検索エンジンにインデックスさせる対象が、単一選択されたページのみ(「?type[]=candy」「 ?type[]=sweet」 は対象だが 「?type[]=candy&type[]=sweet」 はインデックス対象ではない)
の場合は気にする必要はないと思いますが、もし、複数選択したページをインデックスさせたいなら対応が必要かも(?)ということで今回、Eccube4.3で試してみました。
前提条件である「複数選択検索」をできる項目が、Eccube4.3の初期状態では無いので、まずはそれを追加します。
今回は「複数選択可なカテゴリ」を追加します。
(カテゴリ検索は既にあるのですが、単一選択しかできないので、複数選択可な状態のなものを追加します)
1-1.FormTypeのカスタマイズ
EccubeのフォームはFormTypeに実装されているので、カスタマイズして、複数選択可用のカテゴリ項目を追加します。
app/Customize/Form/Extension/ 配下に以下のような「SearchProductTypeExtension.php」を追加します。
実装例
<?php
namespace Customize\Form\Extension;
use Eccube\Form\Type\SearchProductType;
use Eccube\Repository\CategoryRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
class SearchProductTypeExtension extends AbstractTypeExtension
{
private CategoryRepository $categoryRepository;
public function __construct(CategoryRepository $categoryRepository)
{
$this->categoryRepository = $categoryRepository;
}
public static function getExtendedTypes(): iterable
{
yield SearchProductType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$categories = $this->categoryRepository->getList(null, true);
$builder->add('category_ids', EntityType::class, [
'class' => 'Eccube\Entity\Category',
'choices' => $categories,
'choice_label' => 'NameWithLevel',
'multiple' => true,
'expanded' => true,
'required' => false,
'label' => 'カテゴリ(複数選択)',
'attr' => [
'class' => 'form-control',
],
]);
}
}
これで、既存のSearchProductType に対して、「category_ids」フォーム項目を追加したことになります。
既に存在するカテゴリ検索項目「category_id」との違いは、チェックボックスになるように「’multiple’ => true」「’expanded’ => true」を追加しただけです。
1-2.Repositoryのカスタマイズ
新しく追加したフィールド「’category_ids’」で検索されるようにRepositoryもカスタマイズします。
app/Customize/Repository配下に以下のようなファイルを追加します。
実装例
<?php
namespace Customize\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Eccube\Doctrine\Query\QueryCustomizer;
use Eccube\Repository\QueryKey;
class ProductRepositoryCustomizer implements QueryCustomizer
{
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* 商品検索にカテゴリ(複数)を追加する
*
* @param QueryBuilder $builder
* @param array $params
* @param $queryKey
*/
public function customize(QueryBuilder $builder, $params, $queryKey): void
{
// category(s)
if (!empty($params['category_ids'])) {
$Categories = $params['category_ids'];
if ($Categories->count() > 0) {
$subQb = $this->entityManager->createQueryBuilder();
$subQb->select('1')
->from('Eccube\Entity\ProductCategory', 'pct_sub')
->where('pct_sub.Product = p') // 'p'は親クエリのエイリアス
->andWhere($subQb->expr()->in('pct_sub.Category', ':Categories'));
$builder->andWhere($builder->expr()->exists($subQb->getDQL()))
->setParameter('Categories', $Categories);
}
}
}
/**
* ProductRepository::getQueryBuilderBySearchData に適用する.
*
* @return string
* @see \Eccube\Repository\ProductRepository::getQueryBuilderBySearchData()
* @see QueryKey
*/
public function getQueryKey(): string
{
return QueryKey::PRODUCT_SEARCH;
}
}
「category_ids
」が選択されている場合は、選択されたカテゴリIDが、カテゴリとして設定されている商品をExistで絞り込んでいます。
1-3.twigのカスタマイズ
app/template/default/Product 配下に src/Eccube/Resource/template/default/Product/list.twig のコードをコピーして配置します。するとapp/template/default/Product/list.twig の方が参照されます。
新しく配置したapp/template/default/Product/list.twigのformタグの中に、category_idsフィールドを追加します。
その時、既存の、「FormTypeのフィールドをfor文でhiddenとして書き出している処理」からcategory_idsフィールドを除外します。
実装例
<form name="form1" id="form1" method="get" action="?">
{{% for item in search_form %}
{# category_idsは除外 #}
{% if item.vars.name != 'category_ids' %}
<input type="hidden" id="{{ item.vars.id }}"
name="{{ item.vars.full_name }}"
{% if item.vars.value is not empty %}value="{{ item.vars.value }}" {% endif %}/>
{% endif %}
{{% endfor %}
{{# 新しい複数選択カテゴリフィールドの表示 #}
{<div class="form-group">
{{ form_widget(search_form.category_ids) }}
{{ form_errors(search_form.category_ids) }}
<button type="submit" class="btn btn-primary mt-2">
{{ '検索' }}
</button>
{</div>
</form>
これで検索結果一覧ページにアクセスすると、複数選択出来るカテゴリのチェックボックスと検索ボタンが追加された画面が表示されます。
これでカテゴリの複数検索すると下記のようなURLになります。(デコードしています)
http://localhost:8080/products/list?mode=&category_id=&name=&pageno=&disp_number=20&orderby=1&category_ids[]=7&category_ids[]=9
※動作確認のため、いくつかカテゴリを追加しています。
これで前提条件である「同じパラメータを複数回使用したURL」の状態になりました。
いよいよ本題であるURLのカンマ区切りに着手します。
2-1.検索実行直前にjavascriptで配列 → 文字列 変更する
チェックボックスで選択した値をそのままの状態で検索実行してしまうと、配列のURLが生成されてしまうので、javascript でカンマ区切りの文字列に変更します。
実装例(app/template/default/Product/list.twig に追記しました)
<script>
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('form1');
form.addEventListener('submit', function (e) {
const checkboxes = form.querySelectorAll('input[name="category_ids[]"]:checked');
const selectedValues = Array.from(checkboxes).map(cb => cb.value);
// 既存の複数inputをdisabledにして送信されないようにする(後で1つのinputにまとめるため)
checkboxes.forEach(cb => cb.disabled = true);
// 新しいhidden inputを1つ作成
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'category_ids';
input.value = selectedValues.join(',');
form.appendChild(input);
});
});
</script>
上記のjavascript コードで、以下の内容を実行しています。
これだけでURLは、目的である「同じパラメータは1回しか使用されない」状態になります。
http://localhost:8080/products/list?mode=&category_id=&name=&pageno=&disp_number=20&orderby=1&category_ids=7,9
※デコードしています。
しかし、これだけだと検索がうまくいきません。FormTypeでは配列で送られてくることが期待されていますが、文字列で来たためエラーになってしまいます。
今度はFormType側で文字列 → 配列 に変換して帳尻を合わせます。
2-2.FormTypeの処理時に文字列 → 配列 に変換する
手順1で追加した「SearchProductTypeExtension
」に以下の内容を追記します。
実装例
<?php
namespace Customize\Form\Extension;
・・・省略・・・
use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents;
class SearchProductTypeExtension extends AbstractTypeExtension
{
private CategoryRepository $categoryRepository;
public function __construct(CategoryRepository $categoryRepository)
{ ・・・省略・・・ }
public static function getExtendedTypes(): iterable
{ ・・・省略・・・ }
public function buildForm(FormBuilderInterface $builder, array $options)
{
・・・省略・・・
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { $data = $event->getData(); // カンマ区切りの文字列を配列に変換 if (isset($data['category_ids']) && is_string($data['category_ids'])) { $ids = array_filter(array_map('trim', explode(',', $data['category_ids']))); $data['category_ids'] = $ids; $event->setData($data); } });
}
}
PRE_SUBMIT イベントを使って、カンマ区切り文字列を配列に変換しています。
PRE_SUBMIT イベントは「フォームにデータを送信する前に、リクエストのデータを変更する」時に使うものなので、今回のような目的にはピッタリですね。
参考:Symfony Form Events
FormTypeに上記を修正を適用すると、URLの目的を達成しつつ、検索機能も損なわない状態になります。
一応これで今回の試したかったことは出来ました。お試しだったので「category_ids」に特化したコードになってしまいましたが、本当に運用するつもりなら、処理は部品化して汎用的に使えるようにすると良いと思います。
いかがだったでしょうか。今回はたまたま見つけた「同じパラメータを 2 回使用しない」を試してみました。
私は今まで聞いたことが無かったので、SEO対策としての重要度はそこまで高く無いのかもしれません。また、最初にも書いた通り、複数選択された状態をインデックスさせる必要が無い場合はそもそも必要ありません。
それなりに対応コストはかかるので、もし本格的に導入を検討をする際には、一度SEO対策会社の方へ相談してから判断するのが良いでしょう。
こんにちは!
今回はネットショップ運営を考えている方、または今のECサイトに満足していない方に向けて、
日本生まれのECプラットフォーム「EC-CUBE(イーシーキューブ)」をご紹介します。
無料で始められて、しかも柔軟にカスタマイズできるとあって、実は中小企業から大手企業まで幅広く使われているんです。
EC-CUBEは、日本発のオープンソースECプラットフォーム。
言い換えれば、「自分で自由に作れるネットショップの土台」です。
無料でダウンロード・利用できて、自社に合ったショップを思い通りに作れるのが最大の魅力!
デザインの変更も、機能追加も、まるでブロックのパーツのように組み立て自由自在なのです。
✅ 商品の登録やカテゴリ分け
✅ 受注〜発送までの一元管理
✅ 会員登録・購入履歴・ポイント機能
✅ HTML/CSSでの自由なデザイン編集
✅ プラグインで機能拡張(クーポンやSNS連携)
つまり、「これがあればネットショップとして十分」な機能が、はじめからそろっています。
💡 スマホ表示に自動対応
スマートフォンでも見やすく、購入しやすいUIになっています。
💡 会員ランクやポイント制度もカンタン導入
リピーター獲得の施策もばっちり。
💡 越境ECも視野に(多言語・多通貨対応)
必要に応じて、海外販売の足がかりにもなります。
💡 エンジニアにはうれしい構造
開発やカスタマイズがしやすい設計、開発コミュニティやドキュメントも充実。
💡 管理画面がわかりやすい!
日本語で操作に迷わず、誰でもショップ運営をスタートできます。
* これから本格的にネットショップを始めたい方
* 自由にカスタマイズして差別化したい方
* ShopifyやBASEでは物足りなくなってきた方
* 自社独自の販売スタイルに合わせて構築したい方
自分で作りたい人にも、プロに頼んで構築する人にも使いやすいのがEC-CUBEの魅力。
まずは一度、公式サイトやデモで触ってみてはいかがでしょうか?
EC-CUBEは、アイデア次第でショップの可能性がどんどん広がる柔軟なプラットフォームです。
「やってみたいけど、どこから手を付けたらいいかわからない」「自社向けにカスタマイズしたい」など、
導入や運用でお悩みがあれば、ぜひお気軽にご相談ください。
お問い合わせはこちら
PHPでデバックするときに一番手っ取り早いのはver_dump関数ですが、見たい内容を毎回記述する必要があったり、画面表示しない処理(CSVダウンロードなど)だとデバックしにくい面もあります。
そこでXdebugです。
公式:https://xdebug.org/
IDEでブレークポイントをつけた箇所で処理が止まってくれて、変数の中身などを確認することが出来ます。 例えば次の画像のように$idの内容が確認できます。
xdebugの仕組みの概要は以下です。
IDEによってWebサーバーが「呼び出される」のかと思っていましたが、実際は逆で Xdebug(Webサーバー)がIDE に接続しに行くようです。
この辺りは以下の動画が分かりやすかったので、気になる方はご視聴をお勧めします。
#03 – PHP Advanced Debugging With Xdebug- How Xdebug Works
とても便利なのですが、設定が少しややこしいので、今回は現時点で最新のEccube4.3をローカルに構築して、Xdebugの導入してみました!
まずはEccubeのコードを用意します。
EccubeはOSS(オープンソースソフトウェア)で、以下のGitHubから取得できます。
https://github.com/EC-CUBE/ec-cube
コードを適当なディレクトリの配置後、初回インストールを実施するのですが、今回はXdebugの起動を確認すれば良いだけなので、初回インストール状態を残すべく、以下の変更を加えます
docker-compose.yml
volumes:
html-app: # ← ソースコードが含まれるボリューム(初回インストール後も残す)
services:
ec-cube:
volumes:
- html-app:/var/www/html
この状態で初回インストールを行います。
参考:Docker Composeを使用してインストールする
#初回インストールコマンド
# コンテナの起動 (初回のみビルド処理あり)
docker-compose up -d
# 初回はインストールスクリプトを実行
docker-compose exec -u www-data ec-cube bin/console eccube:install -n
ローカルにアクセスできたらOK。
http://localhost:8080/
ルート直下にあるDockerfile、docker-compose.yamlを変更します。
1.Dockerfileの修正
PECLでインストールします。以下を追記します。
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug ## 追記
以下をコメントアウトします。(2度目立ち上げ時に失敗してしまうのでコメントアウト)
#COPY dockerbuild/docker-php-entrypoint /usr/local/bin/
2.php.iniにxdebugの設定を追加
ビルド時に「dockerbuild/php.ini」のファイルをphp.iniに読み込んでいるので、ここに以下の設定を追記します。
[xdebug]
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_port = 9003
xdebug.client_host = host.docker.internal
個人的にclient_hostが毎回ハマるポイントです。
Macでは上記の「host.docker.internal」で問題ないらしいのですが、 私の環境(WLS2)だとうまくいきませんでした。
※最近のバージョンではWLS2でも「host.docker.internal」で出来る、という記事もみたのですが、残念ながら私の環境では出来ませんでした。
色々試行錯誤した結果以下の値を設定することで成功しました。
・コマンドプロンプトや PowerShell でipconfigを実行した後の「イーサネット アダプター vEthernet (WSL):IPv4 アドレス 」の値
※ただしこの値は固定ではない(再起動などで変更される可能性がある)ので、他の方法が出来る場合は他の方法を採用した方が良いと思います。
> ipconfig
イーサネット アダプター vEthernet (WSL):
IPv4 アドレス . . . . . . . . . . : 172.**.***.***
仕組みの概要で触れた通り、IDEはXdebugからの通信を待機して受け取る必要があるので、設定が必要です。
1.設定->PHP->サーバ でサーバーを追加する
プラスマークから追加します。
ここでは主にパスマッピングが重要です。
パスマッピングの設定によって「Xdebug 経由でやってくる“/var/www/html/はローカルではこのパスですよ」と伝えることが出来ます。
名前 : 何でも良い。
ホスト : localhostで設定しているがそれ以外の値でも成功する。
ポート : 80で設定しているがそれ以外の値でも成功する。
デバッガー : Xdebug を選択
パスマッピングを使用する : オンにして対応するパスを設定する
設定値を入れたら適用する
2.設定->PHP->デバッグ でXdebugの設定を確認する
デバッグポート: 9000、9003の2つがデフォルトで指定されていますが、これは
Xdebugのポートのデフォルトが、Xdebug2では9000だったのが、Xdebug3で9003に変更されたためのようです。
今回はPHP8でXdebug3になるので、9003のみにして、
あとは「外部接続を受け入れる」にチェックが入っていることを確認して、適用保存します。
※9000,9003の2つが設定されたままでも問題ありません。
3.実行 / デバッグ構成 を設定する
PhpStormヘッダ部に「現在のファイル」となっている部分をクリックすると
「実行構成の編集」というメニューが表示されるのでそれをクリック。
プラスマークから「PHPリモートデバッグ」を追加します。
名前に何でも良いので値を設定し、適用します。
※「IDEキーでデバッグ接続をフィルターする」にチェックを入れる記事が多いですが、今回はチェック無しで出来たのでOFFのまま進めます。
手順1で立ち上げた環境ですが、一度
ec-cube_1コンテナに入り、 php -v で表示される情報の中に「Xdebug」の文字があればインストールされています。
1.PhpStormのヘッダ部にある電話のようなマークをクリックしてリッスンを開始します。
2.PhpStormのヘッダ部にある虫のようなマークをクリックしてデバッグを開始します。
3.ステップさせたいところにブレークポイントを設定して、ブラウザからリクエストを実行。
ステップデバッグが出来るようになると、初回のダイアログが表示されます。
承認し、最初の画像のようにブレークポイントで停止してくれるようになれば設定完了です!
いかがだったでしょうか。
開発を助けてくれるXdebugですが、EccubeだけではなくてPHPであれば利用できますので、
PHPで開発されている方はローカル環境に入れてみてはいかがでしょうか。
※Xdebugはあくまで開発専用の機能なので、本番環境には絶対に入れてはいけません。
最近これ便利だなっていうjavascriptプラグインを見つけたので紹介したいと思います。
開発者が嬉しいというより使っていただくユーザさんに便利なプラグインです。
名前を入力する場合は大抵フリガナも入力する欄が設置されていると思いますが同じことを2回入力するのって地味にめんどくさいと思うんです。
そんな手間を少しでも楽にしたい時はぜひ使ってみてください。
ECCUBEのバージョンには依存しないので、2系〜4系どこでも使用できるかと思います。
※今回は4系に実装します
https://github.com/harisenbon/autokana
こちら日本語入力に対するフリガナを自動的に別フィールドに記入するJQueryプラグインになります。
注意点も少しあります。
・keydownで発火するためコピペなどでは使えません
・入力されている文字を読み取ってカナに変換しているわけではないのでタイポした場合はカナに文字が残ってしまう
ここからは設置方法を説明します。とっても簡単です。
まず↑のリンクから.jsをダウンロードしhtml/user_data/jsに設置
Twigファイルを修正
app/template/default/Entry/index.twig
<script src="{{ asset('assets/js/autokana-master/jquery.autoKana.js', 'user_data') }}"></script> <script> $(function() { $.fn.autoKana('input[name="entry[name][name01]"] ', 'input[name="entry[kana][kana01]"]', {katakana:true}); $.fn.autoKana('input[name="entry[name][name02]"] ', 'input[name="entry[kana][kana02]"]', {katakana:true}); }); </script>
これだけです!
とってもかんたんですね♪
では実際に名前を入力してみましょう。
ちゃんとカナに入力されているのがわかりますね!
すぐできますのでぜひお試しください
EC-CUBE4 の Docker環境で環境変数を設定する際に、思わぬ壁にぶち当たりました。
services.yaml に記述されている設定内容を、環境ごとに分けるため、環境変数から取得するようにしたかったのです。
クレジット決済の3Dセキュアに関する設定なので、3D_SECURE_SETTING といった感じの名前で環境変数を登録し、設定として取得するようにしました。
docker-compose を使用する環境で環境変数を登録するには、docker-compose.dev.yml の environment に記述します。
services:
ec-cube:
environment:
3D_SECURE_SETTING: "my_value"
環境変数を設定ファイル services.yaml で取得するには、’%env(環境変数名)%’ とします。
parameters:
my_setting: '%env(3D_SECURE_SETTING)%'
以上で、コントローラー等で
$this->eccubeConfig['my_setting']
とすれば、”my_value”が読み取れるはず、が、以下のエラーが発生しました。
Environment variable not found: “3D_SECURE_SETTING”
何度も設定方法を確認し、コンテナの再起動とキャッシュクリアを繰り返すも虚しく時間がすぎるだけでしたが、ふと、「この変数名…?」と気づきました。
数字で始まる変数名は、多くのプログラミング言語で許可されていません。
また環境変数の命名規則も同様なようです。
PHPのコーディングをしている時はほぼ無意識的に避けて命名していたのですが、設定ファイル内でのこととあってか、頭から抜けていました。
英字から始まる環境変数名にすることで、無事取得できました!
イージーなミスですが、油断してるとハマりますね。
eccubeでenumを使いたい!
ECcubeでは固定値などはMasterにレコードを追加して、
使いたい場合は都度DBからレコードを検索して使用しているかと思います。
ですがいちいちDBに接続&検索をして使うのは…という場合にこんなやり方もあります。
enumの追加&使用方法を簡単ですがご紹介したいと思います。
まず、Customize配下にEnumディレクトリを追加
下記のようなファイルを作成
<?phpnamespace Customize\Enum;/*** 会員ランク*/enum CustomerRankType: string{case ROOKIE = ‘1’;case BRONZE = ‘2’;case SILVER = ‘3’;case GOLD = ‘4’;case PLATINUM = ‘5’;case DIAMOND = ‘6’;case MASTER = ‘7’;public function getLabel(): string{return match ($this) {self::ROOKIE => ‘ルーキー’,self::BRONZE => ‘ブロンズ’,self::SILVER => ‘シルバー’,self::GOLD => ‘ゴールド’,self::PLATINUM => ‘プラチナム’,self::DIAMOND => ‘ダイアモンド’,self::MASTER => ‘マスター’,};}public static function getTypeList(){$allList = [];foreach (self::cases() as $item) {$allList[$item->getLabel()] = $item->value;}return $allList;}}
使用方法ですが、例えばFormTypeで使用する場合は下記のようにすれば使用できます。
->add(‘customer_rank’, ChoiceType::class, [
‘required’ => false,
expanded’ => false,
‘multiple’ => false,
‘placeholder’ => ‘選択してください’,
‘choices’ => CustomerRankType::typeList(),
])
Twigにはこんな感じです
<div class=”row mb-2″><div class=”col-3″><span>{{ ‘会員スペシャルランク’|trans }}</span><span class=”badge bg-primary ms-1″>{{ ‘admin.common.required’|trans }}</span></div><div class=”col”><div class=”row”><div class=”col”>{{ form_widget(form.customer_rank) }}</div></div></div></div>
こんな感じで表示することができました。
ぜひ機会があればですが、検討してみてください。
EccubeではtwigやDoctrieで使用されているキャッシュをクリアする方法が、大きく2つあります。
php app/console cache:clear
私の参画していた案件ではコードがデプロイされると自動的にキャッシュクリアコマンドが実行されたので、(2)の方法でキャッシュクリアをしていたことになるのですが、それだとPluginのキャッシュがクリアされませんでした。
ということでキャッシュクリアコマンドでPluginのキャッシュもクリアさせる方法です。
/src/Eccube/Util/Cache.php
public static function clear($app, $isAll, $isTwig = false)
{
$cacheDir = $app['config']['root_dir'].'/app/cache';
$filesystem = new Filesystem();
if ($isAll) {
$finder = Finder::create()->in($cacheDir)->notName('.gitkeep');
$filesystem->remove($finder);
} elseif ($isTwig) {
if (is_dir($cacheDir.'/twig')) {
$finder = Finder::create()->in($cacheDir.'/twig');
$filesystem->remove($finder);
}
} else {
if (is_dir($cacheDir.'/doctrine')) {
$finder = Finder::create()->in($cacheDir.'/doctrine');
$filesystem->remove($finder);
}
if (is_dir($cacheDir.'/profiler')) {
$finder = Finder::create()->in($cacheDir.'/profiler');
$filesystem->remove($finder);
}
if (is_dir($cacheDir.'/twig')) {
$finder = Finder::create()->in($cacheDir.'/twig');
$filesystem->remove($finder);
}
if (is_dir($cacheDir.'/translator')) {
$finder = Finder::create()->in($cacheDir.'/translator');
$filesystem->remove($finder);
}
// pluginディレクトリを対象に追加ここから
if (is_dir($cacheDir . '/plugin')) {
$finder = Finder::create()->in($cacheDir . '/plugin');
$filesystem->remove($finder);
}
// pluginディレクトリを対象に追加ここまで
}
if (function_exists('opcache_reset')) {
opcache_reset();
}
if (function_exists('apc_clear_cache')) {
apc_clear_cache('user');
apc_clear_cache();
}
if (function_exists('wincache_ucache_clear')) {
wincache_ucache_clear();
}
return true;
}
カスタマイズ箇所は「pluginディレクトリを対象に追加ここから」「pluginディレクトリを対象に追加ここまで」とコメントしている間の4行のみです。(コメント含めると6行)
「キャッシュクリアコマンドで全てのキャッシュファイルは削除される」と思い込んでいましたが、デフォルトではPluginは対象外のようです。
ちなみに、--all
をつけてphp app/console cache:clear --all
で実行するとapp/cache配下全てがクリアされるので、Pluginのキャッシュファイルも削除されますが、これは稼働中のサーバでは実行してはいけません。
デフォルトではapp/cache配下にセッションファイルも格納しているためです。
cacheというディレクト名なので削除可能なファイルが置かれている印象を受けますが、実はセッションのようなファイルが入っている、特にカスタマイズしている場合はセッション以外にも削除不可なファイルが配置されている可能性もありますので、allオプションはよほど自信が無い限りは利用しないほうが良いと思います。
以上、「キャッシュクリアコマンドで全てのキャッシュファイルは削除されると思ったらプラグインは別だった」でした。
ECCUBEでは、商品の価格は税抜の本体価格を登録する仕様になっています。
しかし元々税込価格で管理していた場合、端数の処理を考慮しつつ税抜価格を計算して登録しなければなりません。
それならはじめから税込価格を登録したい、というケースで実施したカスタマイズ方法がこちらです。
内容としてはシンプルに、商品の税表示区分はすべて「税込」とし、外税額を求めるメソッドで必ず0を返すようにしてしまうというものです。(確認したECCUBEバージョンは4.2です。)
app/Customize/Service/OrderHelperExtension.php
を作成し、OrderHelper の getTaxDisplayType を上書き宣言します
<?php
namespace Customize\Service;
use Eccube\Entity\Master\TaxDisplayType;
class OrderHelperExtension extends \Eccube\Service\OrderHelper
{
/**
* 税表示区分を取得する.
* 価格を税込みで登録するため、常に"税込"を返す
*
* @param $OrderItemType
*
* @return TaxDisplayType
*/
public function getTaxDisplayType($OrderItemType)
{
return $this->entityManager->find(TaxDisplayType::class, TaxDisplayType::INCLUDED);
}
}
app/Customize/Service/TaxRuleServiceExtension.php
を作成し、TaxRuleService の getTax を上書き宣言します
<?php
namespace Customize\Service;
class TaxRuleServiceExtension extends \Eccube\Service\TaxRuleService
{
public function getTax($price, $product = null, $productClass = null, $pref = null, $country = null)
{
// 価格を税込みで登録するため、外税計算は常に0を返す
return 0;
}
}
app/Customize/Resource/config/services.yaml
でサービスの上書きを設定します。
services:
Customize\Service\OrderHelperExtension:
autowire: true
decorates: Eccube\Service\OrderHelper
Customize\Service\TaxRuleServiceExtension:
autowire: true
decorates: Eccube\Service\TaxRuleService
以上で、商品に登録した価格を税込みとして扱うことができます。
【注意】プラグインや独自カスタマイズで、上記で上書きしたメソッドを使わずに税額・税込価格を計算している場合があります。動作確認を行い、適切な修正を施す必要があります。