Filament v3 Custom Actions: Bulk, Table &amp; Header | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. Laravel Filament v3 Custom Actions: Bulk, Table, and Header Actions Done Right

 Laravel Filament v3 Custom Actions: Bulk, Table, and Header Actions Done Right
===============================================================================

 Go beyond the defaults: build type-safe bulk actions, inject services into header actions, and wire table row actions to queued jobs — all without polluting your resource classes.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 3 Aug 2026 · Updated 3 Aug 2026 · 3 min read

ShareCopy linkCopied

 ![Laravel Filament v3 Custom Actions: Bulk, Table, and Header Actions Done Right](https://cdn.msaied.com/502/ff034ec2bd69cdc8e56eced7a83882a3.png) 

  On this page +1. [Filament v3 Custom Actions: Bulk, Table, and Header Actions Done Right](#filament-v3-custom-actions-bulk-table-and-header-actions-done-right)
2. [1. Extracting Actions Into Dedicated Classes](#1-extracting-actions-into-dedicated-classes)
3. [2. Bulk Actions That Dispatch Batched Jobs](#2-bulk-actions-that-dispatch-batched-jobs)
4. [3. Header Actions With Service Injection](#3-header-actions-with-service-injection)
5. [4. Guarding Actions With Visibility vs. Authorization](#4-guarding-actions-with-visibility-vs-authorization)
6. [5. Passing Extra Data Through mountUsing and form](#5-passing-extra-data-through-codemountusingcode-and-codeformcode)
7. [Takeaways](#takeaways)

 Filament v3 Custom Actions: Bulk, Table, and Header Actions Done Right
----------------------------------------------------------------------

Filament ships with a generous set of built-in actions, but production apps quickly outgrow them. You need bulk operations that dispatch jobs, header actions that resolve services from the container, and row-level actions that enforce policy before they run. This article shows concrete patterns for each.

---

### 1. Extracting Actions Into Dedicated Classes

Inlining action logic inside `getTableActions()` works for demos. For anything real, extract to a class:

```php
// app/Filament/Actions/ArchiveOrderAction.php
namespace App\Filament\Actions;

use App\Jobs\ArchiveOrderJob;
use App\Models\Order;
use Filament\Tables\Actions\Action;

class ArchiveOrderAction
{
    public static function make(): Action
    {
        return Action::make('archive')
            ->label('Archive')
            ->icon('heroicon-o-archive-box')
            ->requiresConfirmation()
            ->authorize(fn (Order $record) => auth()->user()->can('archive', $record))
            ->action(function (Order $record): void {
                dispatch(new ArchiveOrderJob($record->id));
            })
            ->successNotificationTitle('Order queued for archiving');
    }
}

```

Register it in your resource:

```php
public function getTableActions(): array
{
    return [
        ArchiveOrderAction::make(),
        EditAction::make(),
    ];
}

```

The `authorize()` callback receives the resolved model, so policy checks stay close to the action without touching the resource.

---

### 2. Bulk Actions That Dispatch Batched Jobs

Bulk actions receive a `Collection` of selected records. Pair them with `Bus::batch()` for reliable fan-out:

```php
use Filament\Tables\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Bus;

BulkAction::make('reprocess')
    ->label('Reprocess Selected')
    ->icon('heroicon-o-arrow-path')
    ->requiresConfirmation()
    ->deselectRecordsAfterCompletion()
    ->action(function (Collection $records): void {
        $jobs = $records->map(
            fn ($record) => new ReprocessOrderJob($record->id)
        )->all();

        Bus::batch($jobs)
            ->name('reprocess-orders')
            ->allowFailures()
            ->dispatch();
    });

```

`allowFailures()` means one bad record does not abort the entire batch — critical when operating on hundreds of rows.

---

### 3. Header Actions With Service Injection

Header actions live outside the table loop, making them ideal for operations that need infrastructure services:

```php
use Filament\Actions\Action;
use App\Services\ReportExporter;

protected function getHeaderActions(): array
{
    return [
        Action::make('export')
            ->label('Export CSV')
            ->action(function (ReportExporter $exporter): \Symfony\Component\HttpFoundation\StreamedResponse {
                return $exporter->streamCsv(
                    $this->getTableQuery()->get()
                );
            }),
    ];
}

```

Filament resolves the `ReportExporter` from the service container automatically via the `action()` closure's type-hint — no manual `app()` call needed.

---

### 4. Guarding Actions With Visibility vs. Authorization

Two separate concerns are often conflated:

- **`visible()`** — controls whether the action renders at all (UI concern).
- **`authorize()`** — throws a 403 if the action is invoked without permission (security concern).

Always set both:

```php
Action::make('refund')
    ->visible(fn () => auth()->user()->hasRole('billing'))
    ->authorize(fn (Order $record) => auth()->user()->can('refund', $record))
    ->action(fn (Order $record) => $record->issueRefund());

```

Relying only on `visible()` is a security hole — a crafty user can POST the action directly.

---

### 5. Passing Extra Data Through `mountUsing` and `form`

When an action needs user input before executing, combine `form()` with `mountUsing()` to pre-populate fields:

```php
Action::make('reschedule')
    ->form([
        DateTimePicker::make('scheduled_at')->required(),
    ])
    ->mountUsing(fn (ComponentContainer $form, Order $record) =>
        $form->fill(['scheduled_at' => $record->scheduled_at])
    )
    ->action(fn (array $data, Order $record) =>
        $record->update(['scheduled_at' => $data['scheduled_at']])
    );

```

---

### Takeaways

- Extract actions to dedicated classes early; inline closures do not scale.
- Use `Bus::batch()` inside bulk actions for reliable, observable fan-out.
- Header action closures support full container injection via type-hints.
- Always pair `visible()` with `authorize()` — they are not interchangeable.
- `mountUsing()` lets you pre-fill action forms from the current record state.

- [filament](https://www.msaied.com/public/articles?search=filament)
- [laravel](https://www.msaied.com/public/articles?search=laravel)
- [filament-actions](https://www.msaied.com/public/articles?search=filament-actions)
- [php](https://www.msaied.com/public/articles?search=php)

 Frequently asked questions 
---------------------------

  Can I reuse a custom action class across multiple Filament resources?Yes. Because the action is a plain static factory method returning an `Action` instance, you can call `ArchiveOrderAction::make()` from any resource's `getTableActions()` or `getHeaderActions()` without duplication.

   How do I test that an action dispatches the correct job?Use `Queue::fake()` before triggering the action in your Pest test, then assert with `Queue::assertPushed(ReprocessOrderJob::class)`. Filament's `livewire()-&gt;callTableAction()` helper fires the full action lifecycle including your closure.

   What is the difference between `action()` and `successRedirectUrl()` in a header action?`action()` is the handler closure that runs your business logic. `successRedirectUrl()` is an optional follow-up that redirects the user after a successful action — useful after creating a related resource or triggering an export.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleFilament v4 Schema-Based Forms, Infolists, and the Unified Schema API](https://www.msaied.com/public/articles/filament-v4-schema-based-forms-infolists-and-the-unified-schema-api-4) [Next articleLivewire v4.3.5 Released: Fix for SFC Detection with PHP Attribute Array Arguments](https://www.msaied.com/public/articles/livewire-v435-released-fix-for-sfc-detection-with-php-attribute-array-arguments)  

   On this page
-------------

1. [Filament v3 Custom Actions: Bulk, Table, and Header Actions Done Right](#filament-v3-custom-actions-bulk-table-and-header-actions-done-right)
2. [1. Extracting Actions Into Dedicated Classes](#1-extracting-actions-into-dedicated-classes)
3. [2. Bulk Actions That Dispatch Batched Jobs](#2-bulk-actions-that-dispatch-batched-jobs)
4. [3. Header Actions With Service Injection](#3-header-actions-with-service-injection)
5. [4. Guarding Actions With Visibility vs. Authorization](#4-guarding-actions-with-visibility-vs-authorization)
6. [5. Passing Extra Data Through mountUsing and form](#5-passing-extra-data-through-codemountusingcode-and-codeformcode)
7. [Takeaways](#takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
