如何在Symfony中扩展final类的league:oauth:create-client命令
优雅扩展
league:oauth:create-client命令的两种方案 针对原命令是final类无法继承的问题,推荐以下两种无需手动复制参数的优雅实现方式:
方案一:事件订阅扩展(推荐)
利用Symfony的Console事件机制,直接给原命令添加自定义选项,并在命令执行完成后处理关联配置,完全不需要创建新命令。
1. 创建事件订阅者
<?php namespace App\EventSubscriber; use App\Entity\ClientConfiguration; use App\Repository\ClientRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleInitEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class CreateClientConfigSubscriber implements EventSubscriberInterface { public function __construct( private readonly ClientRepository $clientRepository, private readonly EntityManagerInterface $entityManager ) {} public static function getSubscribedEvents(): array { return [ ConsoleEvents::INIT => 'addCustomOption', ConsoleEvents::TERMINATE => 'handleCustomConfig', ]; } // 给原命令添加自定义选项 public function addCustomOption(ConsoleInitEvent $event): void { $command = $event->getCommand(); if ($command?->getName() !== 'league:oauth:create-client') { return; } $command->addOption( 'custom-config', null, InputOption::VALUE_REQUIRED, '为Client添加的自定义配置内容' ); } // 原命令执行成功后,创建关联的ClientConfiguration public function handleCustomConfig(ConsoleTerminateEvent $event): void { $command = $event->getCommand(); if ($command->getName() !== 'league:oauth:create-client' || $event->getExitCode() !== 0) { return; } $input = $event->getInput(); $output = $event->getOutput(); $customConfig = $input->getOption('custom-config'); if (!$customConfig) { return; } // 根据输入的Client名称查询刚创建的Client $clientName = $input->getArgument('name'); $client = $this->clientRepository->findOneBy(['name' => $clientName]); if (!$client) { $output->writeln('<error>未找到刚创建的Client</error>'); return; } // 创建并保存关联配置 $clientConfig = new ClientConfiguration(); $clientConfig->setClient($client); $clientConfig->setCustomConfig($customConfig); $this->entityManager->persist($clientConfig); $this->entityManager->flush(); $output->writeln(sprintf('<info>已为Client "%s"添加自定义配置</info>', $clientName)); } }
2. 注册订阅者服务
在config/services.yaml中添加:
services: App\EventSubscriber\CreateClientConfigSubscriber: arguments: - '@App\Repository\ClientRepository' - '@doctrine.orm.entity_manager' tags: - { name: kernel.event_subscriber }
用法
用户依然使用原命令,只需加上自定义选项即可:
bin/console league:oauth:create-client --custom-config="xxx" 客户端名称
方案二:自定义命令装饰原命令
创建新命令,注入原命令并复用其参数选项,同时添加自定义逻辑。此方案适合需要修改原命令执行流程的场景。
1. 创建自定义命令
<?php namespace App\Command; use App\Entity\ClientConfiguration; use App\Repository\ClientRepository; use Doctrine\ORM\EntityManagerInterface; use League\Bundle\OAuth2ServerBundle\Command\CreateClientCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class CustomCreateClientCommand extends Command { protected static $defaultName = 'app:oauth:create-client'; public function __construct( private readonly CreateClientCommand $originalCommand, private readonly ClientRepository $clientRepository, private readonly EntityManagerInterface $entityManager ) { parent::__construct(); } protected function configure(): void { parent::configure(); // 复用原命令的所有非全局参数/选项 $originalDefinition = $this->originalCommand->getDefinition(); foreach ($originalDefinition->getArguments() as $argument) { $this->getDefinition()->addArgument($argument); } foreach ($originalDefinition->getOptions() as $option) { if (!$option->isGlobal()) { $this->getDefinition()->addOption($option); } } // 添加自定义选项 $this->addOption( 'custom-config', null, InputOption::VALUE_REQUIRED, '为Client添加的自定义配置内容' ); } protected function execute(InputInterface $input, OutputInterface $output): int { // 先执行原命令创建Client $exitCode = $this->originalCommand->run($input, $output); if ($exitCode !== Command::SUCCESS) { return $exitCode; } // 处理自定义配置 $customConfig = $input->getOption('custom-config'); if (!$customConfig) { return Command::SUCCESS; } $clientName = $input->getArgument('name'); $client = $this->clientRepository->findOneBy(['name' => $clientName]); if (!$client) { $output->writeln('<error>未找到刚创建的Client</error>'); return Command::FAILURE; } $clientConfig = new ClientConfiguration(); $clientConfig->setClient($client); $clientConfig->setCustomConfig($customConfig); $this->entityManager->persist($clientConfig); $this->entityManager->flush(); $output->writeln(sprintf('<info>已为Client "%s"添加自定义配置</info>', $clientName)); return Command::SUCCESS; } }
用法
使用新命令执行:
bin/console app:oauth:create-client --custom-config="xxx" 客户端名称
内容的提问来源于stack exchange,提问作者Floxblah
相关产品推荐
相关产品推荐

