mazarini/tools-bundle
A PHP tools bundle from Mazarini offering reusable helper utilities and shared components to speed up development. Install via Composer and integrate common tooling into your projects with minimal setup and configuration.
mazarini/tools-bundle is a Symfony bundle, not a Laravel package — the name, the "bundle" suffix, and the "dispatch between bundles" description all point to the Symfony DI/container model. That framework mismatch is the first thing to internalize before you add it to a Laravel app.
Minimal steps if you are in a Symfony context:
composer require mazarini/tools-bundle
config/bundles.php (Symfony Flex may do this for you):
Mazarini\ToolsBundle\MazariniToolsBundle::class => ['all' => true],
config/packages/ — bundles of this shape usually expose a small Configuration tree via their DependencyInjection/*Extension.php bin/console cache:clear.Where to look first in the repo:
*Bundle.php) — it tells you what compiler passes are registered.DependencyInjection/ — the extension and any compiler passes reveal the real API surface (tag names, service IDs).Resources/config/services.* — how services are wired and which are public/autowired.README.md — sparse for a 0-star repo, so expect to read source.First use case: you have two bundles (or a bundle and app code) that need to talk to each other but you don't want a hard use dependency in either direction. The bundle presumably gives you a small dispatcher/registry you inject instead of the concrete service.
For a Laravel developer, the mental model is: service provider + tagged bindings + a mediator, i.e. what you'd build with $this->app->tag(...) and $this->app->tagged(...). If you try to drop this into Laravel you will hit Symfony-only contracts (ContainerBuilder, CompilerPassInterface, EventDispatcherInterface from symfony/*). Plan on either (a) running Symfony for that slice, or (b) reimplementing the pattern in Laravel rather than installing the package.
The package's value is decoupling, so the day-to-day patterns are about how you register and resolve cross-bundle collaborators.
1. Tag-and-dispatch (the core pattern).
You register your implementing service with a tag the bundle's compiler pass looks for, then inject the bundle's dispatcher/registry and call it with a key or type. This is the Symfony equivalent of Laravel's tagged bindings:
// services.yaml in your bundle
services:
App\Shipping\UpsRateProvider:
tags: ['mazarini.tools.provider'] # verify tag name in the compiler pass
final class RateController
{
public function __construct(private ToolDispatcher $dispatcher) {}
public function __invoke(Order $order): Rate
{
return $this->dispatcher->dispatch('ups', $order); // signature is a guess — read source
}
}
2. Inject the interface, not the implementation. The whole point is that your bundle depends only on the tool interface. Keep that discipline in your own code; if you start use-ing the concrete dispatcher from three bundles you have re-coupled everything and lost the benefit.
3. Decorator pattern for cross-cutting concerns. Wrap registered tools with a logging/timing decorator instead of modifying each tool. Symfony's decorates: attribute works well here, and it is the safest integration point because it doesn't depend on internal tag semantics.
4. Config-driven tool selection. If the bundle exposes a config tree, prefer registering available tools in config and selecting the active one per environment (e.g. a fake tool for test). This is where bundles like this usually earn their keep.
5. Laravel-side translation, if you must. If you only want the idea, implement it idiomatically:
// AppServiceProvider::register()
$this->app->singleton(ToolRegistry::class);
$this->app->tag([UpsProvider::class, FedexProvider::class], 'tools.provider');
$this->app->singleton(ToolRegistry::class, fn ($app) => new ToolRegistry(
collect($app->tagged('tools.provider'))->keyBy(fn ($t) => $t::key())
));
That gives you the same dispatch-between-modules ergonomics without pulling in GPL-licensed Symfony code.
Integration tips:
debug:container --tag=<tag> to confirm the compiler pass picked up your tagged services.License is the biggest one for a Laravel shop. GPL-3.0 is copyleft. If you link this into a distributed application, the GPL's obligations can extend to your application code depending on how it's combined. For internal-only tools it's usually fine; for a SaaS you distribute or an SDK you ship, get legal review before adopting. This is a real adoption blocker, not boilerplate.
Zero stars, zero dependents, zero score. Treat this as unmaintained/experimental. Concrete risks:
"mazarini/tools-bundle": "dev-main#<sha>") rather than trusting a version range.Framework mismatch. If the package is Symfony-only (very likely), Composer will pull symfony/dependency-injection, symfony/http-kernel, etc. into a Laravel app. Some of these collide with Laravel's own container assumptions. Don't install it "just to try"; read the composer.json require block first.
Compiler pass ordering. "Dispatch between bundles" almost always means a compiler pass. Passes run at different phases (TYPE_BEFORE_OPTIMIZATION, TYPE_AFTER_REMOVING, etc.). If your tagged services vanish or the dispatcher sees an empty registry, it is usually because you tagged them in a pass that runs too late, or because a RemoveUnusedDefinitionsPass pruned them. Make the dispatcher's argument reference the tagged iterator explicitly so services aren't removed as unused.
Debugging checklist:
bin/console debug:container --tag=<the-tag> — are your services found?bin/console debug:container <dispatcher-service-id> --show-arguments — is the tagged iterator populated?cache:clear after any services.yaml change; compiler passes are cached aggressively and stale caches mimic "my tag is ignored" bugs.Extension points to favor:
decorates:) rather than subclass. Subclassing ties you to internals that a 0-star package will change.Bottom line for a Laravel developer: the pattern — tagged services plus a dispatcher/registry to decouple modules — is excellent and you can implement it natively in Laravel in under an hour. The package itself is Symfony-specific, GPL-licensed, and effectively unmaintained, so adopting it directly is a hard sell unless you are already in a mazarini Symfony stack and need compatibility with its sibling bundles. Evaluate the source before committing, and isolate it behind an adapter if you do.
How can I help you explore Laravel packages today?