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

Symfony Mailjet Bundle Laravel Package

madjeek-web/symfony-mailjet-bundle

A Symfony bundle that integrates the Mailjet email delivery service, letting you send transactional and marketing messages through Mailjet's API using Symfony's Mailer component with simple configuration and service wiring.

View on GitHub
Deep Wiki
Context7

Getting Started

v1.0.0 is the first stable tag, so treat it as the point where the public API becomes something you can commit to. The practical first step is not to read the README end-to-end but to establish the support matrix before you install anything:

  1. Read composer.json first — check the require block for the php constraint and the illuminate/* (or laravel/framework) range. A package that only supports ^10.0|^11.0 will silently constrain your upgrade path later, and this is the single most common reason a "small utility" becomes a blocker six months out.
  2. Check for package auto-discovery — a extra.laravel.providers / extra.laravel.aliases block means Laravel registers it for you. If it's absent, you register the provider in bootstrap/providers.php (Laravel 11+) or config/app.php (Laravel 10 and earlier). Getting this wrong yields a confusing "class not found" rather than a helpful error.
  3. Install pinned to the new major — composer require vendor/package:^1.0. Do not let Composer resolve ^0.x for you if you're migrating; the constraint should be deliberate.
  4. Publish and inspect the config — php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider" and read the resulting file. The config keys are the package's real API surface, more so than its classes.

First use case: pick the narrowest thing the package does — one value object, one facade call, one command — and wire it in a single, non-critical path (a console command or a queued job) before putting it in an HTTP request cycle. That gives you a cheap loop for observing behaviour without exposing it to users.

If you were previously on a 0.x tag, read the repository's CHANGELOG/UPGRADE files directly. Terse release notes like "First stable release" almost never enumerate the renames and removals that happened during the pre-1.0 churn, and those are exactly what will break you.

Implementation Patterns

Resolve through the container, never new. The whole benefit of a Laravel package is that its service provider has already bound the configured implementation. app(Client::class) or constructor injection respects the user's config; new Client() silently bypasses it and produces behaviour that looks like a config bug.

Wrap it in a thin adapter of your own. Even a 20-line interface plus one concrete implementation means a future major bump is a one-file change rather than a grep across the codebase. This is worth doing for anything that touches money, auth, or an external service.

Drive behaviour from config, not from call sites. Most packages expose either a manager with drivers or a config block of named clients. Prefer declaring two named configurations (services.foo.primary, services.foo.tenant) over branching in application code — it keeps environment-specific differences in config/ where config:cache can see them.

Test with the framework's fakes first. If the package makes HTTP calls, Http::fake() in the package's own test suite or yours will usually intercept it, no package-specific fake required. If it dispatches events or jobs, Event::fake() / Queue::fake() let you assert on intent rather than outcome. Only reach for the package's own testing helpers once you've confirmed the framework-level fake doesn't cover it.

Push long-running work into jobs. Anything that opens a socket, calls a third-party API, or does filesystem work should sit behind ShouldQueue so retries and backoff are handled by the queue rather than by you.

Scheduled tasks and commands are the lowest-risk integration point. A package that provides an artisan command or a schedule hook can be exercised in staging with zero blast radius, which makes it the right place to validate assumptions before broader adoption.

Gotchas and Tips

  • Clear the caches after any config or provider change. php artisan config:clear and php artisan package:discover (or optimize:clear) resolve the majority of "my config change did nothing" and "class not found" reports. In production, remember config:cache will freeze whatever the published config file said at build time — environment variables read at runtime from inside a package may be null under a cached config.
  • vendor:publish without --force will not overwrite. If you upgrade and the package ships new config keys, your stale published file wins and the package falls back to defaults for keys it can't find, which can look like the feature simply doesn't work. Diff the package's config/ directory against yours after every major bump.
  • A 0.x → 1.0.0 jump is the breaking change, even when the notes don't say so. The absence of a "Breaking Changes" heading in a terse release note is not evidence of none. Use composer why-not vendor/package ^1.0 to see what's holding you back, and composer update vendor/package --with-dependencies rather than a blanket composer update when you're testing.
  • Commit composer.lock in applications and upgrade this package deliberately. A first stable release is precisely the moment when other packages start widening their constraints to ^1.0, so a lockfile is what stops an unrelated composer update from moving it under you.
  • Debugging: php artisan tinker plus app(Thing::class) is the fastest way to confirm what the container actually resolved. If the package integrates with Laravel's manager/driver pattern, Thing::getDefaultDriver() tells you which config branch you're on — that one call short-circuits most "it's ignoring my config" investigations.
  • Extension points to look for before you fork: config-driven driver/binding maps you can override from your own provider's boot(), Manager::extend() for custom drivers, and any Macroable traits. Registering a custom driver in AppServiceProvider is almost always preferable to patching vendor code, and it survives the next minor release.
  • Watch the support matrix on minors. A 1.0.1 can quietly drop a PHP version or add a new illuminate/* constraint. Read the composer.json diff, not just the tag message, before letting CI pull it in.
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.
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator