How to use Laravel's Conditionable Trait for dynamic actions
When working with multiple or complex conditional logic, if-else statements can quickly increase cognitive load and by extension, code maintainability.
However, Laravel provides a trait that we can leverage to create a fluent and dynamic API that provides a cleaner approach to conditional logic—the Conditionable
trait. We will use Filament as a case study.
How Does Filament Use the Conditionable Trait?
In Filament, the Conditionable
trait is particularly useful for creating actions that need to behave differently based on certain conditions. For instance, you might want an action to have a label only when another condition (e.g. $iconOnly
) is false.
use Filament\Actions\Action; use Filament\Forms; Action::make('action') ->when($iconOnly, fn (Action $action) => $action->label('')->link()) ->icon('...') ->action(function (array $data) { // do stuff });
In this example, the when()
method checks if $iconOnly
is true. If it is, the callback function modifies the action to remove the label and convert it into a link, such that the action is presented like a clickable icon.
Practical Example: A Flexible Action Builder
Let's look at how you might implement something similar in your own application using an action class.
-
Create a Custom Action Class: Create a class that uses the
Conditionable
trait.<?php namespace App\Actions; use Illuminate\Support\Traits\Conditionable; class MyAction { use Conditionable; protected $label; protected $link = false; protected $formFields = []; public function label($label) { $this->label = $label; return $this; } public function link() { $this->link = true; return $this; } public function form(array $fields) { $this->formFields = $fields; return $this; } public function run(?callable $callback = null) { // Simulate a form submission if ($callback) { $data = ['dummy' => 'value']; // Mock form data call_user_func($callback, $data); } } }
Databases in VS Code? Get DevDb -
Using the Action Builder: You can now use this class to build actions dynamically:
use App\Actions\MyAction; MyAction::make('my_action') ->when(true, fn ($action) => $action->label('')->link()) ->form([ // Define your form fields here ]) ->run(function (array $data) { dump($data); });
In this example, the when()
method accepts a condition and a callback. If the condition is true, it runs the callback on the action instance.
Conclusion
With Laravel's Conditionable
trait, you can build fluent and dynamic APIs in your applications, much like Filament does. This approach makes your code easier to understand and maintain by reducing the amount of conditional logic scattered throughout your application. However, while Conditionable
makes your code more readable, don’t overuse it where simple structures like if/else would suffice.
Remember, writing cleaner and more dynamic code isn’t just about productivity; it’s also about making your codebase more welcoming for future contributors, even your future self!