Brain is an elegant Laravel Package that helps you organize your Laravel application using Domain-Driven Design principles through a simple command-line interface.
- π― Domain-Driven Structure: Easily create new domains with proper architecture
- π Process Management: Generate process classes for complex business operations
- π Query Objects: Create dedicated query classes for database operations
- β‘ Task Management: Generate task classes for background jobs and queue operations
- β»οΈ Code Reusability: By using tasks, you can easily reuse code across different processes, reducing duplication and enhancing maintainability.
- π§© Clear Domain Understanding: The structured approach provides a better understanding of each domain's processes, making it easier to manage and scale your application.
- π§ Improved Maintainability: With well-defined domains and processes, maintaining and updating your application becomes more straightforward and less error-prone.
You can install the package via composer:
composer require r2luna/brainphp artisan make:process
... follow prompt
name: CreateUserProcess
domain: UsersThis will create a new process class in app/Brain/Users/Processes/CreateUserProcess.php
Important
Note that every task running inside a process executes within a database transaction by default.
php artisan make:task
... follow prompt
name: SendWelcomeEmailTask
domain: UsersThis will create a new task class in app/Brain/Users/Tasks/SendWelcomeEmailTask.php
To send the task to the queue simply implements Laravel Contract ShouldQueue to the class
<?php
namespace App\Brain\User;
use Brain\Task;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendWelcomeNotifications extends Task implements ShouldQueue
{
public function handle(): self
{
//
return $this;
}
}Brain Tasks has a protected function called runIn() that you can use to determine when do you want to run the job if you need to delay.
class SendWelcomeNotifications extends Task implements ShouldQueue
{
protected function runIn(): int|Carbon|null
{
return now()->addDays(2);
}
...
}You can use a protected function runIf() to conditionally run a task.
/**
* @property-read int $amount
*/
class SendWelcomeNotifications extends Task
{
protected function runIf(): bool
{
return $this->amount > 200;
}
...
}You can validate the properties passed to a task by defining a rules() method that returns an array of validation rules.
/**
* @property-read User $user
* @property string $message
*/
class SendWelcomeNotifications extends Task
{
public function rules(): array
{
return [
'user' => 'required',
'message' => 'required|string|max:255',
];
}
public function handle(): self
{
// ...
return $this;
}
...
}Rules will validate based on the payload that was passed to the task when it was dispatched, and will override the default validation based on the docblock @property-read annotations.
toArray(): Returns the task properties as an array. Ex.['user' => $this->user]
If you need, for any reason, cancel the process from inside a task. You can call cancelProcess() method to do it.
class AddRoles extends Task
{
public function handle(): self
{
if($anyReason) {
$this->cancelProcess();
}
return $this;
}
}Caution
This will not work if the task is setup to run in a queue.
php artisan make:query
... follow prompt
name: GetUserByEmailQuery
domain: Users
model: UserThis will create a new query class in app/Brain/Users/Queries/GetUserByEmailQuery.php
// Using a Query
$user = GetUserByEmailQuery::run('[email protected]');
// Setting up a Process
class CreateUserProcess extends Process
{
protected array $tasks = [
RegisterUserTask::class,
SendWelcomeEmailTask::class, // Async task
NotifyStaffTask::class, // Async task
SubProcess::class
];
}
// Using a Process
CreateUserProcess::dispatch([
'name' => 'John Doe',
'email' => '[email protected]'
]);
// Using a Task without a process
SendWelcomeEmailTask::dispatch([
'user' => $user
]);Brain helps you organize your code into three main concepts:
- Processes: Complex business operations that might involve multiple steps
- Queries: Database queries and data retrieval operations
- Tasks: Sync/Async operations that can be called as part of a process or not
Each concept is organized within its respective domain, promoting clean architecture and separation of concerns.
composer testPlease see CONTRIBUTING for details.
If you discover any security-related issues, please email [email protected] instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.