基于工厂方法的PDF生成器架构疑问及ContainerInterface问题求助
问题描述
我在服务编排上遇到了问题,想要实现一个基于Provider的PDF生成器,预期流程是:带Provider参数的API请求 → GeneratorController::generate → 工厂方法 → 对应Generator类服务。目前想用Twig生成PDF,但碰到了ContainerInterface相关问题,不确定当前实现思路是否正确,想确认方向是否可行。
GeneratorController代码
public function generate($provider, Request $request): Response { $generator = $this->factory->createGenerator($provider); $content = json_decode($request->getContent(), true); $generator->generate($content['params']); return new JsonResponse($generator->getData()); }
GeneratorFactory代码
class GeneratorFactory { public function createGenerator($generator): Generator { $generatorName = "App\Generators\" . ucwords($generator) . "\Generator"; if (!class_exists($generatorName)) { throw new \Exception("We dont find genarator with name: " . $generator); } return new $generatorName; } }
工厂生成的Generator类代码
public function __construct() { $this->object = new GeneratorObject; $this->validator = new Validator; $this->service = new PdfService(); } public function generate(array $params): void { $valided = $this->validator->Validate($params); if (!$valided) { throw new Exception("Invalid parameters", 1); } $this->setDataToObject($params); $pdf = $this->service->createPdf($this->object); $this->data = $pdf; }
PDF服务类代码
public function createPdf(GeneratorObject $pdfObject): string { $url = ''; $html = $this->templating->render('pdf/index.html.twig',[$pdfObject]); return $url; }
思路分析与优化建议
整体方向是对的
你采用的「工厂模式+Provider路由」思路符合服务编排的开闭原则,新增Provider类型时只需添加对应Generator类,无需修改工厂和控制器代码,扩展性良好。
核心问题:依赖硬编码导致ContainerInterface异常
你遇到的ContainerInterface问题,根源在于手动实例化依赖:
- Generator类构造函数里直接
new PdfService(),但PdfService依赖的Twig服务(templating)是由Symfony容器管理的,手动实例化无法注入容器中的服务,必然会出现依赖缺失错误。 - 同理,Validator、GeneratorObject如果是需要容器注入的服务,手动实例化也会引发类似问题。
优化方案
让工厂依赖容器,实现依赖注入
修改GeneratorFactory,注入容器后通过服务ID获取Generator实例,而非手动new:class GeneratorFactory { private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function createGenerator($provider): Generator { $serviceId = "app.generator." . strtolower($provider); if (!$this->container->has($serviceId)) { throw new \Exception("Generator not found for provider: " . $provider); } return $this->container->get($serviceId); } }同时在
services.yaml中注册所有Generator类:app.generator.invoice: class: App\Generators\Invoice\Generator arguments: ['@validator', '@App\Services\PdfService']Generator类通过构造函数注入依赖
去掉手动实例化,改为依赖注入:private $object; private $validator; private $service; public function __construct(Validator $validator, PdfService $pdfService) { $this->object = new GeneratorObject; // 若GeneratorObject有依赖,同样注入 $this->validator = $validator; $this->service = $pdfService; }PdfService注入Twig服务
确保Twig环境通过构造函数注入:private $twig; public function __construct(Environment $twig) { $this->twig = $twig; } public function createPdf(GeneratorObject $pdfObject): string { $html = $this->twig->render('pdf/index.html.twig', ['data' => $pdfObject]); // 补充HTML转PDF逻辑(如使用wkhtmltopdf/TCPDF) $pdfUrl = $this->savePdfAndReturnUrl($html); return $pdfUrl; }
内容的提问来源于stack exchange,提问作者KPHP
相关产品推荐
相关产品推荐

