Because We Love Happy Coding

フリーライターからエンジニア × 講師。発信力だけあり余ってる感じ

ECCUBE3のプラグインを開発する

今日もまたコーディング。だって僕らはHappy Codingが大好きだから。

目次

Requirements

プラグインにできること

プラグインは、基本的にはServiceProviderの形で提供される。これは、つまり「きっかけ」があったら「アクション(メソッドを実行)」する、という組み合わせを、$appに登録する、という形になる。「きっかけ」には「HTTPリクエスト」や「フックポイント」が利用できる。

また、サービスの形で処理が「呼ばれる」のを待つこともできる。

大きく分けて3種類のことができる、と言えそうだ。

  • HTTPリクエスト、Routingをきっかけに処理する
  • イベント、フックポイントをきっかけに処理する
  • サービスを提供し、呼び出された時に処理する

これとは別に、インストール作業などを効率よく行うため、インストール時やアンインストール時に処理をさせることもできる。

HTTPリクエスト、Routingをきっかけに処理する

Routing は主にページを表示するために利用される。

PluginのServiceProviderでrouteを登録bind()し、処理を担当するPluginのControllerをひもづける。

イベント、フックポイントをきっかけに処理する

ECCUBE3 では、処理中にフックポイントが発生する。このフックポイントをきっかけに処理をさせることができる。たとえば、「商品が登録されたら」「特定のテンプレートが表示される時」など。

フックポイントを使う場合は以下のようにする。

  • config.ymlに処理を担当するクラスファイルを書く (e.g Foobar.php)
  • event.ymlに利用したいフックポイント名 (e.g eccube.hoge.fuga) を書き、そのタイミングで実行するメソッドをひもづける (e.g onHogeFuga())
  • 処理するクラスファイル内にそのメソッドを書く。(e.g Foobar::onHogeFuga)

こうすることによって、フックポイントが発生したタイミングで、クラスファイルのメソッドが処理されるようになる。

イベントを処理するクラスファイルは基本的には一つだけだが、分割する方法が公式サイトに掲載されている。

サービスを提供し、呼び出された時に処理する

Serviceの本来の使い方として、$appにサービスを提供し、どこか別の処理で呼び出す、ということができる。

インストール時等に処理をする

プラグインマネージャーを作成し、そこで実装する。インストール時に必要なファイルをhtmlディレクトリにコピーしたりできる。

  • インストール時
  • アンインストール時
  • アップデート時

プラグインとして配布する場合には重要だが、手元で開発するだけならあまり必要がない。

プラグイン実装の参考記事

プラグインベストプラクティスとは | EC-CUBE 開発ドキュメント

plugin.pdf

この二つがそこそこ参考になった。

プラグインというのは、いくつかの点を除けば、アプリそのものだ。全体のアプリケーションの小型版みたいなものがプラグインフォルダの中にある。Symfonyの構造そのものだから、Symfonyの機能のどの部分でも置き換える(あるいは追加する)ことができる。

プラグインの実装手順

プラグインコード決める(必須)

ユニークな(他のプラグインとかぶらない)プラグインコードを決める。

app/pluginの中に、そのプラグインコードでディレクトリを作成する。

app/Plugin/{PluginCode}/

config.ymlを設置する(必須)

config.ymlの設置は必須となっている。

app/plugin/プラグインコード/config.ymlプラグイン全体の基本設定を書く。

plugin.pdfの16ページ目に記述すべき内容が書いてある。重要。

name: プラグインの名前
code: SomePluginCode
version: 0.0.1
service:
  - SomePluginServiceProvider

イベントを利用する場合は、eventを追加する。クラスファイルを指定するハイフンと角ブラケットの間には半角スペースが必須。

event:
  - [onSomeEvent, NORMAL]//NORMAL は定数。処理の優先度を決める。

データベースにテーブルを追加する場合には、orm pathの記述が必要。

orm.path:
  - /Resource/doctrine

定数宣言する場合には、constを追加する。

const:
    SOME_CONSTANT: some_value 

定数の利用

アプリケーション内で通用する定数を設定する場合、config.ymlで設定してやる。

プラグインの設定、定義 | EC-CUBE 開発ドキュメント

定数を利用する場合には$appから取り出して使う。

$some_var = $app['config']['プラグインコード']['const']['SOME_CONSTANT'];`

HTTPリクエスト、Routingをきっかけに処理する

HTTPリクエスト、Routingをきっかけに処理をしたい場合、config.ymlにServiceという項目を設ける。

name: プラグインの名前
code: SomePluginCode
version: 0.0.1
service:
  - SomePluginServiceProvider

ここにPHPのファイル名を指定することで、プラグインServiceProvider/配下のPHPSomePluginServiceProvider.phpを呼ぶことができる。

register()メソッドを作り、BaseAplication->match()でルーティングを登録する

  public function register(BaseApplication $app)
  {
    $app->match(
      ' some_route/',
      'Plugin\some_code\Controller\SomePluginController::index'
    )->bind('some_route_name');

    //homepageを置き換える
    $app->match(
      '/',
      'Plugin\SomePlugin\Controller\SomeController::index'
    )->bind('homepage');

    //既存ページの無効化
        $app->match('/help/guide', 'Plugin\SomePlugin\Controller\NotFoundController::index')->bind('help_guide');

    // 自作API URL
    $app->match(
      '/some_api',
      'Plugin\SomePlugin\Controller\APIController::SomeApi'
    )->bind('some_api');

}

イベント、フックポイントをきっかけに処理する

config.ymlにEVENTの項目を追加

イベントやフックポイントをきっかけに処理をしたい場合は、config.ymlにEVENTという項目を追加する。

コロンの後ろに/Plugin/{SomePluginCode}/内のクラス名を記述。このファイルは、event.ymlが捉えたフックポイントすべてを処理することになる。

EVENT : FooBar

event.ymlを作成してフックポイントを登録

config.ymlと同じ階層にevent.ymlを作成し、以下のように記述する。

eccube.some.event :
 - [onSomeEvent, NORMAL]

/Plugin/{SomePluginCode}/FooBar.php内のonSomeEvent(EventArgs $event)が呼ばれるようになる。

config.ymlに書けるイベントPHPファイル(上の例ではFooBar.php)は基本一つだけらしい。複数に分割する方法は公式サイトで解説されている。Serviceに登録しておいて、FooBar.phpから呼び出している。

イベントの肥大化を防ぐ | EC-CUBE 開発ドキュメント

先にEVENTをどう分割するか、方針を決めておいた方がよい。肥大化した時に分割しようとしてもなかなか手が回らない。

イベント | EC-CUBE 開発ドキュメント

フックポイントの種類

フックポイント

ECCUBE3の処理(主にController)の中から、dispatch()されてくるもの。

テンプレートフックポイント

Shopping/index.twigのように、テンプレートを読み込む直前に発生するイベント。以下の3つを取得できる。

  • テンプレートファイル名
  • テンプレートソース($event->getSource()
  • パラメータ($event->getParameters())

共通フックポイント

ECCUBE3の仕様により用意されているもの。

フックポイントの一覧

別のページにて紹介する予定。

サービスを提供する

アプリケーション内で使われる共通機能は、Serviceとして$appに登録すると便利だ。

比較的大きなプラグインでは、こうしたServiceを使った方がいい場合もあるだろう。

Service を提供するだけのアプリというのは想像しづらい。どこからも呼ばれなければ意味がない。複数のアプリで連携するような場合ならあるのかもしれない。

Service を提供する場合は、config.ymlにServiceという項目を追加する。

ここにPHPのファイル名を指定することで、プラグインServiceProvicer/配下のPHPSomePluginServiceProvider.phpを呼ぶことができる。

name: プラグインの名前
code: SomePluginCode
version: 0.0.1
service:
  - SomePluginServiceProvider

register() メソッドの中で、$appに登録する。

public function register(BaseApplication $app)
{

    // FormType
    $app['form.type.extensions'] = $app->share($app->extend('form.type.extensions', function ($types) use ($app) {
        $types[] = new \Plugin\SomePlugin\Form\Extension\AddressTypeExtension();
        return $types;
    }));

    // Repository
    $app['plugin.SomePlugin.repository.some_entity'] = $app->share(function () use ($app) {
        return $app['orm.em']->getRepository('Plugin\SomePlugin\Entity\SomeEntity');
    });
}

詳細は仕様書を確認。

プラグインのインストール時や更新時の処理を定義する

主にプラグイン配布をする場合に使われる。

app/plugin/の外にファイルをコピーしたいような時に利用する。

参考記事