Search code examples
laravelwkhtmltopdflaravel-snappy

How to structure the PDF-related code so that it is not in routes file?


I'm using the Laravel Snappy PDF package barryvdh/laravel-snappy

It's all working perfectly, however the routes file now has a lot of information that I'd like to clean out of the routes file and put somewhere else.

Route::get('services/{service}/overview', function ($id) {
    $service = \App\Service::where('id', '=', $id)->first();
    $service->load('sbo_name', 'sbm_name', 'stm_name', 'get_lifecycle_status', 'items', 'environments', 'agreements', 'supported_services', 'required_services', 'serviceDependencies', 'readiness');
    $data['service'] = $service->toArray();
    $pdf = PDF::loadView('reports.services.overview', $data)
        ->setPaper('a4')
        ->setOrientation('portrait')
        ->setOption('footer-right', 'Page [page] of [toPage]     ')
        ->setOption('footer-left', '     Printed: [date]')
        ->setOption('footer-font-size', 8)
        ->setOption('footer-font-name', 'Arial')
        ->setOption('margin-top', 10)
        ->setOption('margin-left', 5)
        ->setOption('margin-right', 5)
        ->setOption('lowquality', false)
        ->setOption('dpi', 96)
        ->setOption('image-quality', 100);
    return $pdf->inline('Service Overview.pdf');
});

What's the best way to structure this? I don't want to repeat the pdf options for each new report either.


Solution

  • First of all, clean up your route files by moving them into a controller.

    Route::get('services/{service}/overview', ExportServiceController@show);

    // app/Http/Controllers/ExportServiceController.php
    class ExportServiceController extends Controller
    
    public function show($id) {
        return (new App/ExportServicePdf)->execute($id);
    
    }
    

    Further clean up your controller by moving the logic into its own class so it's reusable in other controller.

    // for example app/ExportServicePdf.php
    namespace App;
    
    class ExportServicePdf 
    {
       public function execute($id) 
       {
        $service = \App\Service::where('id', '=', $id)->first();
        $service->load('sbo_name', 'sbm_name', 'stm_name', 'get_lifecycle_status', 'items', 'environments', 'agreements', 'supported_services', 'required_services', 'serviceDependencies', 'readiness');
        $data['service'] = $service->toArray();
    
        $pdf = PDF::loadView('reports.services.overview', $data)
        ->setPaper('a4')
        ->setOrientation('portrait')
        ->setOption('footer-right', 'Page [page] of [toPage]     ')
        ->setOption('footer-left', '     Printed: [date]')
        ->setOption('footer-font-size', 8)
        ->setOption('footer-font-name', 'Arial')
        ->setOption('margin-top', 10)
        ->setOption('margin-left', 5)
        ->setOption('margin-right', 5)
        ->setOption('lowquality', false)
        ->setOption('dpi', 96)
        ->setOption('image-quality', 100);
         return $pdf->inline('Service Overview.pdf');
       }
    
    }
    

    A quick dig into the library, there's a public method setOptions() which accepts an array of options.

    In your ExportServicePdf class, you can further refactor it to:

    class ExportServicePdf
    {
       private $options = [
          'footer-font-size' => 8,
          'footer-font-name' => 'Arial',
          //...
        ];
    
        // Then you can do 
        public function execute($id)
        {
           $pdf = PDF::loadView('reports.services.overview', $data)
                 ->setPaper('a4')
                 ->setOrientation('portrait')
                 ->setOptions($this->options)
        }
    
    }