A feature-rich Laravel wrapper for the WeasyPrint Document Factory.
See the Changelog | View the Upgrade Guide
The table below outlines supported versions, where current
means it the latest supported version, and maintenance
is supported by way of bug and security fixes only.
Note: As of version 8, WeasyPrint < 59 is not supported. If you rely on older versions, please use the applicable package version.
Note: As of version 8.1, WeasyPrint 61 is supported. Version 9 of the package will drop support for PHP 8.1, and WeasyPrint < 61.
Package Version | WeasyPrint Version | Laravel | PHP | Branch |
---|---|---|---|---|
8.1.x (latest) |
^59.0|^60.0|^61.0 (semver) |
10.x, 11.x | 8.1+ | 8.x |
8.0.x (current) |
^59.0|^60.0 (semver) |
10.x | 8.1+ | 8.x |
7.x (maintenance) |
≥ v53, < 59 (unchecked) | 10.x | 8.1+ | 7.x |
First make sure WeasyPrint v59+ is installed on your system.
Then, install the package with Composer:
$ composer require rockett/weasyprint
The package will be discovered and registered automatically.
If you would like to publish the default configuration, you may run the command shown below. It’s not recommended to do this however, as the config file does read your environment variables. It is recommended to publish the config file only when you are changing the names of the variables, or you need to resolve them in another way.
$ php artisan vendor:publish --tag=weasyprint.config
WeasyPrint for Laravel is easy to use.
All you need is an instance of the WeasyPrint service class, which can be resolved from the Laravel Service Container as a scoped singleton.
Once you have an instance, you can prepare your source, change config (if needed), and build the output for processing by your application.
There are three ways to get an instance of the WeasyPrint service class.
This contract may either be used in dependency injection, or via the global app()
or resolve()
helper functions.
Dependency Injection:
use WeasyPrint\Contracts\Factory;
class GeneratePDF
{
public function __invoke(Factory $weasyprint)
{
// You now have access to a WeasyPrint instance named $weasyprint.
$weasyprint->prepareSource('<p>WeasyPrint rocks!</p>');
}
}
Global Helpers:
use WeasyPrint\Contracts\Factory;
$weasyprint = app(Factory::class); // or resolve(Factory::class)
// You now have access to a WeasyPrint instance named $weasyprint.
$weasyprint->prepareSource('<p>WeasyPrint rocks!</p>');
If you do not want to use dependency injection, and you do not want to use the app()
or resolve()
helpers, you can use the service instance helper instead. This is the same as calling one the global helpers.
use WeasyPrint\Service;
$weasyprint = Service::instance();
$weasyprint->prepareSource('<p>WeasyPrint rocks!</p>');
Similar to the other options, using the Facade will give you an instance of the WeasyPrint service singleton. The Facade resolves to the Factory
contract which, in turn, provides you with the singleton.
use WeasyPrint\Facade as WeasyPrint;
$source = '<p>WeasyPrint rocks!</p>';
$service = WeasyPrint::prepareSource($source);
Note: For the sake of simplicity, the facade option will be used throughout the remainder of this documentation.
Next step is to prepare the source – that is, the data WeasyPrint will use to render your PDF and return it to your application for processing.
The prepareSource
method takes a single argument that represents your source data.
Here’s the method signature:
use WeasyPrint\Objects\Source;
use Illumintate\Support\Contracts\Renderable;
public function prepareSource(Source|Renderable|string $source): static
The $source
argument may be one of the following:
WeasyPrint\Objects\Source
if you are preparing a Source instance manually. TheSource::new
constructor accepts aRenderable
or astring
.Illumintate\Support\Contracts\Renderable
if you are passing in an instance of something that is renderable, ie it implements therender
method. This might be a Laravel View, which also accepts an array of data. For more information, see the Laravel documentation on views.string
if you are passing in an already-rendered piece of HTML, or asking WeasyPrint to fetch and render the source from an external URL.
If you would like to use the Source
object, you may instantiate it as follows:
use WeasyPrint\Objects\Source;
use WeasyPrint\Facade as WeasyPrint;
$source = Source::new('<p>WeasyPrint rocks!</p>');
$service = WeasyPrint::prepareSource($source);
A Renderable is simply a class that implements the Renderable
contract, described above.
use Illumintate\Support\Contracts\Renderable;
class MyRenderable implements Renderable
{
public function render(): string
{
return 'string with rendered HTML data…';
}
}
// …
$service = WeasyPrint::prepareSource(new MyRenderable);
If you prefer to pass in a string:
use WeasyPrint\Facade as WeasyPrint;
$service = WeasyPrint::prepareSource('<p>WeasyPrint rocks!</p>');
Now that you know how to get a service class instance and prepare the source input, you are ready to build the output.
To do this, you can call the build()
method, which will return an instance of WeasyPrint\Objects\Output
.
$output = $service->build();
The $output
object makes the following methods available:
public function download(string $filename, array $headers = [], bool $inline = false): StreamedResponse;
This method creates a Symfony StreamedResponse
that may be used to download the PDF to the client (browser).
public function inline(string $filename, array $headers = []): StreamedResponse;
Likewise, this method does the same, except it uses an inline attachment so that it may be displayed in the browser. This is just a shorthand for download
, setting $inline
to true
.
public function putFile(string $path, ?string $disk = null, array $options = []): bool;
This method forwards the data to Laravel’s Filesystem using the Storage
facade’s put
method, which gives you the ability to save the PDF to disk.
public function getData(): string;
This method returns the raw PDF data as a string.
If you would prefer to not call build()
, you can simply omit it and call the methods that are available on the Output
class. The service will implicitly build the PDF for you, and then call the applicable method on the output.
WeasyPrint has the ability to add attachments to output PDFs. To add an attachment, call the addAttachment
method:
$service = WeasyPrint::prepareSource('<p>WeasyPrint rocks!</p>')
->addAttachment('/absolute/path/to/attachment');
->addAttachment('/as/many/as/you/like');
Naturally this has no effect when outputting to PNG.
This package comes preloaded with a sensible set of default configs. These defaults are sourced from the package directly, unless you publish the config into your application.
For additional type-safety, default config is prepared using the Config
class. It must be cast to an array
, and the service instance will automatically hydrate it when needed.
Once the default config has been loaded into a service instance, you can change it one of two ways:
Tap the Config
Tapping involves the use of a callback that mutates the existing Config
object in the service instance, using the tapConfig
method.
You need only change the properties you want to change, and everything else will remain untouched (derived from the defaults).
use WeasyPrint\Objects\Config;
$service->tapConfig(
static function (Config $config): void {
$config->binary = '/absolute/path/to/weasyprint';
$config->timeout = 5000;
}
);
Overriding the Config
To override the config with a brand new Config
object, you can call setConfig
, which accepts the object and sets it on the service instance.
use WeasyPrint\Objects\Config;
$service->setConfig(
new Config(
binary: '/absolute/path/to/weasyprint',
timeout: 5000,
)
);
Note: Unlike tapping, overriding the config will disregard any defaults that you might have set in your config file, or those set in the unpublished config file. Instead, the defaults are derived from the constructor of
Config
object.
Below are the default config options, which you can override per the above.
return (array) new \WeasyPrint\Objects\Config(
/**
* The path to the WeasyPrint binary on your system. If it is available on
* your system globally, the package will find and use it. If not, then
* you will need to specify the absolute path.
*/
binary: env('WEASYPRINT_BINARY'),
/**
* The cache prefix to use for the temporary filename.
*/
cachePrefix: env('WEASYPRINT_CACHE_PREFIX', 'weasyprint_cache'),
/**
* The amount of seconds to allow a conversion to run for.
*/
timeout: (int) env('WEASYPRINT_TIMEOUT', 120),
/**
* Force the input character encoding. utf-8 is recommended.
*/
inputEncoding: env('WEASYPRINT_INPUT_ENCODING', 'utf-8'),
/**
* Enable or disable HTML Presentational Hints.
*/
presentationalHints: (bool) env('WEASYPRINT_PRESENTATIONAL_HINTS', true),
/**
* Optionally set the media type to use for CSS @media.
* Defaults to `print` at binary-level.
*/
mediaType: env('WEASYPRINT_MEDIA_TYPE'),
/**
* Optionally set the base URL for relative URLs in the HTML input.
*/
baseUrl: env('WEASYPRINT_BASE_URL'),
/**
* Optionally provide an array of stylesheets to use alongside the HTML input.
* Each stylesheet may the absolute path to a file, or a URL.
* It is recommended to do this at runtime.
*/
stylesheets: [],
/**
* The environment variables passed to Symfony Process when executing
* the WeasyPrint binary.
*/
processEnvironment: ['LC_ALL' => env('WEASYPRINT_LOCALE', 'en_US.UTF-8')],
/**
* Optionally specify a PDF variant.
*/
pdfVariant: WeasyPrint\Enums\PDFVariant::fromEnvironment('WEASYPRINT_PDF_VARIANT'),
/**
* Optionally specify a PDF version.
*/
pdfVersion: WeasyPrint\Enums\PDFVersion::fromEnvironment('WEASYPRINT_PDF_VERSION'),
/**
* For debugging purposes, do not compress PDFs.
*/
skipCompression: env('WEASYPRINT_SKIP_COMPRESSION', false),
/**
* Optimize the size of embedded images with no quality loss.
*/
optimizeImages: env('WEASYPRINT_OPTIMIZE_IMAGES', false),
/**
* When possible, embed unmodified font files in the PDF.
*/
fullFonts: env('WEASYPRINT_FULL_FONTS', false),
/**
* Keep hinting information in embedded font files.
*/
hinting: env('WEASYPRINT_HINTING', false),
/**
* Set the maximum resolution of images embedded in the PDF.
*/
dpi: env('WEASYPRINT_DPI', null),
/**
* Set the JPEG output quality, from 0 (worst) to 95 (best).
*/
jpegQuality: env('WEASYPRINT_JPEG_QUALITY', null),
/**
* Render PDF forms from HTML elements.
*/
pdfForms: env('WEASYPRINT_PDF_FORMS', false),
);
As noted before, you may publish the config file if you’d like to make changes to it – but, in most cases, you’ll want to make use of environment variables by adding them to your .env
file or using whatever mechanism your app uses to resolve them.
If you’d like to make a contribution to WeasyPrint for Laravel, you’re more than welcome to submit a merge request against the main
or current-release branch:
- If you are introducing a non-breaking change, target the
V.x
branch, whereV
is the latest major version of the package. If accepted and does not break any other versions either, it will also be merged into the applicable branches for those versions. - If you are introducing a breaking change of any kind, target the
main
branch. The change will be released in a new major version when accepted, and will not be added to older versions.
Your request should be as detailed as possible, unless it’s a trivial change.
Should it be required, please make sure that any impacted tests are updated, or new tests are created.
- If you are introducing a new feature, you will more than likely need to create a new test case where each piece of functionality the new feature introduces may be tested.
- Otherwise, if you are enhancing an existing feature by adding new functionality, you may add the appropriate test method to the applicable test case.
Then run the tests before opening your merge request:
$ composer run test
This package uses johnbacon/stout
to auto-format code. Before committing your code, please run a format over all dirty files:
$ composer run format
Your commit message should be clear and concise. If you’re fixing a bug, start the message with bugfix:
. If it’s a feature: feature:
. If it’s a chore, like formatting code: chore:
.
If you’d simply like to report a bug or request a feature, simply open an issue.
Licensed under ISC, WeasyPrint for Laravel is an open-source project, and is free to use. In fact, it will always be open-source, and will always be free to use. Forever. 🎉
If you would like to support the development of WeasyPrint for Laravel, please consider making a small donation via PayPal.