### Rapid Setup with QuickStart Source: https://context7.com/thephpleague/tactician/llms.txt Use the QuickStart factory to instantiate a CommandBus with default middleware and handler mappings. ```php title}' created with due date {$command->dueDate}"; } } // Quick setup with command-to-handler mapping $commandBus = QuickStart::create([ CreateTaskCommand::class => new CreateTaskHandler() ]); // Dispatch the command $command = new CreateTaskCommand(); $command->title = 'Write documentation'; $command->dueDate = '2024-12-31'; $result = $commandBus->handle($command); // Output: "Task 'Write documentation' created with due date 2024-12-31" ``` -------------------------------- ### Integrate CallableLocator with DI Containers Source: https://context7.com/thephpleague/tactician/llms.txt Use CallableLocator to wrap your DI container's get method for seamless integration. Supports Symfony, PSR-11, and Laravel containers. ```php get($handlerId); }); // Using with Laravel $locator = new CallableLocator(function ($commandName) { $handlerClass = str_replace('Command', 'Handler', $commandName); return app()->make($handlerClass); }); $handlerMiddleware = new CommandHandlerMiddleware( new ClassNameExtractor(), $locator, new HandleInflector() ); ``` -------------------------------- ### Execute a Command with CommandBus Source: https://context7.com/thephpleague/tactician/llms.txt Manual configuration of the CommandBus using CommandHandlerMiddleware, a command name extractor, and an in-memory locator. ```php emailAddress} registered successfully!"; } } // Set up the locator with command-to-handler mapping $locator = new InMemoryLocator([ RegisterUserCommand::class => new RegisterUserHandler() ]); // Create the handler middleware $handlerMiddleware = new CommandHandlerMiddleware( new ClassNameExtractor(), $locator, new HandleInflector() ); // Create the command bus with middleware $commandBus = new CommandBus([$handlerMiddleware]); // Create and dispatch a command $command = new RegisterUserCommand(); $command->emailAddress = 'alice@example.com'; $command->password = 'secret123'; $result = $commandBus->handle($command); // Output: "User alice@example.com registered successfully!" ``` -------------------------------- ### Implement Custom Middleware in PHP Source: https://context7.com/thephpleague/tactician/llms.txt Create custom plugins by implementing the Middleware interface. The order of middleware in the CommandBus array determines the execution sequence. ```php logger = $logger; } public function execute($command, callable $next) { $commandClass = get_class($command); // Execute logic BEFORE command handling $this->logger->info("Starting: {$commandClass}"); try { // Pass to next middleware in chain $returnValue = $next($command); // Execute logic AFTER successful handling $this->logger->info("Completed: {$commandClass}"); return $returnValue; } catch (\Exception $e) { $this->logger->error("Failed: {$commandClass} - " . $e->getMessage()); throw $e; } } } // Transaction middleware example class TransactionMiddleware implements Middleware { private $entityManager; public function __construct($entityManager) { $this->entityManager = $entityManager; } public function execute($command, callable $next) { $this->entityManager->beginTransaction(); try { $returnValue = $next($command); $this->entityManager->commit(); return $returnValue; } catch (\Exception $e) { $this->entityManager->rollback(); throw $e; } } } // Stack middleware - order matters! $commandBus = new CommandBus([ new LoggingMiddleware($logger), new TransactionMiddleware($entityManager), $handlerMiddleware ]); $commandBus->handle($command); // Execution order: Logging -> Transaction -> Handler -> Transaction -> Logging ``` -------------------------------- ### Implement Self-Executing Commands with Custom Middleware Source: https://context7.com/thephpleague/tactician/llms.txt Create commands that execute themselves by implementing the SelfExecutingCommand interface and using a custom middleware. This bypasses traditional handlers for constrained domains. ```php context = $context; } public function execute($command, callable $next) { if (!$command instanceof SelfExecutingCommand) { return $next($command); // Pass to next middleware } return $command->execute($this->context); } } // Self-executing command example class IncrementCounterCommand implements SelfExecutingCommand { public function execute($context) { $context->counter++; return $context->counter; } } $context = new stdClass(); $context->counter = 0; $commandBus = new CommandBus([ new SelfExecutionMiddleware($context) ]); $commandBus->handle(new IncrementCounterCommand()); // counter = 1 $commandBus->handle(new IncrementCounterCommand()); // counter = 2 ``` -------------------------------- ### Map Commands to Handlers with InMemoryLocator Source: https://context7.com/thephpleague/tactician/llms.txt Configure command-to-handler mappings in memory. Missing handlers will trigger a MissingHandlerException. ```php new CreateUserHandler(), DeleteUserCommand::class => new DeleteUserHandler() ]); // Add handlers dynamically $locator->addHandler(new UpdateUserHandler(), UpdateUserCommand::class); // Get handler for a command $handler = $locator->getHandlerForCommand(CreateUserCommand::class); // Returns: CreateUserHandler instance // Missing handler throws exception try { $locator->getHandlerForCommand(UnknownCommand::class); } catch (\League actician\Exception\[MissingHandlerException](https://github.com/thephpleague/tactician/blob/master/src/Exception/MissingHandlerException.php) $e) { echo $e->getCommandName(); // "UnknownCommand" } ``` -------------------------------- ### Implement Custom HandlerLocator Source: https://context7.com/thephpleague/tactician/llms.txt Create a custom HandlerLocator by implementing the HandlerLocator interface for framework-specific or custom container integrations. Supports explicit mapping and convention-based resolution. ```php container = $container; $this->handlerMap = $handlerMap; } public function getHandlerForCommand($commandName) { // Check explicit mapping first if (isset($this->handlerMap[$commandName])) { $handlerId = $this->handlerMap[$commandName]; return $this->container->get($handlerId); } // Try convention-based resolution $handlerClass = str_replace('Command', 'Handler', $commandName); if ($this->container->has($handlerClass)) { return $this->container->get($handlerClass); } throw MissingHandlerException::forCommand($commandName); } } // Usage $locator = new ContainerHandlerLocator($container, [ // Explicit mappings for special cases 'App\Command\LegacyCommand' => 'legacy.handler.service', ]); ``` -------------------------------- ### Conditional Command Routing with CommandRouterMiddleware Source: https://context7.com/thephpleague/tactician/llms.txt Route commands to different command buses based on interface implementation using a custom middleware. Commands implementing AsyncCommand are sent to an async bus, while others proceed. ```php asyncBus = $asyncBus; } public function execute($command, callable $next) { if ($command instanceof AsyncCommand) { // Route to async queue return $this->asyncBus->handle($command); } // Continue to regular handler return $next($command); } } class SendWelcomeEmailCommand implements AsyncCommand { public $userId; } class CreateUserCommand implements SyncCommand { public $email; public $name; } // Queue handler for async commands $queueMiddleware = new class implements Middleware { public function execute($command, callable $next) { // Add to queue instead of executing immediately echo "Queued: " . get_class($command) . "\n"; return null; } }; $asyncBus = new CommandBus([$queueMiddleware]); $routerMiddleware = new CommandRouterMiddleware($asyncBus); $mainBus = new CommandBus([ $routerMiddleware, $handlerMiddleware ]); $mainBus->handle(new SendWelcomeEmailCommand()); // Queued $mainBus->handle(new CreateUserCommand()); // Executed synchronously ``` -------------------------------- ### Implement NamedCommand for Custom Command Names Source: https://context7.com/thephpleague/tactician/llms.txt Use the NamedCommand interface to define custom string names for commands, allowing for more flexible handler resolution. Map these custom names in the InMemoryLocator. ```php to}"; } } // Use NamedCommandExtractor to resolve command names $locator = new InMemoryLocator([ 'send_email' => new EmailHandler() // Map using custom name ]); $handlerMiddleware = new CommandHandlerMiddleware( new NamedCommandExtractor(), $locator, new HandleInflector() ); $commandBus = new CommandBus([$handlerMiddleware]); $commandBus->handle(new SendEmailCommand()); ``` -------------------------------- ### Prevent Concurrent Execution with LockingMiddleware Source: https://context7.com/thephpleague/tactician/llms.txt Use LockingMiddleware to queue commands that arrive while another command is currently being processed. ```php commandBus = $bus; } public function handle($command) { // This might trigger another command $this->commandBus->handle(new SendConfirmationEmail()); return "Order processed"; } } // LockingMiddleware queues nested commands until current one completes $lockingMiddleware = new LockingMiddleware(); $commandBus = new CommandBus([ $lockingMiddleware, $handlerMiddleware ]); // Commands dispatched inside handlers are queued and executed after $commandBus->handle(new ProcessOrderCommand()); ``` -------------------------------- ### Choose Method Name Inflectors Source: https://context7.com/thephpleague/tactician/llms.txt Select an inflector to define how Tactician resolves the handler method name based on the command class. Supports various conventions including 'handle', class name, and '__invoke'. ```php $handler->handle($command) $inflector = new HandleInflector(); // HandleClassNameInflector - method name includes command class name // CreateUserCommand => $handler->handleCreateUserCommand($command) $inflector = new HandleClassNameInflector(); // HandleClassNameWithoutSuffixInflector - strips "Command" suffix // CreateUserCommand => $handler->handleCreateUser($command) $inflector = new HandleClassNameWithoutSuffixInflector('Command'); // ClassNameInflector - uses camelCase class name // CreateUserCommand => $handler->createUserCommand($command) $inflector = new ClassNameInflector(); // InvokeInflector - uses __invoke magic method (great for single-use handlers) // CreateUserCommand => $handler->__invoke($command) $inflector = new InvokeInflector(); // Example with InvokeInflector for invokable handlers class CreateUserHandler { public function __invoke(CreateUserCommand $command) { return "Created user: {$command->email}"; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.