Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Email Template Bundle Laravel Package

sfk/email-template-bundle

A Symfony bundle for managing and rendering email templates, giving you a central place to store, edit, and reuse HTML email layouts with Twig-style placeholders so transactional messages stay consistent across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony2 bundle, not a Laravel package — despite being listed in a Laravel context. There is no service provider, no facade, and no Composer auto-discovery for Laravel. Treat it as reference material or as something you'd port, not something you'd composer require into a Laravel app.

Minimal steps:

  1. Read Resources/config/services.xml first — it tells you the real public surface: the templating service, the mailer/renderer, and the Twig loader. The README is thin; the service definitions and DependencyInjection/Configuration.php are the actual docs.
  2. Identify the two rendering paths: Twig-backed templates (files on disk) and database-backed templates (Doctrine entity, typically EmailTemplate with subject/body/html fields).
  3. Look at the Doctrine entity + repository if you plan to port the DB path — that's the part with the most reusable logic (template lookup, fallback, locale handling).
  4. First use case: transactional emails with editable copy. The bundle's core value is letting non-developers edit email bodies in a DB/admin area while developers keep the layout in Twig.

If you're staying in Laravel, the fastest path is to read the source (~a few hundred lines) and reimplement the two ideas you actually need: a template resolver (DB → file fallback) and a renderer that merges a layout with the resolved body.

Implementation Patterns

Twig-first rendering (file templates). The bundle registers a Twig loader so templates can be referenced by name, rendered with context, and handed to Swift Mailer. In Laravel terms this maps cleanly to Blade + Mailables: keep the layout in resources/views/emails/layout.blade.php, render the body, and inject it. The bundle's pattern of "render subject and body separately, then compose" is worth copying — it lets the subject be templated independently.

Database-backed templates. The entity typically stores a key/name, locale, subject, and body. The service resolves by key (+ locale), falls back to a default, and renders. This is the pattern to port to Laravel:

  • A email_templates table: key, locale, subject, body, is_active.
  • A resolver that checks DB first, then a config/views fallback.
  • Render with Blade (Blade::render() or a Mailable that pulls the body), not Twig.

Layering: layout + body. Don't store full HTML in the DB. Store the body fragment and render it inside a versioned layout. This is the single most important pattern in the bundle and the one that keeps DB templates maintainable.

Preview before send. The bundle's separation of render and send makes preview trivial. Mirror that: a render() method returning [subject, html, text] that you can hit from a route or artisan command, and a send() that consumes it. Never couple rendering to the mail transport.

Localization. The bundle's locale-aware lookup maps to Laravel's app()->setLocale() around render time, with a fallback chain (fr_CA → fr → en). Implement the fallback explicitly; don't rely on the DB query to do it.

Integration tips for a Laravel port:

  • Wrap resolution in a small EmailTemplateRepository + EmailTemplateRenderer pair; keep Mailables thin and delegate to the renderer.
  • Cache resolved templates (Cache::remember keyed by key.locale.updated_at) — DB hits per email add up in queues.
  • Expose an admin CRUD only for the body fragment; validate that it renders before saving (catch Blade/Twig syntax errors at write time, not send time).

Gotchas and Tips

  • It's Symfony2-era. Expect Swift Mailer (dead in modern Laravel), old Symfony DI conventions, and PHP versions that predate typed properties. Don't try to install it alongside Laravel — namespace and container collisions are likely.
  • No Laravel packaging. No Illuminate\Support\ServiceProvider, no config publish, no facade. Composer will happily install it and nothing will wire up. Budget time for a port, not an integration.
  • DB templates are an injection surface. Storing raw template source and rendering it means anyone who can edit a template can potentially execute template logic. In Twig this was sandboxed-ish; in Blade, {!! !!} on stored bodies is an RCE-adjacent footgun. Sanitize on save and render with a restricted context.
  • Subject templating is easy to forget. The bundle renders subject and body separately; if you port only the body, you'll end up with hardcoded subjects and broken personalization. Template both.
  • Locale fallback is implicit and easy to break. The lookup order (locale → default) is the kind of thing that silently sends English to French users when a row is missing. Log fallbacks in non-production.
  • Debugging rendering failures. Template errors surface at send time inside a queued job — which means silent failures. Add a render-only path and a test that renders every active template on deploy (a simple artisan command iterating keys). This catches broken templates before users do.
  • Caching invalidation. If you cache resolved templates, bust on saved/deleted model events and key by updated_at. Editing a template in admin and not seeing the change is the #1 support ticket for this class of package.
  • Extension points worth keeping. The bundle's separation of loader, renderer, and mailer is the right seam structure. Preserve it in a port: swap the loader (DB vs file vs S3) without touching rendering, and swap the transport without touching templates.
  • Text versions. The bundle focuses on HTML. For deliverability and accessibility, generate a text part too (strip tags or a stored text body); most ports skip this and regret it.
  • Dead dependency signal. Zero stars and an old Symfony2 target mean no security patches. Mine it for patterns, then close the tab — don't ship the code.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment