-
-
Save taylorotwell/68f614deb9538f2e30108c2698266fda to your computer and use it in GitHub Desktop.
<?php | |
/* | |
|-------------------------------------------------------------------------- | |
| Application Routes | |
|-------------------------------------------------------------------------- | |
| | |
| Here is where you can register all of the routes for an application. | |
| It's a breeze. Simply tell Laravel the URIs it should respond to | |
| and give it the controller to call when that URI is requested. | |
| | |
*/ | |
use Illuminate\Http\Request; | |
use Illuminate\Routing\Controller; | |
use Illuminate\Support\Collection; | |
use Illuminate\Database\Connection; | |
use Illuminate\Contracts\Routing\ResponseFactory; | |
/** | |
* Resolve an action out of the container and call it, injecting method dependencies. | |
*/ | |
function marshal($action) | |
{ | |
return App::call([App::make($action), 'handle']); | |
} | |
/** | |
* A repository... | |
*/ | |
class PostRepository | |
{ | |
protected $connection; | |
public function __construct(Connection $connection) | |
{ | |
$this->connection = $connection; | |
} | |
public function all() | |
{ | |
return $this->connection->table('posts')->get(); | |
} | |
} | |
/** | |
* The responder... | |
*/ | |
class ListPostsResponder | |
{ | |
protected $response; | |
public function __construct(ResponseFactory $response) | |
{ | |
$this->response = $response; | |
} | |
public function handle(Collection $data) | |
{ | |
if (count($data) === 0) { | |
return $this->response->make('Not found.', 404); | |
} else { | |
return $this->response->view('posts.index', ['posts' => $data->all()]); | |
} | |
} | |
} | |
/** | |
* The action... | |
*/ | |
class ListPosts | |
{ | |
public function handle(Request $request, | |
ListPostsResponder $responder, | |
PostRepository $posts) | |
{ | |
return $responder->handle( | |
$posts->all() | |
); | |
} | |
} | |
/** | |
* The route... | |
*/ | |
$router->get('/posts', function () { | |
return marshal(ListPosts::class); | |
}); |
(As an aside, you don't need an else if you return in the first half of the conditional: https://gist.github.com/taylorotwell/68f614deb9538f2e30108c2698266fda#file-gistfile1-php-L63)
For what it's worth, I extended Laravel's router to support an invoke
parameter in the route definition, so that I could define invokable Action classes without needing to specify the @__invoke
method suffix on every item.
$router->get('posts', [
'as' => 'posts.list',
'invoke' => ListPosts::class,
]);
It would be nice if the router could determine if an item passed is callable
rather than looking for only \Closure
so extending is not needed, however I understand some of the holes or gotchas that come with doing so.
@pmjones your link was broken: http://pmjones.io/adr/
@jacobhenke fixed; thanks!
I got prompted to visit this gist without much context.
Was there any doubt that Laravel could not conform to ADR?
@cryode Any chance you could share this code?
I'm working on the same thing.
I read somewhere that callables were fixed in 5.3 but they definitely don't work in 5.7.
ADR makes you create a separate route for everything, route config becomes a mess.
For future readers, you can do constructor injection on the action by moving those dependencies to the constructor. No other changes will be required and Laravel's IoC container will automatically do the constructor injection.