You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:29:51