SONATA генерирует PDF с помощью knpSnappy

Я хочу интегрировать экспорт PDF в мое приложение SONATA ADMIN. Для этого я установил KnpSnappy Bundle и SonataExporterBundle. Я следовал старому учебнику, найденному в Google, но в конце концов он не работает.

config.yml:

knp_snappy:
pdf:
    enabled:    true
    binary:     /usr/local/bin/wkhtmltopdf 
    options:    []
image:
    enabled:    true
    binary:     /usr/local/bin/wkhtmltoimage 
    options:    []  
temporary_folder: %kernel.cache_dir%/snappy    

services.yml:

    sonata.admin.exporter:
        class: AppBundle\Export\Exporter
        calls:
            - ["setKnpSnappyPdf", ["@knp_snappy.pdf"]]
            - ["setTemplateEngine", ["@templating"] ]

в моем ModelAdmin я добавил это:

    public function getExportFormats() {
    return array_merge(parent::getExportFormats(), array('pdf'));
}

Я создал AppBundle/Export/Exporter.php:

    namespace AppBundle\Export;

use Exporter\Source\SourceIteratorInterface;
use Symfony\Component\HttpFoundation\Response;
use Sonata\AdminBundle\Export\Exporter as BaseExporter;

class Exporter extends BaseExporter
{
  protected $knpSnappyPdf;
  protected $templateEngine;

  public function getResponse($format, $filename, SourceIteratorInterface $source)
  {
    if ('pdf' != $format) {
      return parent::getResponse($format, $filename, $source);
    }

    $html = $this->templateEngine->renderView('AppBundle:Export:pdf.html.twig', array(
      'source' => $source
    ));
    $content = $this->knpSnappyPdf->getOutputFromHtml($html);

    return new Response($content, 200, array(
      'Content-Type' => 'application/pdf',
      'Content-Disposition' => sprintf('attachment; filename=%s', $filename)
    ));
  }

  public function setKnpSnappyPdf($service)
  {
    $this->knpSnappyPdf = $service;
  }

  public function setTemplateEngine($service)
  {
    $this->templateEngine = $service;
  }
}

ошибка:

RuntimeException:
Invalid "pdf" format, supported formats are : "csv, json, xls, xml"

  at vendor/sonata-project/exporter/src/Exporter.php:52
  at Exporter\Exporter->getResponse('pdf', 'export_model_2018_04_20_15_44_05.pdf', object(DoctrineORMQuerySourceIterator))
     (vendor/sonata-project/admin-bundle/src/Controller/CRUDController.php:952)
  at Sonata\AdminBundle\Controller\CRUDController->exportAction(object(Request))
     (vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:151)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:68)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:202)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (web/app_dev.php:31)
  at require('/var/www/html/acianovintra/web/app_dev.php')
     (vendor/symfony/symfony/src/Symfony/Bundle/WebServerBundle/Resources/router.php:42)

Можете ли вы сказать мне, что я сделал не так?

1 ответ

В проекте мне пришлось экспортировать некоторые данные в формате docx.

Для этого я написал собственный писатель:

<?php

namespace App\MyBundle\Utils\Exporter\Writer;

use Exporter\Writer\TypedWriterInterface;

class DocxWriter implements TypedWriterInterface
{
    /**
     * {@inheritdoc}
     */
    final public function getDefaultMimeType()
    {
        return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
    }

    /**
     * {@inheritdoc}
     */
    final public function getFormat()
    {
        return 'docx';
    }

    //...
}

Затем мне пришлось создать сервис для писателя и добавить тег:

// service.xml
 <?xml version="1.0" ?>

<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="app.exporter.writer.docx" class="App\MyBundle\Utils\Exporter\Writer\DocxWriter">
            <argument>php://output</argument>
            <tag name="sonata.exporter.writer"/>
        </service>
    </services>
</container>

в ExporterCompilerPass из пакета экспортеров, соната получить все услуги, отмеченные sonata.exporter.writer и передать их addWriter из Exporter учебный класс.

Чтобы интегрировать этого нового писателя в sonata admin, вам придется переопределить sonata.admin.exporter как вы уже сделали, за исключением того, что вы будете называть этого нового автора:

<?php
namespace App\MyBundle\Export;

use Exporter\Source\SourceIteratorInterface;
use Sonata\AdminBundle\Export\Exporter as BaseExporter;
use App\MyBundle\Utils\Exporter\Writer\DocxWriter;
use Symfony\Component\HttpFoundation\StreamedResponse;

class Exporter extends BaseExporter
{
    public function getResponse($format, $filename, SourceIteratorInterface $source)
    {
        switch ($format) {
            case 'docx':
                $writer = new DocxWriter('php://output');
                $contentType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
                break;
            default:
                return parent::getResponse($format, $filename, $source);
        }

        $callback = function () use ($source, $writer) {
            $handler = \Exporter\Handler::create($source, $writer);
            $handler->export();
        };

        return new StreamedResponse($callback, 200, array(
            'Content-Type' => $contentType,
            'Content-Disposition' => sprintf('attachment; filename="%s"', $filename),
        ));
    }
}

Благодаря этому вы сможете добавить свой формат pdf в администраторе, переопределяя getExportFormats метод.

Hpe это помогает

Другие вопросы по тегам