こんにちは!ドイです!
前回の記事では、ADRの概念について学びました。
今回は、LaravelでADRの実装をしたいと思います。
Action
Action:DomainとResponderの橋渡しを行う。Controllerとは異なり、「1つのクラスに対して、1アクションのみを持つ」。 クラスは増えるが、MVCで問題だったFat Controllerの状態を回避する。
__invoke():PHPのマジックメソッド。関数としてコールしようとした際にコールされる。また、ADRでは一つのメソッドに対して一つのActionが使用される。ルーティングを書く際にメソッド名を省略して記述することが可能。
<?php namespace App\Http\Actions; use Illuminate\Http\Request; use Illuminate\Http\Response; use App\Http\Controllers\Controller; use App\Domain\TestIndexDomain; use App\Http\Responders\TestIndexResponder; class TestIndexAction extends Controller { protected $Domain; protected $Responder; public function __construct(TestIndexDomain $Domain, TestIndexResponder $Responder) { $this->Domain = $Domain; $this->Responder = $Responder; } /** * @param Request $request * @return Response */ public function __invoke(Request $request): Response { return $this->Responder->response( $this->Domain->get() ); } }
Domain
Domain:ビジネスロジック、データの加工を行う。MVCでのModelに相当する。
<?php namespace App\Domain; use Illuminate\Support\Collection; use App\Models\User; use Illuminate\Support\Facades\DB; class TestIndexDomain { public function get() { return [ 'name' => 'doi', ]; } }
Responder
Responder:Actionから受け取ったデータを、表示のため加工する。
<?php namespace App\Http\Responders; use Illuminate\Http\Response; use Illuminate\Contracts\View\Factory as ViewFactory; class TestIndexResponder { protected $response; protected $view; public function __construct(Response $response, ViewFactory $view) { $this->response = $response; $this->view = $view; } /** * @param $data * @return Response */ public function response($data): Response { $this->response->setContent( $this->view->make('test.index', ['data' => $data]) ); return $this->response; } }
Routing
Routing:Actionでも触れた通り、__invoke()を使用しているため、メソッド名を省略して記述する。
<?php use Illuminate\Support\Facades\Route; Route::get('/test', \App\Http\Actions\TestIndexAction::class);
確認
Hello!! {{ $data['name'] }}
http://localhost/test
にアクセスすると、Domainで渡した値が表示されました。
まとめ
ADRで実装することができました。
小さな案件ではADRで実装するメリットがありませんが、Fat Controllerになりがちな大きな案件の際にADRで実装してみたいなと思います!!