-
Notifications
You must be signed in to change notification settings - Fork 0
Action and Routing
An action in ADR is responsible for handling the request - call the domain, then call the responder and pass any required data. This simplicity allows to model action as a invokable (callable) class.
namespace App\Http\Actions;
class ShowUserAction extends Action
{
/**
* @param Request $request
* @param mixed $id
* @return \Symfony\Component\HttpFoundation\Response
*/
public function __invoke(Request $request, $id)
{
// ...
}
}
Any action should extend HydrefLab\Laravel\ADR\Action\Action
class.
However, it is recommended that action extends App\Http\Actions\Action
class which is already an extension of a base action class. This is situation similar to controllers - typically new controller extend
App\Http\Controllers\Controller
class and not its parent Illuminate\Routing\Controller
class.
Any action should return either responder instance or already built response.
Responder can be created/instantiated by:
- calling
responder
helper method,namespace App\Http\Actions; class ShowUserAction extends Action { public function __invoke(Request $request, $id) { $user = User::find($id); return responder($user); } }
- calling static
ResponderFactory::create()
method,namespace App\Http\Actions; class ShowUsersAction extends Action { public function __invoke() { $users = User::get(); return ResponderFactory::create($users); } }
- using
new
keywordnamespace App\Http\Actions; class ShowUserAction extends Action { public function __invoke(Request $request, $id) { $user = User::find($id); return new ShowUserResponder($user); } }
First two methods use auto-resolving mechanism described here.
More about responders can be found here.
To register single action route, simply add:
Route::get('users/{id}', \App\Http\Actions\ShowUserAction::class);
in your routes file.
Actions are thin controllers. One resource controller in Laravel corresponds to 7 (!) actions. Registering routes for all the actions can be quite bothersome. There is a mechanism that allows to register your resource-like actions' routes in the same way as registering resource controller.
In your routes file, simply add:
Route::adrResource('users');
// or for API-like resource
Route::adrApiResource('users');
This will produce following result:
+--------+-----------+-------------------+---------------+------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-------------------+---------------+------------------------------------+------------+
| | GET|HEAD | users | users.index | App\Http\Actions\IndexUsersAction | web |
| | POST | users | users.store | App\Http\Actions\StoreUserAction | web |
| | GET|HEAD | users/create | users.create | App\Http\Actions\CreateUserAction | web |
| | GET|HEAD | users/{user} | users.show | App\Http\Actions\ShowUserAction | web |
| | PUT|PATCH | users/{user} | users.update | App\Http\Actions\UpdateUserAction | web |
| | DELETE | users/{user} | users.destroy | App\Http\Actions\DestroyUserAction | web |
| | GET|HEAD | users/{user}/edit | users.edit | App\Http\Actions\EditUserAction | web |
+--------+-----------+-------------------+---------------+------------------------------------+------------+
adrResource
and adrApiResource
are route's macros and they can be used in the same way as resource controller's routes registration, i.e. pass namespace or additional route options:
// controller approach
Route::resource('users', 'MyNamespace/UsersController', ['except' => ['destroy']]);
// action approach
Route::adrResource('users', 'MyNamespace', ['except' => ['destroy']]);
The only difference here is that in controller approach namespace or partial namespace of the controller is passed, while in action approach namespace or partial namespace of all the actions is specified.
If namespace is not passed during actions' routes registration, namespace from configuration is taken into consideration.
The package adds one default resource action's class name resolver.
Resource action's class name is composed of:
- namespace,
- action type (index, store, etc.),
- resource name and
- postfix (from configuration).
If actions will be placed or named differently, new resolver(s) should/can be added.
It is possible by calling ActionResolver::extend()
method in any of the application service providers:
ActionResolver::extend(new MyCustomActionResolver());
// or
ActionResolver::extend(function(string $namespace, string $resource, string $actionType) {
// my custom resolver content here
});
Resolvers are run in the reverse order as they were added.
-
2.1. ADR
-
3.1. Conventions
3.2. Action & Routing
3.3. Responder
3.5. Exceptions
3.6. Console
3.7. Examples