Context
I have deployed a Laravel app using Laradock. This app has the feature to generate certificates in PDF and attach them to an email notification.
Everything works fine in Laravel Homestead (development environment), however, that feature is not working in Laradock production mode.
Goal
I have implemented a functionality to send a PDF certificate through an email notification as an attachment like so (using Laravel Filament):
<?php
use Illuminate\Support\Facades\Notification;
use App\Notifications\Certificates\CertificateIssued;
Notification::route('mail',[
$certificate->participant->email=>$certificate->participant->name,
])->notify(new CertificateIssued($record));
Now in the notification class CertificateIssued
I instantiate a Laravel Snappy PDF generator class
public function toMail($notifiable)
{
$generateCertificate = new GenerateCertificate();
//...
return
(new MailMessage)->markdown('emails.certificates.issued',[
//Some vars to be passed
])
->attachData($GenerateCertificate->attachPDF($this->certificate),$pdf_filename, [
'mime' => 'application/pdf',
]);
}
The Laravel Snappy PDF certificate class is like so:
use App\Models\Certificate;
use App\Services\Certificates\Qr\GenerateQr;
use Barryvdh\Snappy\Facades\SnappyPdf as PDF;
class GenerateCertificate
{
public function attachPdf(Certificate $certificate)
{
$pdf = $this->generate_pdf_certificate($certificate);
return $pdf->output();
}
public function generate_pdf_certificate(Certificate $certificate)
{
//QR code
$qr=$this->generate_png_qr($certificate);
//load blade view
$pdf = PDF::loadView('certificates.default',compact('certificate','qr'));
//Set PDF options. todo: abstract options away
$pdf = $this->setPdfOptions($pdf);
return $pdf;
}
public function genera_qr_png(Certificate $certificate)
{
$generateQR = new GenerateQr($this->generate_url_qr_verification($certificate),'png',130);
return $generateQR->image();
}
}
So I want the PDF attachment to be sent on an email notification. That piece of code is also used in a scheduler for newly generated certificates to be sent via email.
Error
But the email sending notification cannot be achieved due to an error in the wkhtmltopdf
[2022-05-19 16:40:53] production.ERROR: The exit status code '127' says something went wrong: stderr: "sh: /usr/local/bin/wkhtmltopdf: not found
.env
I have actually installed the WKHTMLTOPDF
in both the workspace and php-fpm containers.
###########################################################
################ Containers Customization #################
###########################################################
### WORKSPACE #############################################
WORKSPACE_INSTALL_WKHTMLTOPDF=true
### PHP_FPM ###############################################
PHP_FPM_INSTALL_WKHTMLTOPDF=true
Inside the container,
> docker exec -it --user=laradock project_workspace_1 zsh
➜ www git:(master) ✗ /usr/local/bin/wkhtmltopdf -V
wkhtmltopdf 0.12.6 (with patched qt)
➜ www git:(master) ✗ ls -lah /usr/local/bin
total 92M
drwxr-xr-x 1 root root 4.0K May 18 10:18 .
drwxr-xr-x 1 root root 4.0K Apr 16 2021 ..
-rwxr-xr-x 1 laradock www-data 2.6M Apr 22 19:48 composer
-rwxr-xr-x 1 root root 221 May 18 10:15 pip
-rwxr-xr-x 1 root root 221 May 18 10:15 pip3
-rwxr-xr-x 1 root root 221 May 18 10:15 pip3.10
-rwxr-xr-x 1 root root 221 May 18 10:15 pip3.8
-rwxr-xr-x 1 root root 238 May 18 10:15 virtualenv
-rwxr-xr-x 1 root root 208 May 18 10:15 wheel
-rwxr-xr-x 1 laradock www-data 45M Jun 10 2020 wkhtmltoimage
-rwxr-xr-x 1 laradock www-data 45M Jun 10 2020 wkhtmltopdf
I can see it is indeed installed in /usr/local/bin/
and I can actually execute it. Even if the owner is root:root
, but I changed it to laradock:www-data
but it made no difference.
What works and main question
I have another functionality to generate a certificate preview that works as a PDF download which does work. So why does this PDF preview download works and not the PDF attachment?
Here is a PDF generator preview that generates a PDF and prompts for download in the browser (using Laravel Filament):
public function certificate_preview(){
$event = Event::with('relationships...')->findOrFail($this->record->id);
$pdf = SnappyPdf::loadView('certificates.default',['event'=>$this->record])
->setPaper('Letter')
->setOrientation('Portrait')
->setOption('disable-external-links', false)
->setOption('enable-local-file-access', true)
->setOption('enable-internal-links' , true)
->output()
;
$disk = Storage::disk('pdf');
$disk->put('preview.pdf', $pdf);
return Storage::disk('pdf')->download('preview.pdf');//https://dev.to/fractalbit/tips-for-working-with-private-files-in-laravel-1g08
//dd(Storage::disk('pdf')->path('preview.pdf'));
//dd($this->record);
}
The previous code streams the PDF in the browser as a download option or it simply shows it right in the browser:
blob:https://myapp.com/long_uuid_string
where I can see perfectly the PDF! But why isn't the attachment working and outputs the
ERROR: The exit status code '127' says something went wrong: stderr: "sh: /usr/local/bin/wkhtmltopdf: not found" at /var/www/vendor/knplabs/knp-snappy/src/Knp/Snappy/AbstractGenerator.php:469
error?
Version info
The version of wkhtmltopdf
is:
➜ www git:(master) ✗ /usr/local/bin/wkhtmltopdf -V
wkhtmltopdf 0.12.6 (with patched qt)
➜ www git:(master) ✗ php -v
PHP 8.1.5 (cli) (built: Apr 21 2022 10:14:45) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.5, Copyright (c) Zend Technologies
with Zend OPcache v8.1.5, Copyright (c), by Zend Technologies
Problem identified
I have tested to send an email notification without the queue in jobs and it worked!
Looks like the php-worker
container should have the WKHTMLTOPDF
installed, which is missing in the .env
file.
I mean, there's no
### PHP_WORKER ############################################
PHP_WORKER_INSTALL_WKHTMLTOPDF=true
in the PHP-WORKER
section.
So now the question is, how to install that extension in the php-worker
container?