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

Bootstrap Bundle Laravel Package

xrow/bootstrap-bundle

Bootstrap Bundle for Laravel brings the Bootstrap front-end framework into your PHP application, bundling its CSS and JavaScript assets with configuration options so you can build responsive, consistent interfaces without manual asset setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Version 1.6 is a small version bump with a disproportionately large behavioural footprint: a new cache purger now overwrites the legacy eZ cache purger service. Treat it as a migration, not a patch release.

First steps after composer update:

  1. Read the container bindings before the README. Run php artisan config:clear && php artisan cache:clear, then inspect what is bound:
php artisan tinker
>>> app()->getBindings()['Vendor\Package\Contracts\CachePurger'] ?? null
  1. Check the package service provider (vendor/.../src/*ServiceProvider.php). The 1.6 change is almost certainly a $this->app->bind()/singleton() swap of the old EzCachePurger implementation for the new purger class. That line is the source of truth for whether your existing typehints, decorators, or overrides still resolve.

  2. Diff the published config. If you published config/cache-purger.php previously, it is now stale — the new purger likely expects its own driver key, endpoint, or credential block. Re-publish to a temp path and diff:

php artisan vendor:publish --tag=cache-purger-config --force
git diff config/cache-purger.php
  1. First use case: purge a single content/item cache entry on write. Wire it up once and confirm end-to-end before touching bulk flows:
use Vendor\Package\Contracts\CachePurger;

public function __construct(private CachePurger $purger) {}

public function update(Content $content): void
{
    $content->save();

    $this->purger->purge($content->cacheKey());
}

If the legacy purger was the thing you actually depended on, jump straight to the migration pattern below before shipping anything.

Implementation Patterns

Explicit rebinding instead of relying on the default. Keep your own contract in front of the package so a future 1.7 swap doesn't ripple through your codebase:

// AppServiceProvider::register()
$this->app->bind(\App\Cache\Purger::class, function ($app) {
    return new \App\Cache\Purger(
        $app->make(\Vendor\Package\CachePurger::class)
    );
});

Register this after the package provider. If both are in bootstrap/providers.php, order matters — put AppServiceProvider last, or use $this->app->resolving() if the package is lazy-bound.

Feature-flag the switchover. Because 1.6 overwrites the old service rather than adding a parallel one, a config-driven escape hatch is cheap insurance:

// config/cache.php or config/cache-purger.php
'purger' => env('CACHE_PURGER_DRIVER', 'ez_v2'),
$this->app->bind(CachePurger::class, function ($app) {
    return match (config('cache-purger.purger')) {
        'legacy' => new LegacyEzCachePurger(...),
        default  => new EzCachePurgerV2(...),
    };
});

Purge after commit, never before. The most common production bug with any purger is purging inside a transaction, then having a queued job or concurrent read repopulate the cache with pre-commit data.

class PurgeContentCache implements ShouldQueue
{
    public bool $afterCommit = true;
}

Fan-out via events, not controller calls. Let write paths stay thin; listen to domain events and let listeners decide what to purge:

Event::listen(ContentPublished::class, PurgeContentCache::class);
Event::listen(ContentTrashed::class, PurgeContentCache::class);

Queue bulk purges and coalesce them. Purging 500 items individually is 500 round trips. Collect keys, then dispatch one job with Bus::batch() or a single purgeMany(array $keys) call. For purge storms (imports, migrations), guard with a unique job or Cache::lock() so you don't queue the same purge repeatedly.

Decorator for logging/metrics. Wrap the new purger rather than subclassing it — the internals changed in 1.6 and are more likely to move again:

final class LoggingPurger implements CachePurger
{
    public function __construct(
        private CachePurger $inner,
        private LoggerInterface $log,
    ) {}

    public function purge(string $key): void
    {
        $start = microtime(true);
        $this->inner->purge($key);
        $this->log->info('cache.purge', ['key' => $key, 'ms' => (microtime(true) - $start) * 1000]);
    }
}

Test against a fake, not the real purger. Whatever the package exposes, bind a spy in tests so assertions are on intent:

$this->mock(CachePurger::class, function ($mock) use ($content) {
    $mock->shouldReceive('purge')->once()->with($content->cacheKey());
});

Integration tip for multi-store / multi-site setups: make sure the new purger is invoked once per store/scope. Legacy purgers sometimes defaulted to the current site access; if 1.6 changed that default, multi-site installs will silently under-purge. Add an explicit loop and an assertion in tests.

Gotchas and Tips

  • "Overwrite" means the old class is no longer the default resolution. Anything typehinting the concrete legacy class (EzCachePurger or equivalent) will keep working if it's still autowirable, but you'll silently get the old behaviour while the rest of the app gets the new one. Grep for the old FQCN and for the contract name.
  • Subclassing the old purger is the riskiest upgrade case. If you extended it to override a method, 1.6 probably breaks you quietly — the class may still exist but is no longer wired in. Convert to a decorator.
  • Stale container/config caches are the #1 false alarm. After upgrading: php artisan config:clear && php artisan cache:clear && composer dump-autoload. On deploy, ensure config:cache runs after the new config is in place.
  • Octane / long-lived workers. The purger is likely a singleton holding an HTTP client or credentials. If credentials rotate or the client caches state, resolve it per-request ($app->scoped()) or reset it in a listener on Octane\Events\RequestReceived.
  • Purge failures should not break writes. Wrap purges in try/catch and log, or push them to the queue with retries. A purger outage taking down your editorial save path is a classic own-goal.
  • Watch latency and timeouts. A cache purge is an outbound call. Set a short connect/read timeout in the client config; a hanging purge endpoint will stall the request that triggered it.
  • Idempotency expectations. Purging a key that doesn't exist should be a no-op. If the new purger throws on 404, you will discover it during your first deploy — test a missing-key purge explicitly.
  • Look for a registration extension point before hacking. Most purger packages expose a tagged config array or CachePurger::extend(); prefer that over rebinding the contract in a service provider, since it keeps the package's own fallbacks intact.
  • Debugging checklist when purges "don't work": confirm the binding resolves to the new class (app(CachePurger::class)::class), confirm the config key the new purger reads is populated, confirm the target cache backend actually receives the request (log the outbound call), then confirm the key format matches what the reader uses — key-prefix mismatches between purger and application are extremely common and look identical to a broken purger.
  • Pin the version in composer.json ("vendor/package": "^1.6") and run the upgrade on a staging environment with a real cache backend. This release's change is behavioural, not cosmetic, so a green test suite that mocks the purger proves very little.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core