lankerd/groundwork-bundle
Groundwork Bundle provides a reusable foundation for Laravel applications, bundling base classes, traits, and conventions that reduce boilerplate and speed up scaffolding. It helps teams start new projects with a consistent structure and shared groundwork.
Reality check first: this is a Symfony bundle, not a Laravel package. There is no service provider, no facade, and no composer require + auto-discovery path into a Laravel app. Treat this assessment as "how would I evaluate and use it inside a Symfony service," plus "what would I port if I needed the same behavior in Laravel."
Minimal steps:
Inspect before installing. With 2 stars, zero dependents, and a last release in November 2019, the README is likely the only spec. Pull it down and read the bundle class and DI config:
composer require lankerd/groundwork-bundle --no-scripts
ls -R vendor/lankerd/groundwork-bundle
Look first, in this order:
src/*Bundle.php — the bundle class (confirms the real namespace, e.g. Lankerd\GroundworkBundle\GroundworkBundle).DependencyInjection/Configuration.php — the config tree; this is the actual API surface.DependencyInjection/*Extension.php and Resources/config/*.yaml|xml — what services, aliases, and parameters it registers.composer.json — PHP and Symfony version constraints (this dates the bundle faster than anything else).Register it (Symfony Flex will usually do this automatically; otherwise add it):
// config/bundles.php
return [
// ...
Lankerd\GroundworkBundle\GroundworkBundle::class => ['all' => true],
];
Verify the container compiles before writing any code:
bin/console cache:clear
bin/console lint:container
bin/console debug:config groundwork # adjust to the actual extension alias
First use case: pick the one service or abstract base class the bundle exists to provide, wire it into a single controller or command behind your own thin wrapper interface, and confirm it behaves. Do not let it leak into your domain layer on day one — you want a seam to swap it out if the bundle turns out to be a dead end.
Wrap, don't scatter. Because the package is unmaintained, every direct reference to its classes is future migration debt. Bind its services behind your own interfaces:
// src/Foundation/Groundwork/ThingInterface.php
interface ThingInterface { public function doThing(array $input): mixed; }
# config/services.yaml
services:
App\Foundation\Groundwork\ThingInterface:
'@groundwork.thing' # actual id from debug:container
Use it as a service-library, not a framework. Older Symfony bundles often ship base entities, repositories, or traits. If so:
Config-driven integration. Most of this bundle's behavior will be toggled in your config tree. Put its config in config/packages/groundwork.yaml, and pin every option explicitly rather than relying on defaults — defaults in a 2019 bundle are effectively undocumented. Keep the file small and commented with why each value is set.
Compiler passes and tags. If it exposes tagged services or compiler passes, prefer injecting collections (!tagged_iterator) over fetching from the container at runtime. That keeps the bundle's wiring at compile time where Symfony can catch errors.
Decorating rather than forking. If one behavior is wrong, decorate:
services:
App\Foundation\Groundwork\DecoratingThing:
decorates: groundwork.thing
arguments: ['@.inner']
This survives a future composer update better than editing vendor code (and better than a GPL fork you have to maintain).
Symfony-to-Laravel parity, if you're porting. For a Laravel codebase, map the concepts:
ServiceProvider.config/groundwork.php + mergeConfigFrom.$this->app->tag() / tagged() iterator.EventSubscriberInterface → Laravel listeners on the equivalent events.Do the port behind the same ThingInterface and the rest of your app never learns the difference.
Pin it hard. In composer.json, constrain to the exact minor ("lankerd/groundwork-bundle": "~1.0" or whatever resolves) and commit the lock file. An abandoned bundle with a wide constraint is how you get a surprise major from a transitive dependency.
src/ with attribution (mind the license, below). Do not reach for --ignore-platform-reqs to force it in — that just moves the failure to runtime.bin/console debug:config <alias> and debug:container --show-private are your primary discovery tools. If an option is not in Configuration.php, it does not exist, regardless of what the README claims.groundwork), not the vendor. Check getContainerExtension() / getAlias(); wrong alias in YAML silently does nothing (or throws on unknown keys only when ignoreExtraKeys is off).debug:container, debug:autowiring, lint:container, cache:clear. If autowiring fails, it is almost always a missing alias or a private service — alias it explicitly in services.yaml rather than making it public.templates/bundles/GroundworkBundle/... (the documented Symfony override path) instead of editing vendor/. That is the intended extension point and it is upgrade-safe.ThingInterface adapter, a small feature test, and an issue in your backlog to re-evaluate at the next language/framework upgrade.How can I help you explore Laravel packages today?