EC-CUBE3で動的な新規ブロックを作成する方法について。
Symfonyの仕様を理解していない僕は、手探りで何度もエラーを起こしながら、ようやくわかったので、備忘録としてもここに記載することにします。
まず、動的なブロックを作成する時に、なるべくDBやコマンド操作をしないでGUIで解決する方法は、以下の手順となる。
①EC-CUBE管理画面で、「コンテンツ管理」>「ブロック」より、「新規作成」で静的なブロックを作成する.
②ブロックの編集画面もしくは、FTP上で作成したブロックのtwigファイルを編集。
ただし、この時はまだコードを書いていなくてもよい。管理画面上では、ブロックデータは空白では登録できないので、0とかaとか、とりあえず入力して登録する。ここでは、「ピックアップアイテム」というブロックを作成した。
③コントローラー部分への追記をして、動的ブロックを定義する
ここでは例として、
/public_html/src/Eccube/Controller/Block
の中に「PickupItemController.php」というファイルを作成した。
<?php
namespace Eccube\Controller\Block;
use Eccube\Application;
use Symfony\Component\HttpFoundation\Request;
class PickupItemController
{
public function index(Application $app) {
// del_flg(削除フラグ)がたっていないものを取得
$product_data = $app['eccube.repository.product']->findBy(array('del_flg' => 0));
// unsetするため一時的な変数へ
$temp = $product_data;
foreach ($temp as $key => $p) {
$delete_flg = true;
// 非公開のものは除外
if (! $p->isEnable()) { unset($product_data[$key]); continue; }
// タグがPICK UPのものを抽出
$tag = $p->getProductTag();
foreach ($tag as $k => $val) { if ($val->getTag() == 'ピックアップ') $delete_flg = false; }
if ($delete_flg) unset($product_data[$key]);
}
// テンプレートへ値を渡して出力させる
return $app['view']->render('Block/pickup_item.twig', array('PickupItem' => $product_data));
}
}
この記述で、先ほど作成したpickup_item.twigというブロックにDBからのデータを受け渡しする制御をしている。
ここの
if ($val->getTag() == 'ピックアップ'
で「ピックアップ」としている部分、ここで、EC-CUBE管理画面で商品に設定する「タグ」の判定をしているので、この部分を書き換えることで、判定をさせたいタグを書き換えるとよい。
④もうひとつ、コントローラーの書き換えが必要。
これがわからなくて、見つけるのに大変時間を費やしてしまった。。
/public_html/src/Eccube/ControllerProvider
の中にある、
FrontControllerProvider.php
のコードの74行目あたり、「//block」の最後行に、
'\Eccube\Controller\Block\NewProductController::index')->bind('block_new_product');
$c->match('/block/pickup_item', '\Eccube\Controller\Block\PickupItemController::index')->bind('block_pickup_item');
を追加。(以下のようになる)
// block
$c->match('/block/category', '\Eccube\Controller\Block\CategoryController::index')->bind('block_category');
$c->match('/block/cart', '\Eccube\Controller\Block\CartController::index')->bind('block_cart');
$c->match('/block/search_product', '\Eccube\Controller\Block\SearchProductController::index')->bind('block_search_product');
$c->match('/block/news', '\Eccube\Controller\Block\NewsController::index')->bind('block_news');
$c->match('/block/login', '\Eccube\Controller\Block\LoginController::index')->bind('block_login');
//以下のコードを追加した
$c->match('/block/pickup_item', '\Eccube\Controller\Block\PickupItemController::index')->bind('block_pickup_item');
⑤そして、すみません、やはりここでどうしても、DBでの操作が必要でした・・・。
僕はmyPHPAdminでDB操作をしたのですが、「dtb_block」というテーブル情報があるので、そこに②で作成した「ピックアップアイテム」というブロックが存在するので、この「logic_id」の情報を「1」にして更新する。
これでようやく、②で作成した「pickup_item.twig」の作成に入れます!
⑥ブロックの編集
/public_html/app/template/default/Block
にある、pickup_item.twigを以下のように編集。
<div class="top_content" id="newitem">
<div class="inner">
<h2>PICK UP</h2>
<div class="itemarea_width">
<ul class="topList01 clearfix">
{% for p in PickupItem | slice(0, 8) %}
<li>
<a href="{{ url('product_detail', {id : p.getId()} ) }}">
<p class="thumb"><img src="{{ app.config.image_save_urlpath }}/{{p.getMainListImage()}}"></p>
<div class="topList_info">
<dt class="item_name">{{p.name}}</dt>
<p class="price">¥{{p.getPrice02IncTaxMax()|number_format}}<span class="small">(+TAX)</span></p>
</div>
</a>
</li>
{% endfor %}
</ul>
</div>
<p class="topBtn"><a href="{{ url('product_list') }}?orderby=2">VIEW ALL</a></p>
</div><!-- /.inner -->
</div><!-- /#newarrivals -->
このコードの
{% for p in PickupItem | slice(0, 8) %}
ここで、④や⑤で紐づけをした、「PickupItem」という配列情報から、8件取得する制御をしている。
これで、ようやくEC-CUBE3に動的なブロックを作成できました。
EC-CUBEは、デフォルトのテンプレートにある「新着商品」というブロックが、性的なブロックとなっており、ここも動的にするカスタマイズをするためには、このように制御をすれば、タグで「NEW」や「新商品」となっている商品を抽出して並べることができる。
もちろんプラグインでも存在するのだが、クラス名などがイケてなくて、デザインのカスタマイズをするために結局工数がかかってしまう。
今回の方法を使用すれば、タグのほかに、特定の商品カテゴリーを抽出して表示するエリアなども作成できるので、かなり使いまわしがきく。