PHP项目Symfony控制台命令

wen PHP项目 3

本文目录导读:

PHP项目Symfony控制台命令

  1. 创建控制台命令
  2. 运行命令
  3. 实用命令示例
  4. 高级特性
  5. 定时任务(Cron)

我来详细介绍PHP Symfony框架中控制台命令的创建和使用。

创建控制台命令

基础命令类

// src/Command/MyCustomCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class MyCustomCommand extends Command
{
    // 命令名称(必需)
    protected static $defaultName = 'app:my-custom';
    protected function configure()
    {
        $this
            ->setDescription('执行自定义任务')
            ->setHelp('这个命令用于执行特定的业务逻辑')
            // 添加参数
            ->addArgument('name', InputArgument::REQUIRED, '用户名称')
            ->addArgument('age', InputArgument::OPTIONAL, '年龄', 25)
            // 添加选项
            ->addOption('format', 'f', InputOption::VALUE_REQUIRED, '输出格式(json/text)', 'text')
            ->addOption('verbose', 'v', InputOption::VALUE_NONE, '是否详细输出');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // 获取参数
        $name = $input->getArgument('name');
        $age = $input->getArgument('age');
        $format = $input->getOption('format');
        $isVerbose = $input->getOption('verbose');
        // 输出信息
        $output->writeln('<info>开始执行命令...</info>');
        if ($isVerbose) {
            $output->writeln(sprintf('处理用户: %s (年龄: %d)', $name, $age));
        }
        // 根据格式输出
        if ($format === 'json') {
            $output->writeln(json_encode([
                'name' => $name,
                'age' => $age,
                'message' => '执行成功'
            ]));
        } else {
            $output->writeln('<comment>任务完成!</comment>');
        }
        // 返回执行状态
        return Command::SUCCESS; // 或 Command::FAILURE
    }
}

运行命令

# 基本用法
php bin/console app:my-custom John
# 带参数
php bin/console app:my-custom John 30
# 带选项
php bin/console app:my-custom John --format=json -v
# 查看帮助
php bin/console help app:my-custom

实用命令示例

数据库相关命令

// src/Command/DatabaseCleanupCommand.php
class DatabaseCleanupCommand extends Command
{
    protected static $defaultName = 'app:cleanup-database';
    private $entityManager;
    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
        parent::__construct();
    }
    protected function configure()
    {
        $this
            ->setDescription('清理过期数据')
            ->addOption('days', null, InputOption::VALUE_REQUIRED, '保留天数', 30);
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $days = $input->getOption('days');
        $date = new \DateTime("-{$days} days");
        // 删除过期日志
        $logs = $this->entityManager
            ->getRepository(Log::class)
            ->createQueryBuilder('l')
            ->delete()
            ->where('l.createdAt < :date')
            ->setParameter('date', $date)
            ->getQuery()
            ->execute();
        $output->writeln(sprintf('已删除 %d 条过期记录', $logs));
        return Command::SUCCESS;
    }
}

数据导入命令

// src/Command/ImportUsersCommand.php
class ImportUsersCommand extends Command
{
    protected static $defaultName = 'app:import-users';
    private $entityManager;
    private $projectDir;
    public function __construct(EntityManagerInterface $entityManager, string $projectDir)
    {
        $this->entityManager = $entityManager;
        $this->projectDir = $projectDir;
        parent::__construct();
    }
    protected function configure()
    {
        $this
            ->setDescription('从CSV文件导入用户')
            ->addArgument('file', InputArgument::REQUIRED, 'CSV文件路径');
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $file = $input->getArgument('file');
        // 创建进度条
        $progress = new ProgressBar($output, 100);
        $progress->start();
        if (!file_exists($file)) {
            $output->writeln("<error>文件不存在: {$file}</error>");
            return Command::FAILURE;
        }
        $handle = fopen($file, 'r');
        $headers = fgetcsv($handle);
        $count = 0;
        while (($row = fgetcsv($handle)) !== false) {
            $user = new User();
            $user->setName($row[0]);
            $user->setEmail($row[1]);
            $this->entityManager->persist($user);
            $count++;
            // 批量刷新
            if ($count % 20 === 0) {
                $this->entityManager->flush();
                $progress->advance();
            }
        }
        fclose($handle);
        $this->entityManager->flush();
        $progress->finish();
        $output->writeln("\n<info>成功导入 {$count} 个用户</info>");
        return Command::SUCCESS;
    }
}

高级特性

命令分组

// 将命令分组
protected static $defaultName = 'user:create';
protected static $defaultName = 'user:delete';
protected static $defaultName = 'email:send';

交互式输入

use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Question\ConfirmationQuestion;
protected function execute(InputInterface $input, OutputInterface $output): int
{
    $helper = $this->getHelper('question');
    // 确认问题
    $question = new ConfirmationQuestion(
        '确定要执行此操作吗? (y/n) ',
        false
    );
    if (!$helper->ask($input, $output, $question)) {
        $output->writeln('<error>操作已取消</error>');
        return Command::SUCCESS;
    }
    // 隐藏输入(如密码)
    $question = new Question('请输入密码: ');
    $question->setHidden(true);
    $question->setHiddenFallback(false);
    $password = $helper->ask($input, $output, $question);
    return Command::SUCCESS;
}

表格输出

use Symfony\Component\Console\Helper\Table;
protected function execute(InputInterface $input, OutputInterface $output): int
{
    $table = new Table($output);
    $table
        ->setHeaders(['ID', '名称', '邮箱'])
        ->setRows([
            [1, '张三', 'zhangsan@example.com'],
            [2, '李四', 'lisi@example.com'],
        ]);
    $table->render();
    return Command::SUCCESS;
}

定时任务(Cron)

config/services.yaml 中配置:

services:
    App\Command\MyScheduledCommand:
        tags:
            - { name: console.command }

Crontab配置:

# 每天凌晨2点执行
0 2 * * * /usr/bin/php /path/to/project/bin/console app:cleanup-database --days=30
# 每小时执行
0 * * * * /usr/bin/php /path/to/project/bin/console app:send-emails

这些命令可以帮助你自动化各种任务,从简单的数据处理到复杂的业务逻辑实现。

抱歉,评论功能暂时关闭!