狠狠撸
Submit Search
Laravel aspectで関心の分離
?
1 like
?
2,436 views
K
Kenjiro Kubota
Follow
since 2017/07/08
Read less
Read more
1 of 31
Download now
Download to read offline
More Related Content
Laravel aspectで関心の分離
1.
LaravelAspectで関心の分離 KenjiroKubota 2017/07/08
2.
Profile Kenjiro Kubota istyle.inc ?PHP,?HHVM/Hack,?Javascript? DTPDesigner WebDesigner FrontEnginner WebApplicationEngiiner?now?
3.
関心の分離とは 関心の分離(かんしんのぶんり、英語: separation of
concerns、SoC)とは、ソフトウェア工 学において、プログラムを機能面において可能な限り重複がない、複数の機構に明確に分割 することをいう。ここでいう「関心?関心事?」とは、プログラムのある機能や振る舞い、目的 のことである。?Wikipedia?
4.
Aspect?AOP?とは アスペクト指向プログラミング(アスペクトしこうプログラミング、Aspect Oriented Programming、AOP)は、オブジェクト指向ではうまく分離できない特徴(クラス間を横断 ?cross‐cutting? するような機能)を「アスペクト」とみなし、アスペクト記述言語をもちいて 分離して記述することでプログラムに柔軟性をもたせようとする試み。アスペクトの例とし ては、データ転送帯域の制限や例外の処理などがある。Java
にアスペクト指向的要素を追加 したAspectJ が実験的に実装されている。?Wikipedia?
5.
横断的関心事を解决する手段
6.
代表的なケースはロギング、トランザクション、キャッシュなどが挙げられます
7.
Laravelで利用する際はRay.Aopを用いている以下のライブラリがオススメ(宣伝) ytake/laravel‐aspect
8.
利用ケース ロギング 普通はこんな感じ public?function?get($id) { ????Log::info($id); ????$this‐>logger‐>info($id); } Logファサードを使ったり、コンストラクトインジェクションしたloggerを使ったり...
9.
LaravelAspectを使うと use?YtakeLaravelAspectAnnotationLoggable; class?AspectLoggable { ????/** ?????*?@Loggable ?????*?@param?null?$id ?????*?@return?null ?????*/ ????public?function?normalLog($id?=?null) ????{ ????????return?$id; ????} }
10.
利用ケース トランザクション 普通はこんな感じ? public?function?save(array?$params) { ????DB::beginTransaction(); ????try?{ ????????$result?=?$this‐>eloquent‐>save($params); ????????DB::commit(); ????????return?$result; ????}?catch(Exception?$e)?{ ????????DB::rollback(); ????????Log::error($e‐>getMessage()); ????????throw?$e; ????} }
11.
LaravelAspectなら use?YtakeLaravelAspectAnnotationTransactional; /** ?*?@Transactional("master") ?*?@LogExceptions ?*/ public?function?save(array?$params) { ????return?$this‐>eloquent‐>save($params); }
12.
アノテーションで関心の分离ができる
13.
他にもデフォルトで便利なアノテーションが用意されてます 詳しくはライブラリのREADEMEを見てください。
14.
LaravelAspectに用意されてるアノテーションも便利なんですが 自分たちのアプリに合わせた独自のアノテーションを作り たいですよね?
15.
サンプルケース 最終ログイン日時の記録
16.
まずはLaravelAspectを導入 $?composer?require?‐‐no‐update?ytake/laravel‐aspect?&&?composer?update
17.
Provider登録 ?config/app.php? 'providers'?=>?[ ????//?added?AspectServiceProvider? ????YtakeLaravelAspectAspectServiceProvider::class, ????//?added?Artisan?Command ????YtakeLaravelAspectConsoleServiceProvider::class, ]
18.
設定ファイルとかModulesをアプリケーションにコピー $?php?artisan?ytake:aspect‐module‐publish $?php?artisan?vendor:publish
19.
こんな感じで追加されます laravel ??‐?app ????‐?Modules ??????‐?CacheableModule.php ??????‐?CacheEvictModule.php ??????‐?CachePutModule.php ??????‐?TransactionalModule.php ??????‐?LoggableModule.php ??????‐?LogExceptionsModule.php ??????‐?PostConstructModule.php ??????‐?RetryOnFailureModule.php ?????? ??‐?config ????‐?ytake‐laravel‐aop.php
20.
独自アノテーションの定义
21.
use?DoctrineCommonAnnotationsAnnotation; /** ?*?@Annotation ?*?@Target("METHOD") ?*?Class?LastLoginTime ?*/ class?LastLoginTime?extends?Annotation { ????// } アスペクト利用時は以下の様になる ‐> ?@LastLoginTime()?
22.
インターセプターの定義 ※ アノテーションが実行されるときの挙動を定義
23.
use?RayAopMethodInvocation; use?RayAopMethodInterceptor; use?YtakeLaravelAspectAnnotationAnnotationReaderTrait; class?LastLoginTimeInterceptor?implements?MethodInterceptor { ????use?AnnotationReaderTrait; ???? ????/** ?????*?@param?MethodInvocation?$invocation ?????*?@return?object ?????*/ ????public?function?invoke(MethodInvocation?$invocation) ????{ ????? //?before ????????$result?=?$invocation‐>proceed(); ????????//?after ????????$user?=?$result‐>getUser(); ????????$lastLoginTime?=?app()‐>make(AppServiceLastLoginTime::class); ????????if?(!$lastLoginTime‐>update($user))?{ ????????????throw?new?ErrorException("Failed?Update?Last?Login?Time"); ????????} ????????return?$result; ????} }
24.
//?before $result?=?$invocation‐>proceed(); //?after beforeはアノテーションを記述したメソッドが実行される前に実行される。 afterはメソッド実行されたあとに実行される $resultにはそのメソッドの返り値が入ります。
25.
ポイントカットの定義 ※ 特定のアノテーションが実行されるときに起動されるインターセプターを定義
26.
class?LastLoginTimePointCut?extends?CommonPointCut?implements?PointCutable { ????/**?@var?string?*/ ????protected?$annotation?=?AppAnnotationLastLoginTime::class; ???? ????/** ?????*?@param?Container?$app ?????*?@return?RayAopPointcut ?????*/ ????public?function?configure(Container?$app) ????{ ????????$this‐>setInterceptor(new?LastLoginTimeInterceptor); ????????return?$this‐>withAnnotatedAnyInterceptor(); ????} }
27.
モジュールの追加 ※ アノテーションが利用されるクラスを定義する
28.
use?AppAspectPointCutLastLoginTimePointCut; use?YtakeLaravelAspectModulesAspectModule; class?LastLoginTimeModule?extends?AspectModule { ????/**?@var?array?*/ ????protected?$classes?=?[ ????????AppHttpControllerLoginController::class, ????]; ???? ????/** ?????*?@return?LastLoginTimePointCut ?????*/ ????public?function?registerPointCut() ????{ ????????return?new?LastLoginTimePointCut; ????} }
29.
最後にModulesを以下に登録してあげればOK ?config/ytake‐laravel‐aop.php? ????????'modules'?=>?[ ????????????... ????????????//?append?modules ????????????AppModulesLastLoginTimeModule::class, ????????],
30.
まとめ LaravelAspectをとりあえず導入するだけでも楽々AOPが実現できる 拡張もできるので独自の要件にも対応できる 関心を分離することでいちクラスの責務を追求できるようになります 単一責任の原則
31.
thanks :?
Download