[EC-CUBE] 3.0.14
[開発サーバ] xampp Apache/2.4.25
[OS] Windows7
[PHP] 5.6.30
[データベース] mysql 4.6.5.2
===================================
教えてください。上記の環境で独自プラグインを開発中の者です。
商品登録時に店舗独自の項目を追加するためのプラグインを開発しています。
プラグインチュートリアルを参考に似たようなプログラムを書いています。
→プラグインチュートリアル:
http://doc.ec-cube.net/plugin_tutorial必須ファイルを作成し、テーブルを作成し、管理画面にフォームを追加するところまでは上手くいきましたが、フォームの情報をエンティティから初期入力したり(onAdminProductEditInit)、フォームの情報をデータベースに保存したり(onAdminProductEditComplete)する処理を書いている時に、どこかいじってしまったのか、既存商品編集のページ[管理トップ>商品管理>商品マスター>商品検索>商品クリック]がエラーで表示されなくなってしまいました。(商品新規登録[管理画面トップ>商品管理>商品登録]の画面は表示されます。)
またプラグインを一度アンインストールして、コマンドラインから再度インストールしてみたのですが、プラグイン有効化時にエラーがでます。
■プラグインインストール時のコンソールエラー■
[インストールはうまくいく]
$ php app/console plugin:develop install --code KaitekiProductDetailExtension
success
[有効化時にエラー]
$ php app/console plugin:develop enable --code KaitekiProductDetailExtension
[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'Plugin\KaitekiProductDetailExtension\Entity\KaitekiProductDetail
Extension' was not found in the chain configured namespaces Eccube\Entity,
Plugin\CartAnalytics\Entity, Plugin\CategoryContent\Entity, Plugin\CheckedI
tem\Entity, Plugin\ChgOrderStatus\Entity, Plugin\ContactList\Entity, Plugin
\ContactMailConfig\Entity, Plugin\EccubeApi\Entity, Plugin\GSFeed\Entity, P
lugin\GmoPaymentGateway\Entity, Plugin\MailMagazine\Entity, Plugin\Nissen\E
ntity, Plugin\ProductReview\Entity, Plugin\RegisterWhileShopping\Entity, Pl
ugin\RelatedProduct\Entity, Plugin\Ryfety\Entity, Plugin\SalesRanking\Entit
y, Plugin\Shiro8Welcome3\Entity, Plugin\SimpleSiteMaintenance\Entity, Plugi
n\SiteMap\Entity, Plugin\SortProduct\Entity
plugin:develop [--path [PATH]] [--code [CODE]] [--uninstall-force [UNINSTALL-FOR
CE]] [--] <mode>
[しかしもう一度有効化を試みると成功する]
$ php app/console plugin:develop enable --code KaitekiProductDetailExtension
success
■DEVモードで商品編集ページを開いた時のPHPエラー■
Whoops, looks like something went wrong.
1/1
InvalidArgumentException in Pimple.php line 78:
Identifier "kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension" is not defined.
in Pimple.php line 78
at Pimple->offsetGet('kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension') in Event.php line 28
at Event->onAdminProductEditInit(object(EventArgs), 'admin.product.edit.initialize', object(EventDispatcher))
at call_user_func(array(object(Event), 'onAdminProductEditInit'), object(EventArgs), 'admin.product.edit.initialize', object(EventDispatcher)) in EventDispatcher.php line 161
at EventDispatcher->doDispatch(array(array(object(Event), 'onRenderAdminProductInit'), array(object(Event), 'onAdminProductEditInit')), 'admin.product.edit.initialize', object(EventArgs)) in EventDispatcher.php line 46
at EventDispatcher->dispatch('admin.product.edit.initialize', object(EventArgs)) in ProductController.php line 277
at ProductController->edit(object(Application), object(Request), '3')
at call_user_func_array(array(object(ProductController), 'edit'), array(object(Application), object(Request), '3')) in HttpKernel.php line 144
at HttpKernel->handleRaw(object(Request), '1') in HttpKernel.php line 64
at HttpKernel->handle(object(Request), '1', true) in Application.php line 586
at Application->handle(object(Request)) in Application.php line 563
at Application->run() in index_dev.php line 103
■プラグインのファイル/フォルダ構成■
app/Plugin/KaitekiProductDetailExtension
┣ Entity
┃ ┗ KaitekiProductDetailExtension.php
┣ Repository
┃ ┗ KaitekiProductDetailExtensionRepository.php
┣ Resource
┃ ┃┗ doctorine
┃ ┃ ┗ migration
┃ ┃ ┗ Version20170606212700.php
┃ ┗ Plugin.KaitekiProductDetailExtension.Entity.KaitekiProductDetailExtension.dcm.yml
┣ ServiceProvider
┃ ┗ KaitekiProductDetailExtensionServiceProvider.php
┣ config.yml
┣ Event.php
┣ event.yml
┗ PluginManager.php
■プラグインの全ソースコード■
config.yml
name: 快適商品詳細ページ拡張項目
code: KaitekiProductDetailExtension
version: 1.0.1
orm.path:
- /Resource/doctrine
event: Event
servcie:
- KaitekiProductDetailExtensionServiceProvider
PluginManager.php
<?php
namespace Plugin\KaitekiProductDetailExtension;
use Eccube\Plugin\AbstractPluginManager;
class PluginManager extends AbstractPluginManager
{
public function install($config, $app)
{
}
public function uninstall($config, $app)
{
$this->migrationSchema($app, __DIR__.'/Resource/doctrine/migration', $config['code'], 0);
}
public function enable($config, $app)
{
$this->migrationSchema($app, __DIR__.'/Resource/doctrine/migration', $config['code']);
}
public function disable($config, $app)
{
}
public function update($config, $app)
{
}
}
event.yml
admin.product.edit.initialize:
- [onAdminProductEditInit, NORMAL]
admin.product.edit.complete:
- [onAdminProductEditComplete, NORMAL]
Event.php
<?php
namespace Plugin\KaitekiProductDetailExtension;
use Eccube\Event\EventArgs;
use Plugin\KaitekiProductDetailExtension\Entity\KaitekiProductDetailExtension;
class Event
{
/** @var \Eccube\Application $app */
private $app;
public function __construct($app)
{
$this->app = $app;
}
public function onAdminProductEditInit(EventArgs $event)
{
$product = $event->getArgument('Product');
$id = $product->getId();
$ExtraForms = null;
// IDの有無で登録か編集かを判断
if ($id) {
// アイテム編集時は初期値を取得
$ExtraForms = $this->app['kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension']->find($id);
}
// アイテム新規登録またはコンテンツが未登録の場合
if (is_null($ExtraForms)) {
$ExtraForms = new KaitekiProductDetailExtension();
}
// フォームの追加
/** @var FormInterface $builder */
// FormBuildeの取得
$builder = $event->getArgument('builder');
// 項目の追加
$builder->add(
'plg_kaiteki_product_detail_extension_base_shipping_fee',
'integer',
array(
'required' => true,
'label' => '基本送料',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_hokkaido_shipping_fee',
'integer',
array(
'required' => true,
'label' => '北海道送料',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_okinawa_ritou_shipping_fee',
'integer',
array(
'required' => true,
'label' => '沖縄、離島送料',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_is_guaranteed',
'checkbox',
array(
'required' => true,
'label' => '3ヶ月保障',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_is_need_construct',
'checkbox',
array(
'required' => true,
'label' => '組立商品',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_is_large_product',
'checkbox',
array(
'required' => true,
'label' => '大型商品',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_has_bed_tana',
'checkbox',
array(
'required' => true,
'label' => '棚付ベッド',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_has_bed_outlet',
'checkbox',
array(
'required' => true,
'label' => 'コンセント付ベッド',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_has_bed_light',
'checkbox',
array(
'required' => true,
'label' => '照明付ベッド',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_has_bed_matless',
'checkbox',
array(
'required' => true,
'label' => 'マットレス付ベッド',
'mapped' => false,
)
);
$builder->add(
'plg_kaiteki_product_detail_extension_can_not_discount',
'checkbox',
array(
'required' => true,
'label' => '値引き不可',
'mapped' => false,
)
);
// 初期値を設定
$builder->get('plg_kaiteki_product_detail_extension_base_shipping_fee')->setData($ExtraForms->getBaseShippingFee());
$builder->get('plg_kaiteki_product_detail_extension_hokkaido_shipping_fee')->setData($ExtraForms->getHokkaidoShippingFee());
$builder->get('plg_kaiteki_product_detail_extension_okinawa_ritou_shipping_fee')->setData($ExtraForms->getOkinawaRitouShippingFee());
$builder->get('plg_kaiteki_product_detail_extension_is_guaranteed')->setData($ExtraForms->isGuaranteed());
$builder->get('plg_kaiteki_product_detail_extension_is_need_construct')->setData($ExtraForms->isNeedConstruct());
$builder->get('plg_kaiteki_product_detail_extension_is_large_product')->setData($ExtraForms->isLargeProduct());
$builder->get('plg_kaiteki_product_detail_extension_has_bed_tana')->setData($ExtraForms->hasBedTana());
$builder->get('plg_kaiteki_product_detail_extension_has_bed_outlet')->setData($ExtraForms->hasBedOutlet());
$builder->get('plg_kaiteki_product_detail_extension_has_bed_light')->setData($ExtraForms->hasBedLight());
$builder->get('plg_kaiteki_product_detail_extension_has_bed_matless')->setData($ExtraForms->hasBedMatless());
$builder->get('plg_kaiteki_product_detail_extension_can_not_discount')->setData($ExtraForms->canNotDiscount());
}
/**
* 管理画面:商品登録画面で、登録処理を行う.
*
* @param EventArgs $event
*/
public function onAdminProductEditComplete(EventArgs $event)
{
/** @var Application $app */
$app = $this->app;
/** @var Product $product */
$product = $event->getArgument('Product');
/** @var FormInterface $form */
$form = $event->getArgument('form');
// 現在のエンティティを取得
$id = $product->getId();
// 商品IDをもとに拡張フォームの値を取得
$ExtraForms = $app['kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension']->find($id);
if (is_null($ExtraForms)) {
$ExtraForms = new KaitekiProductDetailExtension();
}
// エンティティを更新
$ExtraForms
->setId($id)
->setContent($form['plg_kaiteki_product_detail_extension_base_shipping_fee']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_hokkaido_shipping_fee']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_okinawa_ritou_shipping_fee']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_is_guaranteed']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_is_need_construct']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_is_large_product']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_has_bed_tana']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_has_bed_outlet']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_has_bed_light']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_has_bed_matless']->getData())
->setContent($form['plg_kaiteki_product_detail_extension_can_not_discount']->getData());
// DB更新
$app['orm.em']->persist($ExtraForms);
$app['orm.em']->flush($ExtraForms);
}
}
Entity/KaitekiProductDetailExtension.php
<?php
namespace Plugin\KaitekiProductDetailExtension\Entity;
use Eccube\Entity\AbstractEntity;
/**
* Class KaitekiProductDetailExtension.
*/
class KaitekiProductDetailExtension extends AbstractEntity
{
private $id;
private $is_guaranteed;
private $is_need_construct;
private $is_large_product;
private $has_bed_tana;
private $has_bed_outlet;
private $has_bed_light;
private $has_bed_matless;
private $can_not_discount;
private $base_shipping_fee;
private $hokkaido_shipping_fee;
private $okinawa_ritou_shipping_fee;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function isGuaranteed()
{
return $this->is_guaranteed;
}
public function setIsGuaranteed($flag)
{
$this->is_guaranteed = $flag;
return $this;
}
public function isNeedConstruct()
{
return $this->is_need_construct;
}
public function setIsNeedConstruct($flag)
{
$this->is_need_construct = $flag;
return $this;
}
public function isLargeProduct()
{
return $this->is_large_product;
}
public function setIsLargeProduct($flag)
{
$this->is_large_product = $flag;
return $this;
}
public function hasBedTana()
{
return $this->has_bed_tana;
}
public function setHasBedTana($flag)
{
$this->has_bed_tana = $flag;
return $this;
}
public function hasBedOutlet()
{
return $this->has_bed_outlet;
}
public function setHasBedOutlet($flag)
{
$this->has_bed_outlet = $flag;
return $this;
}
public function hasBedLight()
{
return $this->has_bed_light;
}
public function setHasBedLight($flag)
{
$this->has_bed_light = $flag;
return $this;
}
public function hasBedMatless()
{
return $this->has_bed_matless;
}
public function setHasBedMatless($flag)
{
$this->has_bed_matless = $flag;
return $this;
}
public function canNotDiscount()
{
return $this->can_not_discount;
}
public function setCanNotDiscount($flag)
{
$this->can_not_discount = $flag;
return $this;
}
public function getBaseShippingFee()
{
return $this->base_shipping_fee;
}
public function setBaseShippingFee($fee)
{
$this->base_shipping_fee = $fee;
return $this;
}
public function getHokkaidoShippingFee()
{
return $this->hokkaido_shipping_fee;
}
public function setHokkaidoShippingFee($fee)
{
$this->hokkaido_shipping_fee = $fee;
return $this;
}
public function getOkinawaRitouShippingFee()
{
return $this->okinawa_ritou_shipping_fee;
}
public function setOkinawaRitouShippingFee($fee)
{
$this->okinawa_ritou_shipping_fee = $fee;
return $this;
}
}
Repository/KaitekiProductDetailExtensionRepository.php
<?php
namespace Plugin\KaitekiProductDetailExtension\Repository;
use Doctrine\ORM\EntityRepository;
/**
* Class KaitekiProductDetailExtensionRepository.
*/
class KaitekiProductDetailExtensionRepository extends EntityRepository
{
}
Resource/doctrine/Plugin.KaitekiProductDetailExtension.Entity.KaitekiProductDetailExtension.dcm.yml
Plugin\KaitekiProductDetailExtension\Entity\KaitekiProductDetailExtension:
type: entity
table: plg_kaiteki_product_detail_extension
repositoryClass: Plugin\KaitekiProductDetailExtension\Repository\KaitekiProductDetailExtensionRepository
id:
id:
type: integer
nullable: false
options:
unsigned: false
id: true
column: product_id
generator:
strategy: NONE
fields:
is_guaranteed:
type: boolean
nullable: false
is_need_construct:
type: boolean
nullable: false
is_large_product:
type: boolean
nullable: false
has_bed_tana:
type: boolean
nullable: false
has_bed_outlet:
type: boolean
nullable: false
has_bed_light:
type: boolean
nullable: false
has_bed_matless:
type: boolean
nullable: false
can_not_discount:
type: boolean
nullable: false
base_shipping_fee:
type: integer
nullable: true
hokkaido_shipping_fee:
type: integer
nullable: true
okinawa_ritou_shipping_fee:
type: integer
nullable: true
lifecycleCallbacks: { }
Resource/doctrine/migration/Version20170606212700.php
<?php
namespace DoctrineMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\SchemaTool;
use Eccube\Common\Constant;
class Version20170606212700 extends AbstractMigration
{
// 対象のエンティティを指定
protected $entities = array(
'Plugin\KaitekiProductDetailExtension\Entity\KaitekiProductDetailExtension',
);
public function up(Schema $schema)
{
// テーブルの生成
$app = \Eccube\Application::getInstance();
$meta = $this->getMetadata($app['orm.em']);
$tool = new SchemaTool($app['orm.em']);
$tool->createSchema($meta);
}
public function down(Schema $schema)
{
$app = \Eccube\Application::getInstance();
$meta = $this->getMetadata($app['orm.em']);
$tool = new SchemaTool($app['orm.em']);
$schemaFromMetadata = $tool->getSchemaFromMetadata($meta);
// テーブル削除
foreach ($schemaFromMetadata->getTables() as $table) {
if ($schema->hasTable($table->getName())) {
$schema->dropTable($table->getName());
}
}
// シーケンス削除
foreach ($schemaFromMetadata->getSequences() as $sequence) {
if ($schema->hasSequence($sequence->getName())) {
$schema->dropSequence($sequence->getName());
}
}
}
protected function getMetadata(EntityManager $em)
{
$meta = array();
foreach ($this->entities as $entity) {
$meta[] = $em->getMetadataFactory()->getMetadataFor($entity);
}
return $meta;
}
}
ServiceProvider/KaitekiProductDetailExtensionServiceProvider.php
<?php
namespace Plugin\KaitekiProductDetailExtension\ServiceProvider;
use Eccube\Application;
use Silex\Application as BaseApplication;
use Silex\ServiceProviderInterface;
class KaitekiProductDetailExtensionServiceProvider implements ServiceProviderInterface
{
public function register(BaseApplication $app)
{
// Repository
$app['kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension'] = $app->share(function () use ($app) {
return $app['orm.em']->getRepository('Plugin\KaitekiProductDetailExtension\Entity\KaitekiProductDetailExtension');
});
}
public function boot(BaseApplication $app)
{
}
}
DEVモードのエラーメッセージから推測すると、Event.phpの、
$ExtraForms = $this->app['kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension']->find($id);
の部分で、$app['kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension']のキーが$appに登録されていないので見つからないのが原因かと思っています。
またプラグイン有効化時にもエラーがでますので、恐らくServiceProviderがうまく動いていないので、$appに['kaiteki_product_detail_extension.repository.kaiteki_product_detail_extension']が登録できていないのではないか・・・?
と推測できますが、どこをどう修正すれば良いのかわかりません。
どなたかお分かりになる方いらっしゃいましたら、ご教授いただけませんでしょうか。
よろしくお願いいたします。