Actions & Bulk Actions
An action is a named operation a user can run for one record, such as deactivating one customer. A bulk action runs once for a selection of records, such as deactivating several customers together. You define the operation on the Resource; its handler contains the application code that does the work.
Use actions() for one-record actions and bulkActions() for selection actions. Adding an action definition does not change a record by itself: configure a handle(...) callback. SeviaFlow displays these actions in the Resource UI and asks for confirmation when required.
Complete example: deactivate customers
This example defines one action for an individual customer and one for selected customers. The first handler receives one Eloquent model. The bulk handler receives an Illuminate\Support\Collection of selected models.
<?php
declare(strict_types=1);
namespace App\SeviaFlow\Resources\Examples;
use App\Models\Customer;
use Illuminate\Support\Collection;
use SeviaFlow\Core\Resources\Action;
use SeviaFlow\Core\Resources\BulkAction;
use SeviaFlow\Core\Resources\Columns\BooleanColumn;
use SeviaFlow\Core\Resources\Columns\TextColumn;
use SeviaFlow\Core\Resources\Resource;
use SeviaFlow\Core\Resources\Table;
final class ActionsResource extends Resource
{
protected static string $model = Customer::class;
public static function table(Table $table): Table
{
return $table->columns([
TextColumn::make('name')->label('Name')->searchable()->sortable(),
BooleanColumn::make('active')->label('Active'),
]);
}
/**
* @return array<int, Action>
*/
public static function actions(): array
{
return [
Action::make('deactivate')
->label('Deactivate account')
->danger()
->requiresConfirmation()
->successMessage('Customer deactivated.')
->authorize(fn (mixed $user, Customer $record): bool => $record->active)
->handle(function (Customer $record): void {
$record->update(['active' => false]);
}),
];
}
/**
* @return array<int, BulkAction>
*/
public static function bulkActions(): array
{
return [
BulkAction::make('deactivate_selected')
->label('Deactivate selected')
->danger()
->maxRecords(50)
->requiresConfirmation()
->handle(function (Collection $records): void {
foreach ($records as $record) {
if ($record instanceof Customer) {
$record->update(['active' => false]);
}
}
}),
];
}
}
In the example, danger() marks deactivation as consequential and requires confirmation. The individual action also checks its own condition in authorize(...). The bulk action limits the selection to 50 records. SeviaFlow also enforces the global UI cap at seviaflow-ui.bulk_actions.max_selected.
Configure a one-record Action
| Method | What it does | When to use it |
|---|---|---|
make('deactivate') | Creates an action with a stable machine name. If you omit a label, the name is converted to readable text. | Use a short identifier for the operation; keep display wording in label(). |
label(...), description(...) | Set the button text and supporting explanation shown to the operator. | Describe the result in terms the person using the screen will understand. |
primary(), secondary(), danger() | Set the visual treatment. danger() also turns on confirmation; these styles do not grant permission. | Reserve danger() for consequential actions such as disabling or cancelling. |
requiresConfirmation() | Requires an explicit confirmation before the handler runs. danger() already enables this. | Use for an action that is easy to trigger but costly to reverse. |
confirmButton(...), cancelButton(...) | Change the labels on the confirmation dialog buttons. | Use labels that make the outcome clear, such as “Deactivate customer”. |
authorize(fn ($user, $record) => ...) | Adds an action-specific check. It must return true to allow the action; an exception fails closed. | Use for a record-specific rule. Keep the app's normal Resource and Laravel authorization checks as well. |
handle(fn ($record) => ...) | Registers the code that performs the operation. The callback receives the Eloquent record. | Update the record or call application services needed for this action. |
successMessage(...), errorMessage(...) | Set the message shown after success or when the handler fails. Unexpected exceptions are reported by the UI and are not shown as raw exception text. | Use concise messages that tell the operator what happened or what to try next. |
execute($record) | Runs the configured handler for a record. It fails if no handler was configured. | Normally SeviaFlow calls this after the action is selected; define handle() in Resource configuration. |
Configure a BulkAction
A bulk action follows the same pattern, but its handler receives the full selected collection. It is marked as mutating by default, so the UI requires update authorization for every selected record. Use readOnly() only when the operation only reads records; then the UI checks view authorization instead. mutating() restores the update-check behavior.
| Method | What it does |
|---|---|
maxRecords(50) | Sets a per-action cap in addition to the global selection limit. |
authorize(fn ($user, $records) => ...) | Adds an action-specific check for the user and the selected collection. |
handle(fn (Collection $records) => ...) | Registers the operation. The handler receives an Illuminate\Support\Collection; decide how to process each record. |
readOnly(), mutating() | Choose whether the UI requires view or update authorization for each selected record. |
danger(), requiresConfirmation() | Require confirmation before running the operation on the selection. danger() also marks it as dangerous in the UI. |
execute($records) | Runs the configured handler for a collection. Normally SeviaFlow calls it after the user confirms the action. |
Bulk handlers should be safe for the maximum number of records your application permits. If a task is long-running or must call an external service, put that work in an application job and report failures explicitly.
Get Started