cwsps154/my-gallery
A Laravel/PHP package for adding image galleries to your application. It offers a straightforward way to organize, display, and manage gallery images, helping you integrate reusable gallery functionality without building the core features from scratch.
This is a Filament plugin (v1.0.0) that drops a gallery resource into an existing Filament panel. It is not a standalone Laravel package — everything happens inside a panel, so start from a panel you already have running.
Install and scaffold
composer require cwsps154/my-gallery
php artisan my-gallery:install
The install command is the first thing to inspect. It is the package's opinionated setup step (likely migrations + asset publishing). Run it before touching the panel provider, and check vendor/cwsps154/my-gallery/src/Commands to see exactly which tags it publishes — that tells you what you can safely re-publish later.
Register the plugin in your PanelProvider::panel():
$panel->plugins([MyGalleryPlugin::make()]);
Migrate if the install command publishes migrations (php artisan migrate), then load the panel and confirm the Gallery resource appears in the sidebar.
First real use case: a media library for a single-tenant admin panel. Upload a gallery per record (product, post, property listing), and let editors manage ordering/visibility without a separate CMS. Wire the gallery to your model via the plugin's resource before you start styling anything — get the data model right first.
Where to look first when something is off:
config/my-gallery.php (publish with php artisan vendor:publish --tag=my-gallery-config) — currently only a settings-page key.can* methods, to see whether closures receive a model/record argument.Closure-based authorization (default path). The plugin exposes four capability hooks that map to Filament's resource policies:
MyGalleryPlugin::make()
->canViewAny(fn () => auth()->user()->hasRole('admin'))
->canCreate(fn () => auth()->user()->can('create-gallery'))
->canEdit(fn () => true)
->canDelete(fn () => auth()->user()->isSuperAdmin());
This is the pattern to reach for in most apps. It keeps the gate logic in the panel provider, next to the rest of your panel configuration, and avoids inventing a policy class for a package-owned resource.
Permission-string authorization (ecosystem path). If you already run cwsps154/filament-users-roles-permissions, the same four methods accept a (guard, permission) pair instead of a closure:
MyGalleryPlugin::make()
->canViewAny('have-access', 'view-gallery')
->canCreate('have-access', 'create-gallery')
->canEdit('have-access', 'edit-gallery')
->canDelete('have-access', 'delete-gallery');
Treat the two signatures as mutually exclusive per capability — pick closures throughout, or permission pairs throughout. Mixing them in one plugin instance works only by coincidence of how the plugin dispatches; don't rely on it.
Multi-panel setups. Register the plugin per panel and vary the capabilities per panel. A admin panel gets full CRUD; a marketing panel gets canViewAny + canCreate only, with canEdit/canDelete returning false. Because each MyGalleryPlugin::make() is a separate instance, this is clean and needs no extra abstraction.
Extracting authorization into a policy-like helper. Once you have more than one panel, the closures get repetitive. Pull them into a small class and reference it:
$panel->plugins([
MyGalleryPlugin::make()
->canViewAny(fn () => GalleryAccess::viewAny(auth()->user()))
->canCreate(fn () => GalleryAccess::create(auth()->user())),
]);
Keeps the panel provider readable and gives you one place to unit test the rules.
Settings page integration. The published config's single key, settings-page, points at \CWSPS154\AppSettings\Page\AppSettings::class. Set it to your own Filament page class if you want the gallery's settings screen to live inside your app's settings area rather than the vendor page. This is the main extension point in v1.0.0 — it's how you brand and embed gallery configuration.
Day-to-day workflow. Upload via the create screen (screenshots show a two-step create flow, so expect a file-upload step followed by metadata/details), then manage ordering and deletion from the list view. For editorial teams, this is the whole loop — no artisan commands, no config edits.
my-gallery.php shipping with only settings-page means most behavior is hardcoded or configured through the plugin's fluent methods. Don't expect to tune storage disks, image sizes, or upload limits from config — check the plugin class and the resource source before assuming a config key exists.settings-page references a vendor class from a different package (CWSPS154\AppSettings\Page\AppSettings). If you don't have that package installed, publishing the config without overriding this key will produce a class-not-found when the settings page is resolved. Publish the config early and set it to a page you actually have, or leave the feature untouched.canEdit only for galleries the user owns), verify in the plugin source whether a record is passed; if it isn't, fall back to a policy or a global scope on the underlying model rather than trying to infer it from request().->canViewAny('have-access', 'view-gallery') — the first argument is the guard, the second the permission. Swapping them silently denies access, which reads as "the plugin's broken" rather than "the arguments are backwards." Double-check the guard name matches your config/auth.php guards, not your panel ID.->canDelete(...), inside the array literal. Harmless in that snippet, but copy-pasting it into a ->plugins([...]) call with other plugins will produce confusing parse errors.can* closures returning false (or a guard/permission mismatch), not Filament caching. php artisan filament:optimize-clear / optimize:clear after changing a panel provider, then re-check the closure — panel provider changes are cached in production."cwsps154/my-gallery": "^1.0") and expect the can* signatures and config shape to be the most likely breaking points in 1.x. Wrap the plugin registration in a single private method on your panel provider so a future signature change is a one-file fix.How can I help you explore Laravel packages today?