1. Go to this page and download the library: Download avoqado-dev/laravel-usecase library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
// ✅ After: Clean Controller with Use Case
class UserController
{
public function store(CreateUserRequest $request)
{
$userId = Mediator::dispatch(new CreateUser(
name: $request->validated('name'),
email: $request->validated('email'),
password: $request->validated('password'),
));
return redirect()->route('users.show', $userId);
}
}
namespace App\UseCases\Users\CreateUser;
use AvoqadoDev\UseCase\Contracts\Request;
use AvoqadoDev\UseCase\Contracts\UsesDatabaseTransaction;
/**
* @see CreateUserHandler
* @implements Request<int>
*/
final readonly class CreateUser implements Request, UsesDatabaseTransaction
{
public function __construct(
public string $name,
public string $email,
public string $password,
) {}
public function transactionAttempts(): int
{
return 1;
}
}
namespace App\UseCases\Users\CreateUser;
use App\Models\User;
use App\Rules\EmailMustBeUnique;
use AvoqadoDev\UseCase\Contracts\Request;
use AvoqadoDev\UseCase\Contracts\RequestHandler;
use AvoqadoDev\UseCase\BusinessRules\Contracts\GuardsRules;
final readonly class CreateUserHandler implements RequestHandler
{
public function __construct(
private GuardsRules $guardsRules
) {}
/**
* @param CreateUser $request
*/
public function handle(Request $request): int
{
// Validate business rules
$this->guardsRules->guard(
new EmailMustBeUnique($request->email)
);
// Execute business logic
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
return $user->id;
}
}
use AvoqadoDev\UseCase\Facades\Mediator;
use App\UseCases\Users\CreateUser\CreateUser;
// From a controller
$userId = Mediator::dispatch(new CreateUser(
name: $request->validated('name'),
email: $request->validated('email'),
password: $request->validated('password'),
));
// From a job
$userId = Mediator::dispatch(new CreateUser(...));
// From a command
$userId = Mediator::dispatch(new CreateUser(...));
// From another use case
$userId = Mediator::dispatch(new CreateUser(...));
use AvoqadoDev\UseCase\Contracts\UsesDatabaseTransaction;
final readonly class CreateOrder implements Request, UsesDatabaseTransaction
{
public function transactionAttempts(): int
{
return 3; // Retry up to 3 times on deadlock
}
}
use AvoqadoDev\UseCase\Contracts\Cacheable;
use DateInterval;
final readonly class GetUserStats implements Request, Cacheable
{
public function __construct(public int $userId) {}
public function cacheKey(): string
{
return "user_stats_{$this->userId}";
}
public function ttl(): DateInterval
{
return new DateInterval('PT1H'); // Cache for 1 hour
}
}
use AvoqadoDev\UseCase\Contracts\UsesAtomicLock;
final readonly class ProcessPayment implements Request, UsesAtomicLock
{
public function __construct(public string $orderId) {}
public function lockKey(): string
{
return "payment_{$this->orderId}";
}
public function lockWaitSeconds(): int
{
return 10; // Wait up to 10 seconds for lock
}
}
use AvoqadoDev\UseCase\Contracts\ReadsFromWriteDatabase;
final readonly class GetRecentOrder implements Request, ReadsFromWriteDatabase
{
// No additional methods needed - just implement the interface!
}
final readonly class CreateOrderWithPayment implements
Request,
UsesDatabaseTransaction, // Wrap in transaction
UsesAtomicLock, // Prevent concurrent processing
ReadsFromWriteDatabase // Read from master DB
{
public function transactionAttempts(): int { return 3; }
public function lockKey(): string { return "order_{$this->orderId}"; }
public function lockWaitSeconds(): int { return 10; }
}
namespace App\Rules;
use App\Models\User;
use AvoqadoDev\UseCase\BusinessRules\Contracts\BusinessRule;
final readonly class EmailMustBeUnique implements BusinessRule
{
public function __construct(
public string $email,
public ?int $exceptUserId = null
) {}
public function passes(): bool
{
return User::query()
->where('email', $this->email)
->when($this->exceptUserId, fn($q) => $q->where('id', '!=', $this->exceptUserId))
->doesntExist();
}
public function message(): string
{
return 'The email address is already taken.';
}
public function code(): string
{
return 'email_must_be_unique';
}
public function context(): array
{
return ['email' => $this->email];
}
}
$this->guardsRules->guard(
new EmailMustBeUnique($request->email),
new PasswordMustBeStrong($request->password),
new UserMustBeAdult($request->birthdate)
);