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

Symfony 4.1命令中执行路由:解决PDF生成超时问题

在Symfony 4.1命令行中执行路由生成PDF

完全可以通过RouterInterface和HttpKernelInterface实现命令行环境下执行路由的需求,核心思路是模拟HTTP请求流程,让内核处理路由对应的控制器逻辑,以下是具体实现方案:

实现步骤

1. 注入核心服务

在自定义命令类的构造函数中注入RouterInterface(用于生成路由URI、设置请求上下文)、HttpKernelInterface(用于处理模拟的HTTP请求),以及你需要的其他服务(如文件存储、邮件服务)。

2. 手动设置路由上下文

命令行环境没有默认的HTTP请求上下文,需要手动指定请求的scheme(http/https)和host,确保路由能生成正确的URI。

3. 生成路由并处理请求

通过路由生成目标URI,创建Request对象后交给内核处理,获取响应中的PDF内容。

4. 后续处理

将PDF内容保存到服务器指定目录,再发送邮件通知用户下载链接。

代码示例

// src/Command/GeneratePersonPdfCommand.php
namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;

class GeneratePersonPdfCommand extends Command
{
    protected static $defaultName = 'app:generate-person-pdf';

    private $router;
    private $httpKernel;
    private $filesystem;
    private $mailer;
    private $pdfStorageDir;

    public function __construct(
        RouterInterface $router,
        HttpKernelInterface $httpKernel,
        Filesystem $filesystem,
        MailerInterface $mailer,
        string $pdfStorageDir
    ) {
        parent::__construct();
        $this->router = $router;
        $this->httpKernel = $httpKernel;
        $this->filesystem = $filesystem;
        $this->mailer = $mailer;
        $this->pdfStorageDir = $pdfStorageDir;
    }

    protected function configure()
    {
        $this
            ->addArgument('personId', InputArgument::REQUIRED, '要生成PDF的用户ID')
            ->setDescription('通过路由生成用户PDF并发送下载通知邮件');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $personId = $input->getArgument('personId');

        // 设置路由上下文,确保生成正确的URI
        $this->router->getContext()->setScheme('https');
        $this->router->getContext()->setHost('mysite.com');

        // 生成目标路由的URI
        try {
            $uri = $this->router->generate('print_person', ['id' => $personId]);
        } catch (\Exception $e) {
            $output->writeln(sprintf('路由生成失败:%s', $e->getMessage()));
            return Command::FAILURE;
        }

        // 创建模拟HTTP请求并交由内核处理
        $request = Request::create($uri, 'GET');
        $response = $this->httpKernel->handle($request, HttpKernelInterface::MASTER_REQUEST, false);

        // 检查响应状态
        if (!$response->isSuccessful()) {
            $output->writeln(sprintf('请求处理失败,状态码:%d', $response->getStatusCode()));
            return Command::FAILURE;
        }

        // 保存PDF到服务器
        $pdfFilename = sprintf('person_%d.pdf', $personId);
        $pdfPath = $this->pdfStorageDir . '/' . $pdfFilename;
        $this->filesystem->dumpFile($pdfPath, $response->getContent());

        // 发送下载通知邮件
        $downloadUrl = sprintf('https://mysite.com/download/pdf/%s', $pdfFilename);
        $email = (new Email())
            ->from('noreply@mysite.com')
            ->to('user@example.com') // 替换为实际用户邮箱
            ->subject('你的PDF已生成')
            ->text(sprintf('点击链接下载PDF:%s', $downloadUrl));

        $this->mailer->send($email);

        $output->writeln(sprintf('PDF生成完成,路径:%s', $pdfPath));
        return Command::SUCCESS;
    }
}

注意事项

  • 认证处理:如果print_person路由需要用户认证,命令行环境没有默认会话,需手动设置认证令牌(通过TokenStorageInterface),或在控制器中添加逻辑允许命令行请求跳过认证(比如检查$request->isCli())。
  • 路径配置:pdfStorageDir需要在services.yaml中配置为参数,示例:
    parameters:
        pdf_storage_dir: '%kernel.project_dir%/public/pdf'
    
  • 异常处理:添加足够的异常捕获逻辑(如文件写入失败、邮件发送失败),确保任务能返回正确状态码,方便cron日志排查问题。
  • 资源控制:若PDF生成耗时极长,需确保服务器资源充足,可添加任务锁机制避免重复执行。

内容的提问来源于stack exchange,提问作者Szatmari Daniel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:07:28