sylius/plugins-bundle
A Sylius bundle for organizing and managing plugins in your e-commerce application. It provides a structured approach to registering plugins and integrating extensions, helping keep customizations maintainable as your Sylius store grows.
Do not treat this as an installable dependency in a Laravel app. The realistic first step depends on which of two situations you are in.
If you have a legacy Symfony2/Sylius codebase that already references it:
SyliusPluginsBundle.php, then DependencyInjection/SyliusPluginsExtension.php, then Resources/config/services.xml. The extension file is the actual public surface: it lists the plugin manager/registry service and any console commands. The README is thin; the code is the documentation.app/AppKernel.php:
new Sylius\Bundle\PluginsBundle\SyliusPluginsBundle(),
app/console cache:clear). Symfony2's container is compiled, and stale cache is the number-one cause of "the bundle does nothing."app/console list and look for sylius:plugins:*. If no command exists, resolve the manager directly and dump the list:
$plugins = $container->get('sylius.plugins.manager')->getPlugins();
If you are on Laravel (the likely case):
repositories entry or a require line — the composer.json targets PHP 5.x/7.0 and Symfony 2.x, and resolution against Laravel 9+ on PHP 8.1+ will hard-fail before you reach any runtime error.Resources/ layout) is Symfony2-specific and does not translate.Composer-as-registry. The core idea: a "plugin" is a Composer package that also declares one or more Symfony bundles. The manager enumerates installed packages and filters by that declaration. If you use it at all, use it as a read-only registry — iterate plugins to build admin menus, dashboards, or feature flags. Never treat it as an installer; there is no maintainer to fix a broken install path.
Kernel registration loop. Symfony2 has no runtime bundle registration, so plugins still need a line in AppKernel.php. The day-to-day pattern is a guarded loop that asks the manager for bundle classes:
foreach ($this->getPluginBundles() as $class) {
if (class_exists($class)) {
$bundles[] = new $class();
}
}
Order matters — respect any declared dependency order, not alphabetical. A plugin that boots before its dependency will fail on container compile, which surfaces as a cryptic service-not-found, not a plugin error.
CLI-driven observability. The highest-value use of a 14-star archived bundle is auditing, not automation. Wire plugin inspection into your deploy script: on each deploy, dump the active plugin list + versions to a log or dashboard. That gives you a diffable record of what changed between releases — genuinely useful during a migration.
Per-plugin configuration. Plugin config typically flows through the bundle's DI extension (load, then prepend/merge). Copy the shape of this into Laravel as a PHP config file per plugin, merged in a PluginServiceProvider or a dedicated PluginManager singleton.
Laravel translation (the build path). Reimplement natively rather than porting:
vendor/composer/installed.json or use Composer\InstalledVersions and filter on an extra.laravel-plugin manifest key. This mirrors the bundle's Composer-as-registry model without any Symfony coupling.plugins table (name, version, enabled, installed_at) so enable/disable is a DB flag, not a kernel edit. This is strictly better than the Symfony2 model, where "disable" means editing AppKernel.php.PluginServiceProvider that iterates enabled plugins and calls register() / boot() on each plugin's provider, respecting declared dependencies.loadViewsFrom / loadTranslationsFrom / loadRoutesFrom with publishable assets (--tag) instead of Symfony's Resources/config|views|translations convention.name, version, provider, requires, priority) so third parties can ship a plugin without touching your code — the one design idea worth carrying over verbatim.php and symfony/* constraints. Do not reach for --ignore-platform-reqs — running unpatched Symfony2 code on PHP 8 is undefined behavior, not "mostly working."class_exists() and keep a hardcoded allowlist you can fall back to.file_get_contents over HTTP in the source first.sylius.plugins.manager from the container works in Symfony2; if you ever try to port that call into a modern Symfony or Laravel container, the service may be private or the ID gone entirely. Depend on an interface, not a string ID.plugin.{name}.*) from day one.How can I help you explore Laravel packages today?