coringawc/filament-single-record-resource
Implements the single-record resource pattern for Filament. Replace index lists with a per-user “one record” resource (Profile, Settings, Wallet, Subscription). Traits handle routing, navigation, auth fallbacks, record resolution, and nested breadcrumbs.
index to view and handling authorization.Wallet → Companies → Products), preserving breadcrumbs and URL consistency without exposing parent IDs.SingleRecordResolvableResource interface enables static analysis and IDE support, reducing runtime errors and improving maintainability.viewAny() behavior to allow record-level access even when collection-level permissions are denied, aligning with SaaS/multi-tenant architectures.index pages with view/edit pages and add two traits (HasSingleRecordResource to the Resource, HasSingleRecord to pages). No database migrations or complex refactoring.SingleRecordResolvableResource is recommended for new projects.firstOrCreate) may introduce race conditions or inconsistent state if not idempotent. Requires validation in CI/CD.resolveSingleRecord()) must cover edge cases like:
nullfirstOrCreate conflicts)viewAny vs. view permissions).viewAny always be denied for single-record resources? If yes, document this as a team convention.viewAny = false but view = true for specific roles? Test thoroughly.firstOrCreate) require transactional guarantees? If yes, wrap in a service layer.5.x) and monitor deprecations.SingleRecordResolvableResource) be enforced via static analysis (e.g., PHPStan)? If yes, add to your baseline rules.stancl/tenancy if the resolver logic accounts for tenant context (e.g., where('tenant_id', tenant()->id)).filament/testing for auth stubs in tests.SingleRecordResolvableResource adoption (if enforcing the contract).viewAny policies) for comparison.index pages with view/edit pages across the codebase./profile instead of /profile/index).index pages exist. Test with plugins like filament-spatie-laravel-permission or filament-activity-log.view routes for single-record Resources.getUrl() or getViewUrl() instead of hardcoding /index in links/redirects.belongsTo(user)) over complex ones (e.g., firstOrCreate).resolveSingleRecordBuilder) is easier to update than scattered index page logic.SingleRecordResolvableResource adoption.firstOrCreate only in services") in the team’s architecture decision records (ADRs).viewAny/view policies and resolver logic.isNestedResource() and query scoping.# Check resolver output in Tinker
app(\App\Filament\Resources\MyWalletResource::class)->resolveSingleRecord()
N+1 queries. Use with() or eager loading in resolveSingleRecordBuilder.filament()->cache() or Laravel’s cache.view/edit pages).SingleRecordResolvableResource) to reduce onboarding time for complex resolvers.| Failure Scenario | Impact | Mitigation |
|---|---|---|
Resolver returns null |
Broken UI/404 | Add @throws docs and validate in tests. Use resolveSingleRecordOrFail(). |
Authorization conflict (viewAny=false, view=true) |
Access denied for valid users | Test with filament:test and adjust policies. |
| Nested resource URL misrouting | Inconsistent navigation | Use getUrl() and validate isNestedResource() logic. |
Race condition in firstOrCreate |
Duplicate records | Wrap in transactions or use upsert. |
| Filament major version upgrade | Package compatibility issues | Pin to a branch (e.g., 5.x) and monitor Filament’s changelog. |
HasSingleRecordResource vs. SingleRecordResolvableResource).filament()->auth()->user() stubs in tests).// Resource.php
use HasSingleRecord
How can I help you explore Laravel packages today?