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

Components Bundle Laravel Package

sauls/components-bundle

A PHP package that bundles reusable UI components for rapid application development. It organizes shared components into one installable bundle, reducing duplication and keeping templates consistent across projects, with simple configuration and integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer and publish its config so you can see the defaults before writing any widgets:

composer require <vendor>/<package>
php artisan vendor:publish --tag=<package>-config

Where to look first, in order:

  1. The service provider — confirms what is bound into the container and whether the widget factory is a singleton. This matters a lot for the new cacheable() behaviour, because a shared factory instance is what makes fluent caching stick across calls.
  2. config/<package>.php — the widget registry, default renderer, and (from v1.0.5) the cache block. Read it before you register anything.
  3. The factory class itself (WidgetFactory or similarly named) — this is the object you will spend 90% of your time with. Skim its public methods; cacheable() is the newest addition and is the entry point for this release.

The first use case to get working end-to-end is deliberately boring: register a single widget in the config, render it once in a Blade view via the package's facade/helper, and confirm it appears. Once that loop works, take a widget that does real work (a query, an API call, an aggregate) and chain ->cacheable() onto it. If the second render is measurably faster and the output is identical, you have understood the package.

Implementation Patterns

One widget class per concern. Keep widgets small and single-purpose; the factory resolves and composes them, so a widget that does three things is a widget you cannot cache independently. Name them after the thing they display (RevenueThisMonthWidget, OpenTicketsWidget), not after where they sit on the page.

Resolve through the factory, never new. Every widget should come out of the factory so that the package's lifecycle hooks, dependency injection, and now the cache layer all apply. Direct instantiation silently bypasses caching and is the single most common reason someone reports "cacheable() doesn't work".

Use cacheable() at the call site, not in the widget. The idiomatic pattern for v1.0.5 is fluent, applied where you build the widget:

$factory->make(RevenueThisMonthWidget::class)
    ->cacheable(ttl: 300);

This keeps the cache decision next to the place that knows how fresh the data needs to be. A widget rendered on a public marketing page can be cached for an hour; the same widget on an admin dashboard might want sixty seconds. Same class, different policy.

Layer the cache deliberately. Three distinct lifetimes usually exist in a dashboard: static chrome (cache forever / cache at the HTTP layer), aggregate figures (minutes), and per-user figures (seconds or not at all). Use cacheable() for the middle band and let the framework handle the rest. Do not reflexively cache everything — a cache stampede on a cold deploy is worse than an uncached query.

Invalidate on write, not on a timer. Where a widget reflects Eloquent data, hook model events (saved, deleted) to forget the corresponding cache entry rather than relying on short TTLs. TTL is a safety net, not a strategy. If the package exposes a cache-key helper, use it in the observer so the key is constructed in exactly one place.

Test with the cache faked. Cache::spy() or the array driver in tests, then assert the underlying query ran once across two renders. Without this assertion you will never notice when a refactor quietly drops the caching.

Compose dashboards from a registry, not hardcoded Blade. Register widgets in config or a service provider and loop over them in the view. Adding a widget then becomes a one-line change rather than an edit to a template, and per-widget cache policy travels with the registration.

Gotchas and Tips

Cache keys must include the arguments. If your widget varies by tenant, user, or date range, those values have to be part of the key. A widget cached under revenue alone will cheerfully serve one tenant's numbers to another — the highest-severity bug this feature can introduce. Check the key derivation before shipping.

The cache driver matters. If the package uses cache tags for grouped invalidation, they are unsupported on the file and database drivers and will throw or silently no-op. Confirm which driver your production environment actually uses; file in local and Redis in production is a classic way to have invalidation work everywhere except where it counts.

Version your cache keys across deploys. When a widget's markup or query changes, old cached output is now wrong. Append a version constant (or the git SHA) to the key so a deploy flushes naturally. This is cheaper and more reliable than remembering to run cache:clear during a release.

Singletons and request state. A cached widget must not capture per-request state (the authenticated user, locale, flashed input) unless that state is in the key. Widgets that read auth()->user() internally and are cached globally are a data leak waiting to happen. Prefer passing such values in explicitly.

Debugging order when a widget looks stale: (1) is cacheable() actually on the call chain, (2) what is the resolved key — dump it, (3) does the driver support what the package is asking of it, (4) forget the key manually and see if the output changes. If forgetting fixes it, the bug is invalidation, not rendering.

Debugging order when a widget is slow despite caching: check that the expensive work happens inside the cached section rather than before it. A common mistake is building the data in the controller and then marking the widget cacheable — you have cached the render and not the query. Move the work into the widget.

Extension points worth knowing: most factories of this shape expose a macro or an extend hook, letting you register custom resolution logic without forking. If your team needs a house style for cache TTLs, that is the place to enforce it — wrap cacheable() in your own helper so nobody hardcodes a number.

Config quirks. The cache block is new in v1.0.5; if you published the config on an earlier version, your copy will not contain it and the package will fall back to whatever defaults are compiled in. Re-publish to a temp directory and diff rather than overwriting, or you will lose any customisations you made to the widget registry.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource