EventListener使いこなし術 - Symfony勉強会#10

35
EventListener 使いこなし術 Symfony 勉強会 #10 岡田祐一 @okapon_pon

description

Symfony勉強会#10 の LT枠で発表してきた内容です。 ブログ http://okapon-pon.hatenablog.com/entry/2014/07/29/015745

Transcript of EventListener使いこなし術 - Symfony勉強会#10

Page 1: EventListener使いこなし術 - Symfony勉強会#10

EventListener 使いこなし術

Symfony 勉強会 #10岡田祐一 @okapon_pon

Page 2: EventListener使いこなし術 - Symfony勉強会#10

自己紹介•名前:岡田祐一 (@okapon_pon)

• 所属:株式会社クロコス エンジニア

• 2013年~ 日本Symfonyユーザー会

• Symfony歴 2年半ほど

Page 3: EventListener使いこなし術 - Symfony勉強会#10

本日の話

EventListener使いこなし術

あらため

EventListenerできること

Page 4: EventListener使いこなし術 - Symfony勉強会#10

まえおき

!

Symfonyについて

Page 5: EventListener使いこなし術 - Symfony勉強会#10

Symfony

!

素直で柔軟なフレームワーク

Page 6: EventListener使いこなし術 - Symfony勉強会#10

Symfony

!

HWに縛られず自由に開発できる

Page 7: EventListener使いこなし術 - Symfony勉強会#10

Symfony

柔軟性を支える屋台骨

• DI (+ configuration)

• Event DispatcherEventListenerはここの話

Page 8: EventListener使いこなし術 - Symfony勉強会#10

Symfony

イベント駆動のフレームワーク

!

フックポイントが用意されている!

Page 9: EventListener使いこなし術 - Symfony勉強会#10

Symfonyのイベント

標準で用意されてるイベント !

• kernel.request • kernel.controller • kernel.view • kernel.response • kernel.exception

Page 10: EventListener使いこなし術 - Symfony勉強会#10

Symfonyのイベント

任意のイベントにフック可能

任意のタイミングでResponseを返すことが可能

Page 11: EventListener使いこなし術 - Symfony勉強会#10

EventListener 実例

それでは例を見ていきましょう

Page 12: EventListener使いこなし術 - Symfony勉強会#10

kernel.controllerイベント

kernel.controllerイベント !

コントローラーの実行前に 発行されるイベント

Page 13: EventListener使いこなし術 - Symfony勉強会#10

kernel.controllerイベント

BeforFilterControllerListener というクラスを作ってみます

Page 14: EventListener使いこなし術 - Symfony勉強会#10

kernel.controllerイベント

EventLisnerを登録# service.yml services: my.blog.before_filter_controller_listener: class: My\BlogBundle\EventListener\BeforFilterControllerListener tags: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Page 15: EventListener使いこなし術 - Symfony勉強会#10

EventListenerクラス作成class BeforeFilterControllerListener { public function onKernelController(FilterControllerEvent $event) { $c = $event->getController(); if (!is_array($c)) { return; } $controller = $c[0]; ! if (method_exists($controller, 'before')) { $controller->before($event->getRequest(); } } }

Page 16: EventListener使いこなし術 - Symfony勉強会#10

EventListenerクラス作成

何やってるか分かりました?

Page 17: EventListener使いこなし術 - Symfony勉強会#10

コントローラー側/** * @Route("/blog") * @Template() */ class BlogController extends Controller { public function before(Request $request) { // Actionが呼ばれる前に実行したい処理が書ける } ! /** * @Route("/", name="blog_index") */ public function indexAction() { } }

Page 18: EventListener使いこなし術 - Symfony勉強会#10

Controller実行前のフック

どこかのフレームワークで 見たことある機能・・・

Page 19: EventListener使いこなし術 - Symfony勉強会#10

なぜSymfonyにないのか?

コントローラーに書くと

• 再利用しにくい

• テストしづらい

Page 20: EventListener使いこなし術 - Symfony勉強会#10

なぜSymfonyにないのか?

もう一度コードに戻ります

Page 21: EventListener使いこなし術 - Symfony勉強会#10

class BeforeFilterControllerListener { public function onKernelController(FilterControllerEvent $event) { $c = $event->getController(); if (!is_array($c)) { return; } $controller = $c[0]; ! if (method_exists($controller, 'before')) { $controller->before($event->getRequest(); } } }

EventListenerクラス作成

コントローラー側に書く必要がないと感じませんか?

Page 22: EventListener使いこなし術 - Symfony勉強会#10

EventListener まとめ1

EventListenrに記述した方が変な依存を持たずシンプルに実装

できる 【サンプルコード】 https://gist.github.com/okapon/fd2dfdacf87e417f7957

Page 23: EventListener使いこなし術 - Symfony勉強会#10

EventListener 実装例

Securityコンポーネント よく分からなくて昔作ったオレオレ認証

https://gist.github.com/okapon/88f5bd56a886c287a7d1

Page 24: EventListener使いこなし術 - Symfony勉強会#10

EventListener 実装例

先ほどの実装例では isSecure()メソッドはマーカー → annotationにするとよい

!

【参考】Doctrine-Common-Annotations http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html

Page 25: EventListener使いこなし術 - Symfony勉強会#10

EventListener まとめ2

ユーザー認証の仕組みもEventListenrを使えば 簡単に実装できる

Page 26: EventListener使いこなし術 - Symfony勉強会#10

ちなみに

ここまでkernel.controllerを取り上げといてなんですが・・・ よく使うのは • kernel.request • kernel.response

Page 27: EventListener使いこなし術 - Symfony勉強会#10

では気を取り直して

Page 28: EventListener使いこなし術 - Symfony勉強会#10

EventListener使いどころ複数コントローラーで実行したい共通処理

• 認証まわり • 初回登録時のアクセス判定 • チュートリアルの完了状態で表示出し分け • アクセスの分析(referrerとか)

Page 29: EventListener使いこなし術 - Symfony勉強会#10

チュートリアルの表示判定する例

ユーザーはどこのURLにでもアクセスする可能性がある

!

• kernel.requestをフック • EventListenerでチュートリアル完了か判定 • 完了してなければチュートリアルを表示

Page 30: EventListener使いこなし術 - Symfony勉強会#10

TutorialListener実装例1class TutorialListener { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } if (!$this->securityContext->getToken()) { return; } ! $user = $this->securityContext->getToken()->getUser(); if ($this->doseNeedTutorial($user)) { // チュートリアルのURLにリダイレクトするとか $event->setResponse(new RedirectResponse('/tutorial', 302)); } } }

Page 31: EventListener使いこなし術 - Symfony勉強会#10

TutorialListener実装例2class TutorialListener { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } if (!$this->securityContext->getToken()) { return; } ! $user = $this->securityContext->getToken()->getUser(); if ($this->doseNeedTutorial($user)) { // sessionに状態を入れるとか $this->session->set(’needTutorial’, true)); } } }

Page 32: EventListener使いこなし術 - Symfony勉強会#10

アクセスデータの収集に使う例

!

• どこからアクセスされたかreferrerを取る • sessionに保存 • 必要なタイミングでsessionから取出し保存

Page 33: EventListener使いこなし術 - Symfony勉強会#10

アクセスデータの収集に使う例use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; !class AccessLogListener { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } $request = $event->getRequest(); ! // あくまでrefを取るだけのサンプル

// 実際には各種属性情報を保存しとくと良い

$ref = $request->query->get('ref'); if ($ref) { $request->getSession()->set(‘ref’, $ref); } } }

Page 34: EventListener使いこなし術 - Symfony勉強会#10

まとめ(無理矢理)!

• コントローラ実行前の共通処理を書くのに便利

• EventListener使えばアイデア次第で色々ハックできる

• オレオレ作ってしまってもいいじゃない

Page 35: EventListener使いこなし術 - Symfony勉強会#10

EventListener おまけ

活用事例としてはbrtriverさんのお話が非常に参考になります !「運用しやすい管理画面とは」 http://tech.voyagegroup.com/archives/7644534.html !"PHP Fatal error: Allowed memory size of xxx" で落ちる前にできること http://d.hatena.ne.jp/brtRiver/20131206/1386345547