kcs / mjml
Installs: 278
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Language:Rust
Type:php-ext
Ext name:ext-mjml
pkg:composer/kcs/mjml
README
PHP extension that embeds MRML, the MJML rendering engine written in Rust, so that you can render MJML templates directly from PHP without shelling out to a CLI tool.
Documentation
The full documentation lives under ./docs/ and is published as a MkDocs site. Start with the architecture overview and consult the dedicated guides for installation, configuration, usage, API details, and troubleshooting.
To preview the site locally install MkDocs and run:
composer run docs:serve
This command proxies to mkdocs serve using the navigation defined in mkdocs.yml.
Overview
- Native MJML rendering – compile templates into responsive HTML emails through a thin PHP wrapper around the Rust engine.
- File and stream support – render inline strings or files (including stream wrappers) through
renderandrenderFile. - Configurable output – control comments, custom fonts, and social icon URLs via constructor options.
- Exceptions-first API – failed renders surface as
Mjml\Exception\RenderException, enabling straightforward error handling.
Requirements
- PHP 8.0 or newer with the development headers (
php-dev,php-devel, or similar). - Rust toolchain with Cargo available in
PATH(the build usescargo build). - Build dependencies required by MRML, for example
build-essential,gcc,make,libclang-dev,openssl,libssl-dev, andgit. phpizeandphp-configfrom your PHP installation.
Note: On Alpine Linux install
php-dev,cargo,clang-dev,openssl-dev, andbuild-base. On Debian/Ubuntu useapt install php-dev rustc cargo build-essential libclang-dev libssl-dev.
Installation
Build from source
phpize ./configure # add --enable-cargo-debug to build a debug artefact make sudo make install # installs mjml.so into the active PHP extension dir
After installation, enable the extension in your php.ini (see Configuration). During development you can load the module from the build tree instead of running make install:
php -dextension=./target/release/mjml.so your-script.php
Composer / packaged distribution
The project is published as a Composer package (kcs/mjml). You can pull the extension into your project with:
pie install kcs/mjml
PIE will place the extension artefact under the PHP extension directory (and enable it, if possible).
Configuration
Add one of the following lines to your PHP configuration:
; system-wide configuration extension=mjml ; or provide an absolute path when running from the build tree extension=/path/to/mjml-php/target/release/mjml.so
When using PHP-FPM or Apache, restart the service so the new module is loaded.
Usage
<?php use Mjml\Mjml; use Mjml\Exception\RenderException; $mjml = new Mjml(["disable_comments" => true]); try { // Render a MJML string and fetch the body HTML. $email = $mjml->render('<mjml><mj-body><mj-text>Hello world!</mj-text></mj-body></mjml>'); echo $email->getBody(); // Render from a file or stream. Stream wrappers such as s3:// are supported. $newsletter = $mjml->renderFile(__DIR__ . '/templates/newsletter.mjml'); file_put_contents(__DIR__ . '/build/newsletter.html', $newsletter->getBody()); // Inspect the default fonts shipped with MRML. $fonts = Mjml::defaultFonts(); printf("Roboto is loaded from %s\n", $fonts['Roboto']); // Render a template that includes reusable components. $withPartials = $mjml->renderFile(__DIR__ . '/templates/with-includes.mjml'); echo $withPartials->getTitle(); } catch (RenderException $e) { // Handle invalid MJML gracefully (syntax error, missing include, …). error_log('MJML render failed: ' . $e->getMessage()); }
render and renderFile both return an instance of Mjml\Email, exposing:
getTitle(): string|nullgetPreview(): string|nullgetBody(): string
Constructor options
Pass an associative array to new Mjml($options) to tweak the renderer:
| Option | Type | Default | Notes |
|---|---|---|---|
disable_comments |
bool |
false |
Non-boolean values raise a TypeError. When true, HTML comments emitted by MRML are stripped. |
social_icon_origin |
string |
https://www.mailjet.com/images/theme/v1/icons/ico-social/ |
Must be a non-empty string. Controls the base URL used by <mj-social-element> icons. |
fonts |
array<string, string> |
Mjml::defaultFonts() |
Keys are font names and values the font URL. Passing anything other than string keys/values triggers a validation error. |
Default fonts
print_r(Mjml::defaultFonts());
Outputs an associative array similar to:
Troubleshooting
configure: error: cargo command missing– install Rust and ensurecargois in yourPATH.phpizenot found – install PHP development tools (apt install php-dev,dnf install php-devel, etc.).- Missing includes during rendering – check that the
mj-includepaths exist and that PHP has permission to read them (seetests/0001-include.phptfor an example layout). - Segmentation faults or crashes – rebuild in debug mode (
./configure --enable-cargo-debug && make clean && make) and open an issue with the failing template.
License
Licensed under the MIT License.
Contributing
-
Fork the repository and create a feature branch.
-
Build the extension locally (see Build from source).
-
Run the PHPT test suite before submitting a pull request:
php -dextension=./modules/mjml.so run-tests.php tests
Integration scenarios live under
tests/integration/. -
Follow the existing coding style and commit conventions, then open a pull request.