Actions
Your resource automatically exposes the actions you have defined on it. Configure them, register them and you are done !
Overview
Actions can be generated using the rest:action
Artisan command. By default, every action is placed in your App\Rest\Actions
directory.
php artisan rest:action SendWelcomeNotificationAction
You are now ready to configure your action:
namespace App\Rest\Actions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Lomkit\Rest\Actions\Action;
use Lomkit\Rest\Http\Requests\RestRequest;
class SendWelcomeNotificationAction extends Action
{
/**
* Perform the action on the given models.
*
* @param array $fields
* @param \Illuminate\Support\Collection $models
* @return mixed
*/
public function handle(array $fields, \Illuminate\Support\Collection $models)
{
foreach ($models as $model) {
$model->notify(new \App\Notifications\SendWelcomeNotification($fields['expires_at']))
->delay($this->resource instanceof \App\Rest\UserResource ? 50 : 0);
}
}
/**
* The action fields.
*
* @param \Lomkit\Rest\Http\Requests\RestRequest $request
* @return array
*/
public function fields(\Lomkit\Rest\Http\Requests\RestRequest $request)
{
return [
'expires_at' => [
'required', 'date'
]
];
}
}
In the handle
method you receive a Collection of models. The models correspond to the resource the action has been registered on.
You are free to do whatever you want in this handle
method: update records, send jobs, etc...
You can access the resource that launched the action by using $this->resource
at any moment.
Register an action
To register an action, you simply need to specify it in your resource:
use App\Rest\Actions\SendWelcomeNotificationAction;
class UserResource extends Resource
{
/**
* The actions that should be linked
* @param RestRequest $request
* @return array
*/
public function actions(RestRequest $request): array {
return [
SendWelcomeNotificationAction::make()
];
}
}
Authorizations
In case you don't want to expose your actions to all users, you simply need to condition this method:
use App\Rest\Actions\SendWelcomeNotificationAction;
class UserResource extends Resource
{
/**
* The actions that should be linked
* @param RestRequest $request
* @return array
*/
public function actions(RestRequest $request): array {
$actions = [];
if ($request->user()->isAdministrator()) {
array_push($actions, SendWelcomeNotificationAction::make())
}
return $actions;
}
}
Fields
Sometimes, you want to directly collect data from your frontend users. This is what fields are made for. You need to define them in your action first:
namespace App\Rest\Actions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Lomkit\Rest\Actions\Action;
use Lomkit\Rest\Http\Requests\RestRequest;
class SendWelcomeNotificationAction extends Action
{
/**
* The ation fields.
*
* @param \Lomkit\Rest\Http\Requests\RestRequest $request
* @return array
*/
public function fields(\Lomkit\Rest\Http\Requests\RestRequest $request)
{
return [
'expires_at' => [
'required', 'date'
]
];
}
}
In the returned array, the key should correspond to the field name provided in the call, while the value should represent the desired set of validations for that field. Laravel Rest API automatically validates all fields based on your defined validation rules.
You get those fields in the $field
variable in your handle
method.
Meta
Because your actions are exposed to frontend users, they do receive certain information about them, such as uriKey
, name
and fields
. However, you are also welcome to provide your own data.
You can achieve this by invoking withMeta
within your action's constructor:
class SendWelcomeNotificationAction extends Action
{
public function __construct()
{
$this->withMeta([
'color' => '#FFFFFF'
]);
}
}
Alternatively, you can call it during the action registration if you wish to define distinct meta information based on the resource:
use App\Rest\Actions\SendWelcomeNotificationAction;
class UserResource extends Resource
{
/**
* The actions that should be linked
* @param RestRequest $request
* @return array
*/
public function actions(RestRequest $request): array {
return [
SendWelcomeNotificationAction::make()
->withMeta(['color' => '#FFFFFF'])
];
}
}
Queued actions
If your actions require a significant amount of processing time, you might want to queue them. To instruct Laravel Rest API to queue your actions dynamically, you should use the ShouldQueue
interface:
namespace App\Rest\Actions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Lomkit\Rest\Actions\Action;
use Illuminate\Contracts\Queue\ShouldQueue;
use Lomkit\Rest\Http\Requests\RestRequest;
class SendWelcomeNotificationAction extends Action implements ShouldQueue
{
// ...
}
Laravel Rest Api will chunk your results and create a job for each chunk. By default, the chunk size is set to 100
,
if you wish to change this, declare the chunkCount
property on your model:
namespace App\Rest\Actions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Lomkit\Rest\Actions\Action;
use Illuminate\Contracts\Queue\ShouldQueue;
use Lomkit\Rest\Http\Requests\RestRequest;
class SendWelcomeNotificationAction extends Action implements ShouldQueue
{
/**
* The number of models that should be included in each chunk.
*
* @var int
*/
public $chunkCount = 100;
}
handle
method will be directly called for each chunk.Customizing the queue and connection
You may customize the queue connection and queue name that the action is queued on by setting the $connection
and $queue
properties on your class:
namespace App\Rest\Actions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Lomkit\Rest\Actions\Action;
use Illuminate\Contracts\Queue\ShouldQueue;
use Lomkit\Rest\Http\Requests\RestRequest;
class SendWelcomeNotificationAction extends Action implements ShouldQueue
{
/**
* The name of the connection the job should be sent to.
*
* @var string|null
*/
public $connection;
/**
* The name of the queue the job should be sent to.
*
* @var string|null
*/
public $queue;
}
Batchable Actions
You may instruct Laravel Rest Api that an action is batchable by using the BatchableAction
and ShouldQueue
interfaces on your class:
namespace App\Rest\Actions;
use Illuminate\Contracts\Queue\ShouldQueue;
use Lomkit\Rest\Actions\Action;
use Lomkit\Rest\Contracts\BatchableAction;
class SendWelcomeNotificationAction extends Action implements ShouldQueue, BatchableAction
{
/**
* Register callbacks on the pending batch.
*
* @param array $fields
* @param \Illuminate\Bus\PendingBatch $batch
* @return void
*/
public function withBatch(array $fields, PendingBatch $batch)
{
$batch->then(function (Batch $batch) {
// ...
})->catch(function (Batch $batch, Throwable $e) {
// ...
})->finally(function (Batch $batch) {
// ...
});
}
}
The new withBatch
method allows you to register callbacks on your pending batch. This means that these callbacks will be called depending on the batch status.
For example, if you want to send a notification when jobs are successfully completed, you should use the then
method. This method will trigger once at the end of all jobs triggered depending on your chunk size.
If you are not familiar with batches please see the Laravel Documentation.
Standalone actions
You may have sometimes an action that does not require any models to run. If you are in this situation, you might want to register the action as
standalone
by invoking the standlone
method when registering the action.
These actions will always receive an empty collection of models in the handle
method.
use App\Rest\Actions\ResetPasswordAction;
class UserResource extends Resource
{
/**
* The actions that should be linked
* @param RestRequest $request
* @return array
*/
public function actions(RestRequest $request): array {
return [
ResetPasswordAction::make()->standalone()
];
}
}