baserCMSのプラグイン作り(イベント処理)を楽しんでみましょー。

先日、baserCMS3系用 Keywordプラグイン2.0.0をリリースしました。
baserCMS2系 → 3系では、コアとなるフレームワークであるCakePHPが、1系から2系に切り替わってまして、その対応が目的でした。

それに伴い、baserCMSのこれまでのフック処理は、Cakeイベントへと切り替わったので、作成した内容をもとにちょっと紹介しようと思います。

プラグイン開発について | baser CMS - 国産オープンソース!フリー(無料)で『コーポレートサイトにちょうどいいCMS』

baserCMSのプラグインを作成するということは?

プラグインでできる事は相当多岐に渡ります。
例えば、キーワード・プラグインではブログ記事と固定ページに任意の入力欄を追加して、コンテンツ専用のキーワード設定を可能にしています。

管理システム側に入力欄を追加すること自体は、baserCMSのコア側に手を入れることでももちろん可能なのですが、それを行ってしまうと、次バージョンアップ時のメンテナンスが少しメンドーなことになってしまいます。
なぜメンドーなことになるかというと、基本的にbaserCMSのバージョンアップは、コアの本体ファイルを上書きすることで行うため、バージョンアップ時に再度、自身で手を入れた箇所を記述し直す事になってしまうからです。

そうした手間を回避するひとつの手段として、カスタマイズ部分をプラグインを利用して実装し、提供する、ということが挙げられます。
baserCMSのプラグインは、所定の場所にファイルをアップロードして、管理システム側よりそのプラグインを有効化するだけで使えるようにできてます。
ということは、必要な機能をプラグインとしてまとめておくことで、くっつけたり切り離したりが自由に行えることになります。

本体側の仕様変更に対応する必要のある場面は出てくる可能性がありますが、作成したプラグインのメンテナンスだけで済む、というのはラクな感じです。

どうやってプラグイン側から本体側の表示や動作を変えてるの?

というワケで、具体的にどんな感じで動作を作るのかを見ていく事にします。
先ず、baserCMS には「プラグインイベント」という仕組みが備わってます。

これは、CakePHPが備えているCakeEventを、baserCMS側にて拡張しているBaserEventに当たります。

このイベントを利用することで、任意の箇所で任意の処理を挟み込む、といったことができるようになります。
例えば、動作の流れが1(開始)から10(終了)まである場合に、
1,2,3,4,5・・・ここで任意の処理を挟み込む・・・6,7,8,9,10
といったことをするような感じになります。

この「任意の処理」が行える場所は決まっていて、例えば、固定ページやブログ記事の表示を行う直前・直後のタイミング、記事を編集した直前・直後のタイミング、メールを送信する直前のタイミング・・・などが挙げられます。

動作作成例としてキーワード・プラグインを用いて紹介

では具体的にどうするのか、github にて公開中のキーワード・プラグインを例にして見てみましょう。
baserCMS3系用 Keywordプラグイン2.0.0 リリース
materializing/keyword

sc_keyword_plugin

固定ページ・ブログ記事編集画面にキーワード用の入力欄を追加する

keyword/Event/KeywordHelperEventListener.php at master · materializing/keyword
ここでは、管理システム側の固定ページとブログ記事編集画面で、キーワードの入力欄を追加してます。
※2系では以下に当たります。
keyword/views/helpers/keyword_hook.php at 1.3.1 · materializing/keyword

ここではプラグインイベントの1つである「Form.afterInput」を使ってます。
Form.afterInput は、フォーム表示を行う際の入力欄を判別し、その任意の入力欄の後ろ側に処理を挟み込む事ができるイベントです。

追加したい入力欄をビューとして用意しておいて、それを表示させるようにすると良さそうです。

2系時のフック処理のように、引っ掛けるポイントの指定が必要になるのですが、この箇所が、$registerHooks から $events に変更されてます。
名称も「afterFormInput」から「Form.afterInput」に変更となってる点が注意点です。
また、引数の数も変更となり1つで済むようになりました。
この $event から様々な情報をまとめて取得できるようになってます。

Form.afterInput では、フォームの表示内容を戻り値として返す必要があります。
そこで、取得できる内容に、用意しているプラグイン側のエレメント(ビューの部品)を追加して表示させているのです。
keyword/View/Elements/admin/keyword_form.php at master · materializing/keyword

キーワード入力欄に入力された内容を保存

keyword/Event/KeywordModelEventListener.php at master · materializing/keyword
次に、キーワード入力欄に入力された内容を保存する必要があります。
イベントのタイミングとしては、追加保存や編集保存のタイミングになるので、イベントとしては afterSave 辺りが良さそうです。
※2系では以下に当たります。
keyword/models/behaviors/keyword_hook.php at 1.3.1 · materializing/keyword

2系時は、それぞれのフックポイントを配列形式で記述する規則だったのですが、イベント指定の記述規則は、{プラグイン名}.{モデル名}.{イベント名} となります。

キーワード・プラグインでは、固定ページとブログ記事の2つのモデルに対応する機能のため、save() する更に直前でデータを整形するメソッドを挟んでます。
Model->save() 辺りの処理は通常の CakePHP と同じ扱いなので割愛します。

他にも、このモデルイベントでは beforeValidate や beforeFind を利用することで、データのチェックや取得を行ってます。

2系時の内容よりメソッドが増えて複雑化してるように見えますが、処理の内容はほぼ同じです。
フック → イベントへの切り替わりに際して、イベントの命名規則が変わり、それに伴う対応となります。

キーワード入力欄に保存した内容を削除する

keyword/Event/KeywordModelEventListener.php at master · materializing/keyword
次に、保存されているキーワード情報を削除する場面を考えてみます。
ある記事を削除した際には、そこに紐付けているキーワード情報も削除して良さそうです。
タイミングとしては、データの削除に当るので「afterDelete」が適切そうです。

登録するイベント名では、{モデル名}.{イベント名} とする事でイベントの発動箇所を、特定のモデルの際に絞り込んでおく事ができます。
プラグインに対して指定する場合は {プラグイン名}.{モデル名}.{イベント名} となります。

処理の中身自体は、通常の CakePHP と同様の処理になるので割愛します。
afterDelete を使えば、任意のデータを削除するタイミングで、関連データの削除やその他の自由な処理を行う事ができる、という点がポイントです。

キーワード入力欄に保存した内容を取り出す

keyword/Event/KeywordControllerEventListener.php at master · materializing/keyword
※2系では以下に当たります。
keyword/controllers/components/keyword_hook.php at 1.3.1 · materializing/keyword

公開側での処理はこちらに集めてます。
管理システム側でキーワード入力欄に保存した内容を取り出してます。
イベントのタイミングとしては、記事の表示するとき、に当るので「beforeRender」を使ってみました。

コントローラー・イベントでは、イベント名のルールとして {コントローラ名}.{イベント名} を利用できます。
また、{プラグイン名}.{コントローラ名}.{イベント名} の指定も可能なので、この仕組みを利用する事で、イベントの発動ポイントをより最初から絞り込んでおく事が可能です。

・・・ということで、「beforeRender()」は「pagesBeforeRender()」の方が良さそうですね(´Д`)

2014/01/13 追記

さっそく処理を変更した 2.0.1リリースしちゃいました。
他にもちょいちょい見直しちゃったてへぺろ(・ω・)

beforeRender では、登録しているキーワードの情報を取得して、存在していれば $event->_subject->viewVars['keywords'] に入れ込んでます。
こうすることで、ビュー側まで配達されていきます。

BaserEvent のご紹介

このくらいの追加・編集・削除・表示のイベントを利用する事で、プラグイン側のデータの利用ができるようになります。
もうちょっと基本的なサンプルが良いな、という場合は、やはり公式のサンプルが有効なので紹介しておきます。
プラグイン開発について | baser CMS - 国産オープンソース!フリー(無料)で『コーポレートサイトにちょうどいいCMS』

また、イベントの指定可能な箇所の確認には、以下のファイルを覗いてみると良いです。
■ BASERCMS/lib/Baser/Event/〜EventDispatcher.php
basercms/lib/Baser/Event at master · basercms/basercms

インストール時のスキーマファイルの生成

DBを利用するプラグインを作成する際には、専用のテーブルを作成し、DB構造を決めてから取り掛かる場面が多いかと思います。
私の場合、phpMyAdminやNavicat等のDB用のツールを利用して進めてます。
そして、プラグインのインストール時に利用するのが スキーマ・ファイルです。
簡単に言うと、DBにテーブルを作成する際の雛形、となるファイルです。
keyword/Config/sql/keywords.php at master · materializing/keyword

baserCMSには、このスキーマファイルを簡単に作成する仕組みが備わってます。
管理システム側で以下のURLを叩きます。
YOUR_BASERCMS/admin/tools/write_schema
あとは、テーブルを指定して「生成」ボタンを押すだけで、必要となるスキーマ・ファイルを作成する事ができるようになってます。超便利。

個人的には「/admin/tools/maintenance」画面にメニューとしてあっても良いんじゃないかなぁ?とか思ってます。

baserCMS3系からは、生成されるスキーマ・ファイルが2系と微妙に異なる内容となってます。
具体的には、アクセス修飾子がついたり、InnoDBの指定ができたり。
というワケで、3系対応のプラグインを作成する際は、このスキーマ・ファイル生成機能を使っておくと良いです。

それから、キーワード・プラグインではインストール時に一括で必要なデータを生成するようにしてます。
keyword/Config/init.php at master · materializing/keyword
登録中の固定ページとブログ記事のデータから、キーワード用の保存データを一括で生成してます。
参考になれば・・・ということで紹介しておきます。

最後に。。。

今回は、プラグインフックからプラグインイベントへの変更ということで、キーワード・プラグインを用いて、その変更箇所や内容について紹介してみました。

  • イベント処理になって、引数の指定が1つになってラクになった
  • コントローラやモデル単位で最初から指定箇所を絞り込んでおける

といったメリットがあります。

コア側に手を触れずにやりたい事が実現できるプラグインの仕組みは、作ってて楽しいですよ。
どの辺から手を付けたら良いのかなぁ、という方に、今回の紹介記事が少しでも役に立てたら嬉しく思います。

また、稚拙ながらもbaserCMS用プラグインを幾つか公開してます。
materializing/optional_link
materializing/btn_change_date_time
この辺りも併せて見てもらうと、やりたいことのなにかの素材になるかもしれません。。。なったらとても嬉しいです。

ではまた・・・丶(・ω・)ノ

▲ to Top

トラックバック(0)

▲ to Top