メモ > 技術 > CMS: ECCube > プラグインの作成
プラグインの作成
■プラグインでページを作成
$ php bin/console eccube:plugin:generate
EC-CUBE Plugin Generator Interactive Wizard
===========================================
name [EC-CUBE Sample Plugin]:
> サンプルページプラグイン
code [Sample]:
> SamplePage
ver [1.0.0]:
> 1.0.0
[OK] Plugin was successfully created: サンプルページプラグイン SamplePage 1.0.0
以下の場所にプラグインの雛形が作成される。
html\app\Plugin\SamplePage
ページ表示用にファイルを作成する。
html\app\Plugin\SamplePage\Controller\SampleController.php
<?php
namespace Plugin\SamplePage\Controller;
use Eccube\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Routing\Annotation\Route;
class SampleController extends AbstractController
{
/**
* @Route("sample", name="sample")
* @Template("@SamplePage/default/index.twig")
*/
public function index()
{
return [];
}
}
html\app\Plugin\SamplePage\Resource\template\default\index.twig
{% extends 'default_frame.twig' %}
{% block main %}
<p>サンプルページです</p>
{% endblock %}
以下のコマンドでプラグインをインストールできる。
プラグインファイルをリポジトリに含めていたとしても、インストールコマンドの実行は必要。
$ php bin/console eccube:plugin:install --code=SamplePage
管理画面の「プラグイン → プラグイン一覧」の「ユーザー独自プラグイン」に、作成したプラグインが表示される。(上記コマンドを実行して初めて表示される。)
一覧に表示されている三角の「有効化」ボタンで、プラグインを有効化できる。
もしくは、以下のコマンドでプラグインを有効化することもできる。
$ php bin/console eccube:plugin:enable --code=SamplePage
プラグインを有効化すると、以下でプラグインによって作成されたページを表示できる。
ただしこの時点では、他ページのようなヘッダとフッタは表示されない。
http://eccube4.local/sample
一覧に表示されている四角2つの「無効化」ボタンで、プラグインを有効化できる。
もしくは、以下のコマンドでプラグインを無効化することができる。
$ php bin/console eccube:plugin:disable --code=SamplePage
以下のコマンドでプラグインをアンインストールできる。
アンインストール後、念のためキャッシュを削除しておく。
$ php bin/console eccube:plugin:uninstall --code=SamplePage
$ php bin/console cache:clear --no-warmup
■プラグインで作成したページにヘッダとフッタを表示
引き続き、プラグインの有効化時にページとレイアウトに関する情報がデータベースに登録されるようにする。
以下のファイルを作成する。
このファイルはプラグインの有効化・無効化時に実行されるので、ここにページレイアウト登録のためのプログラムを記述する。
html\app\Plugin\SamplePage\PluginManager.php
<?php
namespace Plugin\SamplePage;
use Eccube\Entity\PageLayout;
use Eccube\Plugin\AbstractPluginManager;
use Eccube\Repository\LayoutRepository;
use Eccube\Repository\PageLayoutRepository;
use Eccube\Repository\PageRepository;
use Symfony\Component\DependencyInjection\ContainerInterface;
class PluginManager extends AbstractPluginManager
{
// 1: トップページ用レイアウト, 2:下層ページ用レイアウト
const ADD_PAGE_LAYOUT_ID = 2;
// ページ設定
const ADD_PAGE_NAME = "サンプルページ";
const ADD_PAGE_URL = "sample";
const ADD_PAGE_FILE_NAME = "SamplePage/Resource/template/default/index";
const ADD_PAGE_META_ROBOTS = "noindex"; // or null
// 0: Controller不要, 2: Controller必要
const ADD_PAGE_EDIT_TYPE = 2;
/**
* プラグイン有効化時に走る
* @param array $meta
* @param ContainerInterface $container
*/
public function enable(array $meta, ContainerInterface $container) {
$this->createPage($container);
}
/**
* プラグイン無効化時・アンインストール時に走る
* @param array $meta
* @param ContainerInterface $container
*/
public function disable(array $meta, ContainerInterface $container) {
$this->deletePage($container);
}
/**
* ページ情報を挿入する dtb_page, dtb_page_layout
* @param ContainerInterface $container
*/
private function createPage(ContainerInterface $container) {
// dtb_page に存在しないことを確認する
$pageRepository = $container->get(PageRepository::class);
$pageFindResult = $pageRepository->findOneBy(["url" => $this::ADD_PAGE_URL]);
if (is_null($pageFindResult) == false) return;
// dtb_layout から下層ページ用レイアウトを取得する
$layoutRepository = $container->get(LayoutRepository::class);
$underLayout = $layoutRepository->findOneBy(["id" => $this::ADD_PAGE_LAYOUT_ID]);
// dtb_page_layout の次のSortNoを取得する
$pageLayoutRepository = $container->get(PageLayoutRepository::class);
$LastPageLayout = $pageLayoutRepository->findOneBy([], ['sort_no' => 'DESC']);
$nextSortNo = $LastPageLayout->getSortNo() + 1;
// EntityManager準備
$em = $container->get('doctrine.orm.entity_manager');
$em->beginTransaction();
// INSERT INTO dtb_page
$page = $pageRepository->newPage();
$page->setName($this::ADD_PAGE_NAME)
->setUrl($this::ADD_PAGE_URL)
->setFileName($this::ADD_PAGE_FILE_NAME)
->setEditType($this::ADD_PAGE_EDIT_TYPE)
->setMetaRobots($this::ADD_PAGE_META_ROBOTS);
$em->persist($page);
$em->flush($page);
// INSERT INTO dtb_page_layout
$pageLayout = new PageLayout();
$pageLayout->setLayout($underLayout)
->setLayoutId($underLayout->getId())
->setPageId($page->getId())
->setSortNo($nextSortNo)
->setPage($page);
$em->persist($pageLayout);
$em->flush($pageLayout);
$em->commit();
}
/**
* ページ情報を削除 dtb_page, dtb_page_layout
* @param ContainerInterface $container
*/
private function deletePage(ContainerInterface $container) {
// dtb_page に存在することを確認する
$pageRepository = $container->get(PageRepository::class);
$page = $pageRepository->findOneBy(["url" => $this::ADD_PAGE_URL]);
if (is_null($page)) return;
// EntityManager準備
$em = $container->get('doctrine.orm.entity_manager');
$em->beginTransaction();
// DELETE FROM dtb_page WHERE インストール時にINSERTしたページ
$em->remove($page);
$em->flush($page);
// DELETE FROM dtb_page_layout WHERE インストール時にINSERTしたページレイアウト
$pageLayoutRepository = $container->get(PageLayoutRepository::class);
$pageLayout = $pageLayoutRepository->findOneBy(["page_id" => $page->getId()]);
if(is_null($pageLayout) === false){
$em->remove($pageLayout);
$em->flush($pageLayout);
}
$em->commit();
}
}
プラグインを無効化し、再度有効化する。
これによって、上記で作成したファイルの内容が実行される。
$ php bin/console eccube:plugin:disable --code=SamplePage
$ php bin/console eccube:plugin:enable --code=SamplePage
以下を再読込すると、ヘッダやフッタが表示されている。
http://eccube4.local/sample
[EC-CUBE4] ヘッダー・フッター付きの新規ページを作成する方法→プラグイン化 - Qiita
https://qiita.com/seiyaan/items/382e3d2107ca859c38ad
■プラグインで作成したページに商品情報を表示
html\app\Plugin\SamplePage\Controller\SampleController.php
<?php
namespace Plugin\SamplePage\Controller;
use Eccube\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Routing\Annotation\Route;
use Eccube\Repository\ProductRepository;
class SampleController extends AbstractController
{
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* ProductController constructor.
*
* @param ProductRepository $productRepository
*/
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* @Route("sample", name="sample")
* @Template("@SamplePage/default/index.twig")
*/
public function index()
{
$Products = $this->productRepository->findAll();
return [
'Products' => $Products,
];
}
}
html\app\Plugin\SamplePage\Resource\template\default\index.twig
{% extends 'default_frame.twig' %}
{% block main %}
<p>サンプルページです</p>
<ul>
{% for Product in Products %}
<li>
{{ Product.id }}
/
{{ Product.name }}
/
{{ Product.create_date|date('Y-m-d H:i:s') }}
</li>
{% endfor %}
</ul>
{% endblock %}
■プラグインで作成したページに独自に追加したテーブルの内容を表示
html\app\Plugin\SamplePage\Controller\SampleController.php
<?php
namespace Plugin\SamplePage\Controller;
use Eccube\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Routing\Annotation\Route;
use Customize\Repository\ContactRepository;
class SampleController extends AbstractController
{
/**
* @var ContactRepository
*/
protected $contactRepository;
/**
* ContactController constructor.
*
* @param ContactRepository $contactRepository
*/
public function __construct(
ContactRepository $contactRepository
) {
$this->contactRepository = $contactRepository;
}
/**
* @Route("sample", name="sample")
* @Template("@SamplePage/default/index.twig")
*/
public function index()
{
$Contacts = $this->contactRepository->findAll();
return [
'Contacts' => $Contacts,
];
}
}
html\app\Plugin\SamplePage\Resource\template\default\index.twig
{% extends 'default_frame.twig' %}
{% block main %}
<p>サンプルページです</p>
<ul>
{% for Contact in Contacts %}
<li>
{{ Contact.id }}
/
{{ Contact.name01 }} {{ Contact.name02 }}
/
{{ Contact.kana01 }} {{ Contact.kana02 }}
/
{{ Contact.email }}
/
{{ Contact.create_date|date('Y-m-d H:i:s') }}
</li>
{% endfor %}
</ul>
{% endblock %}
■既存ページに情報を表示
データの表示はEvent経由で行う必要があるみたい。
以下が参考になりそう。
EC-CUBE4系のプラグインを開発してみた - Qiita
https://qiita.com/yoshiharu-semachi/items/03817d6dd883b000348f
以下、実際に試したメモ。
プラグイン一覧 → サンプルページプラグイン → 設定
で「名前」に「テスト」と登録しておく。
以下にEntityが作成されていることを確認する。
app\Plugin\SamplePage\Entity\Config.php
以下にRepositoryが作成されていることを確認する。
app\Plugin\SamplePage\Repository\ConfigRepository.php
以下にFormが作成されていることを確認する。(管理画面のフォームに項目を追加するためのもの?要確認。)
app\Plugin\SamplePage\Form\Type\Admin\ConfigType.php
以下にControllerが作成されていることを確認する。
app\Plugin\SamplePage\Controller\Admin\ConfigController.php
以下にEventが作成されていることを確認する。
app\Plugin\SamplePage\Event.php
Event.php の内容を以下のように編集する。
<?php
namespace Plugin\SamplePage;
use Eccube\Event\TemplateEvent;
use Plugin\SamplePage\Repository\ConfigRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class Event implements EventSubscriberInterface
{
/**
* @var ConfigRepository
*/
protected $ConfigRepository;
/**
* ProductReview constructor.
*
* @param ConfigRepository $ConfigRepository
*/
public function __construct(ConfigRepository $ConfigRepository)
{
$this->ConfigRepository = $ConfigRepository;
}
/**
* 配列のキーはイベント名、値は呼び出すメソッド名です。
*
* @return array
*/
public static function getSubscribedEvents()
{
return [
'Product/detail.twig' => 'StockShowTwig',
];
}
/**
* @param TemplateEvent $event
*/
public function StockShowTwig(TemplateEvent $event)
{
$twig = '@SamplePage/default/Product/stock_show.twig';
// addSnippet()関数で指定したテンプレートを<body>タグの下部に追加できます。
$event->addSnippet($twig);
$Config = $this->ConfigRepository->get();
$parameters = $event->getParameters();
$parameters['pluginName'] = $Config->getName();
$event->setParameters($parameters);
}
}
以下のファイルを作成する。
app\Plugin\SamplePage\Resource\template\default\Product\stock_show.twig
{# Style #}
<style type="text/css">
#stock_show_area {
padding: 0 0 14px 0;
border-bottom: 1px dotted #ccc;
}
#stock_show_area p {
font-size: 18px;
}
</style>
<script>
{# JQueryのinsertAfterメソッドを使いProduct/detail.twigの<div class="ec-productRole__tags">の直後に挿入 #}
$(function() {
$('#stock_show_area').insertAfter($('.ec-productRole__tags'));
});
</script>
{# 規格あり商品の場合 #}
{% if Product.hasProductClass %}
{# 規格なし商品の場合 #}
{% else %}
{% if Product.getStockMin > 0 and Product.getStockMin <= 100 %}
<div id="stock_show_area">
<p>残り {{ Product.getStockMin }} 点です。ご注文はお早めに! by {{ pluginName }}</p>
</div>
{% endif %}
{% endif %}
これで完成。商品在庫数が100個以下なら、商品詳細ページに「ご注文はお早めに!!」のメッセージが表示される。
表示されなければキャッシュを削除する。
※引き続き、登録項目の追加を試したい。
「残り○点です」の基準値を管理画面から登録できるようにして、それをもとに画面に表示できるようにしたい。
■その他
未検証だが、以下も参考になりそう。
EC-CUBE 4 でお問い合わせプラグインを作ってみた | freks blog
https://blog.freks.jp/eccube4-plugin/
EC-CUBE4 独自プラグイン開発 ?独自プラグイン開発Tips - Qiita
https://qiita.com/haruna-nagayoshi/items/27108c75eaf9511f3524