Shopware 6.5自定义文档类型生成PDF报错:无法找到对应生成器
Shopware 6.5.0.0 自定义文档类型PDF生成报错问题排查
我按照Shopware官方文档在Shopware 6.5.0.0中创建了名为order_confirmation的自定义文档类型,后台订单创建新文档时能识别该类型,但生成PDF时提示错误:Unable to find a document generator with type 'order_confirmation'。我参考官方invoice的服务配置编写了services.xml,也实现了对应的Document Renderer类,且已确认TYPE常量与迁移中定义的文档类型一致,但问题仍未解决。以下是相关代码:
services.xml
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="Dima\OrderConfirmation\Core\Checkout\Document\Renderer\OrderConfirmationRenderer"> <argument type="service" id="order.repository"/> <argument type="service" id="Shopware\Core\Checkout\Document\Service\DocumentConfigLoader"/> <argument type="service" id="Shopware\Core\Checkout\Document\Twig\DocumentTemplateRenderer"/> <argument type="service" id="Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface"/> <argument>%kernel.project_dir%</argument> <tag name="document.renderer" /> </service> </services> </container>
OrderConfirmationRenderer
<?php declare(strict_types=1); namespace Dima\OrderConfirmation\Core\Checkout\Document\Renderer; use Shopware\Core\Checkout\Document\Renderer\AbstractDocumentRenderer; use Shopware\Core\Checkout\Document\Renderer\DocumentRendererConfig; use Shopware\Core\Checkout\Document\Renderer\RenderedDocument; use Shopware\Core\Checkout\Document\Renderer\RendererResult; use Shopware\Core\Checkout\Document\Service\DocumentConfigLoader; use Shopware\Core\Checkout\Document\Struct\DocumentGenerateOperation; use Shopware\Core\Checkout\Document\Twig\DocumentTemplateRenderer; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException; use Shopware\Core\System\Locale\LocaleEntity; use Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface; class OrderConfirmationRenderer extends AbstractDocumentRenderer { public const DEFAULT_TEMPLATE = '@DimaOrderConfirmation/documents/order_confirmation.html.twig'; final public const TYPE = 'order_confirmation'; /** * @internal */ public function __construct( private readonly EntityRepository $orderRepository, private readonly DocumentConfigLoader $documentConfigLoader, private readonly DocumentTemplateRenderer $documentTemplateRenderer, private readonly NumberRangeValueGeneratorInterface $numberRangeValueGenerator, private readonly string $rootDir, ) { } public function supports(): string { return self::TYPE; } /** * @param array<DocumentGenerateOperation> $operations */ public function render(array $operations, Context $context, DocumentRendererConfig $rendererConfig): RendererResult { $ids = \array_map(fn (DocumentGenerateOperation $operation) => $operation->getOrderId(), $operations); if (empty($ids)) { return new RendererResult(); } $result = new RendererResult(); $template = self::DEFAULT_TEMPLATE; $orders = $this->orderRepository->search(new Criteria($ids), $context)->getEntities(); foreach ($orders as $order) { $orderId = $order->getId(); try { $operation = $operations[$orderId] ?? null; if ($operation === null) { continue; } $config = clone $this->documentConfigLoader->load(self::TYPE, $order->getSalesChannelId(), $context); $config->merge($operation->getConfig()); $number = $config->getDocumentNumber() ?: $this->getNumber($context, $order, $operation); $now = (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT); $config->merge([ 'documentDate' => $operation->getConfig()['documentDate'] ?? $now, 'documentNumber' => $number, 'custom' => [ 'invoiceNumber' => $number, ], ]); // If document is uploaded manually if ($operation->isStatic()) { $doc = new RenderedDocument('', $number, $config->buildName(), $operation->getFileType(), $config->jsonSerialize()); $result->addSuccess($orderId, $doc); continue; } /** @var LocaleEntity $locale */ $locale = $order->getLanguage()->getLocale(); $html = $this->documentTemplateRenderer->render( $template, [ 'order' => $order, 'config' => $config, 'rootDir' => $this->rootDir, 'context' => $context, ], $context, $order->getSalesChannelId(), $order->getLanguageId(), $locale->getCode() ); $doc = new RenderedDocument( $html, $number, $config->buildName(), $operation->getFileType(), $config->jsonSerialize(), ); $result->addSuccess($orderId, $doc); } catch (\Throwable $exception) { $result->addError($orderId, $exception); } } return $result; } public function getDecorated(): AbstractDocumentRenderer { throw new DecorationPatternException(self::class); } private function getNumber(Context $context, OrderEntity $order, DocumentGenerateOperation $operation): string { return $this->numberRangeValueGenerator->getValue( 'document_' . self::TYPE, $context, $order->getSalesChannelId(), $operation->isPreview() ); } }
问题解决方法
1. 完善服务标签配置
你的services.xml中document.renderer标签缺少type属性,Shopware无法将Renderer与对应的文档类型关联。修改标签部分:
<tag name="document.renderer" type="order_confirmation" />
这个属性明确告诉系统该Renderer服务负责处理order_confirmation类型的文档。
2. 验证文档类型迁移
确保迁移文件中插入的document_type记录的technical_name与Renderer的TYPE常量完全一致(大小写敏感),示例迁移代码:
$this->connection->insert('document_type', [ 'technical_name' => 'order_confirmation', 'name' => '订单确认单', 'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT), ]);
3. 清除缓存并重建容器
修改服务配置后执行以下命令:
bin/console cache:clear bin/console cache:warmup
4. 检查模板路径
确认@DimaOrderConfirmation/documents/order_confirmation.html.twig模板存在于插件的Resources/views/documents/目录下,路径和文件名必须完全匹配。
内容的提问来源于stack exchange,提问作者Darkice997
相关产品推荐
相关产品推荐

