EloquentはLaravelでなくても便利なのでORMとしてCodeigniterやSlimで利用してますが
Eloquentのモデルが設定したイベントが呼ばれないので調べてみました。
エラーにはならず、普通にORMとして機能するんですけど、イベントが如何せんよばれない。。
class User extends Model {
public static function boot(){
parent::boot();
self::creating(function ($q) {
log出力とかしたい。
});
self::updating(function ($q) {
log出力とかしたいのに、イベントが呼ばれない。。
});
}
$user = User::find(1);
$user->last_login_at = time();
$user->save();
最初slim eloquent event not working,slim eloquent event not callなどで
ググったけど、SlimでEloquentとなるとModelの基本しか見つからないので
vendorの中をちゃんと読むことにしました。
Illuminate\Database\Eloquent\Model.phpを見ると
トレイトにHasEventsってぽいやつがいる。
そして中でイベントが設定されていれば、Dispatcher読んでる。
Model.php
namespace Illuminate\Database\Eloquent;
abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
{
use Concerns\HasAttributes,
Concerns\HasEvents,
Concerns\HasGlobalScopes,
Concerns\HasRelationships,
Concerns\HasTimestamps,
Concerns\HidesAttributes,
Concerns\GuardsAttributes,
ForwardsCalls;
HasEvents.php
namespace Illuminate\Database\Eloquent\Concerns;
use Illuminate\Contracts\Events\Dispatcher;
trait HasEvents
{
/**
* The event map for the model.
*
* Allows for object-based events for native Eloquent events.
*
* @var array
*/
protected $dispatchesEvents = [];
省略
/**
* Get the observable event names.
*
* @return array
*/
public function getObservableEvents()
{
return array_merge(
[
'retrieved', 'creating', 'created', 'updating', 'updated',
'saving', 'saved', 'restoring', 'restored',
'deleting', 'deleted', 'forceDeleted',
],
$this->observables
);
}
省略
protected function registerObserver($class)
{
$className = $this->resolveObserverClassName($class);
// When registering a model observer, we will spin through the possible events
// and determine if this observer has that method. If it does, we will hook
// it into the model's event system, making it convenient to watch these.
foreach ($this->getObservableEvents() as $event) {
if (method_exists($class, $event)) {
static::registerModelEvent($event, $className.'@'.$event);
}
}
}
イベントディスパッチャーはIlluminate\Contracts\Events\Dispatcherか。
と思いディレクトリを探すと無い。
そこで気づきました。。イベント設定してもDispatcher無いじゃん。
EventってEloquentが持ってるのかよければ依存で持ってきてると思ったけど。。。違うよね。。
今回はSlimを利用していて、下記のようにDBを読んでいます。
// DIC configuration
$container = $app->getContainer();
$container['db'] = function( $c ) {
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection( $c['settings']['db'] );
$capsule->getConnection()->enableQueryLog();
$capsule->setAsGlobal();
$capsule->bootEloquent();
return $capsule;
};
composer.jsonはこんな感じ
"require": {
"slim/slim": "^3.12",
"monolog/monolog": "^1.24",
"danielstjules/stringy": "^3.1",
"respect/validation": "^1.1",
"illuminate/database": "^5.5"
},
さっそくイベントライブラリを追加します。
composer require illuminate/container
composer require illuminate/events
そして、コンテナに入れてるDBにも設定を追加します。
最初間違って、setAsGlobalの後にsetEventDispatcherして動かなくて悩みました。。
use Illuminate\Events\Dispatcher as Dispatcher;
use Illuminate\Container\Container as Container;
// DIC configuration
$container = $app->getContainer();
$container['db'] = function( $c ) {
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection( $c['settings']['db'] );
$capsule->setEventDispatcher( new Dispatcher( new Container ) );
$capsule->getConnection()->enableQueryLog();
$capsule->setAsGlobal();
$capsule->bootEloquent();
return $capsule;
};
これでSlimフレームワークでもEloquentのModelイベントが動くようになりました。