I've made a Bundle and a REST controller inside. The "index" method return array in JSON-format, it's ok:
MyBundle/Controller/Api/Rest/BaconController.php
class BaconController extends Controller implements ClassResourceInterface
{
    /**
     * @var Request $request
     * @return array
     * @Rest\View
     */
    public function cgetAction(Request $request)
    {
        $mediaType = $request->attributes->get('media_type');
        $format = $request->getFormat($mediaType);
        my_dump($format);
        return array(
             array("id" => 1, "title" => "hello",),
             array("id" => 2, "title" => "there",),
        );
    }
}
MyBundle/Resources/config/api/routing_rest.yml
my_api_rest_bacon:
    type: rest
    resource: "MyBundle:Api/Rest/Bacon"
    name_prefix: api_rest_bacon_
    prefix: /my/bacon
So, at this point JSON results get returned perfectly:
mysite.com/app_dev.php/api/my/bacon/bacons.json
returns my array.
But now I need to get my controller generate a PDF with the data. So I want it to return PDF document when I call:
mysite.com/app_dev.php/api/my/bacon/bacons.pdf
I've found some half-manuals: RSS view handler, RSS config.ynal, CSV issue with answers. And tried to make something similar:
I've added these lines to
Symfony/app/config/config.yml
framework:
    [...some old stuff here...]
    request:
        formats:
            pdf: 'application/pdf'
fos_rest:
    body_converter:
        enabled:              true
    format_listener:
        rules:
            # Prototype array
            -
                # URL path info
                path:                 ~
                # URL host name
                host:                 ~
                prefer_extension:     true
                fallback_format:      html
                priorities:           [html,json]
            -
                path:                 ~
                host:                 ~
                prefer_extension:     true
                fallback_format:      pdf
                priorities:           [pdf]
    view:
        # @View or @Template
        view_response_listener: force #true
        formats:
            json: true
            pdf: true
            xls: true
            html: false
        templating_formats:
            pdf: false
            xls: false
        mime_types: {'pdf': ['application/pdf']}
    routing_loader:
        default_format: html
    param_fetcher_listener: true
    body_listener: true
    allowed_methods_listener: true
services:
    my.view_handler.pdf:
        class: Lobster\MyBundle\View\PdfViewHandler
    my.view_handler:
        parent: fos_rest.view_handler.default
        calls:
            - ['registerHandler', [ 'pdf', [@my.view_handler.pdf, 'createResponse'] ] ]
MyBundle/View/PdfViewHandler.php
namespace Lobster\MyBundle\View;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class PdfViewHandler
{
    public function createResponse(ViewHandler $handler, View $view, Request $request, $format)
    {
        my_dump('pdf createResponse started');
        $pdf = "some pdf";
        return new Response($pdf, 200, $view->getHeaders());
    }
}
So now when I call
mysite.com/app_dev.php/api/my/bacon/bacons.pdf
I see an error An Exception was thrown while handling: Format html not supported, handler must be implemented and my function my_dump saves to a text file info about file format: it is html, not pdf.
Also pdf createResponse didn't work. Why?
So I've found the solution (I will describe how to enable 2 output formats: PDF and XLS):
1) This section in config.yml is not needed:
framework:
    [...some old stuff here...]
    request:
        formats:
            pdf: 'application/pdf'
2) fos_rest.format_listener section in config.yml should look like this:
format_listener:
    rules:
        -
            path:                 '^/api/my/bacon.*\.xls$'
            host:                 ~
            prefer_extension:     false
            fallback_format:      json
            priorities:           [xls, json]
        -
            path:                 '^/api/my/bacon.*\.pdf$'
            host:                 ~
            prefer_extension:     false
            fallback_format:      json
            priorities:           [pdf, json]
        -
            path:                 ~
            host:                 ~
            prefer_extension:     true
            fallback_format:      html
            priorities:           [html,json]
3) need to add service section into fos_rest in config.yml
fos_rest:
[...]
    service:
        view_handler: my.view_handler
4) services root section in config.yml should look like
services:
    my.view_handler.xls:
        class: Lobster\MyBundle\View\XlsViewHandler
    my.view_handler.pdf:
        class: Lobster\MyBundle\View\PdfViewHandler
    my.view_handler:
        parent: fos_rest.view_handler.default
        calls:
            - ['registerHandler', ['xls', [@my.view_handler.xls, 'createResponse'] ] ]
            - ['registerHandler', ['pdf', [@my.view_handler.pdf, 'createResponse'] ] ]
And this is it. Now it works perfect
If files will have different data content, then Controller could as well generate file on their own, returning results in BinaryFileResponse.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With