sourcetoad/enhanced-resources
Laravel API resource enhancement that lets a single Resource expose multiple output “formats” via PHP attributes. Mark methods with #[Format], pick formats with ->format('name'), and optionally set a default with #[IsDefault] to avoid exceptions.
## Getting Started
### **First Steps**
1. **Installation**
```bash
composer require sourcetoad/enhanced-resources:^7.3.0
Publish the config (if needed):
php artisan vendor:publish --provider="SourceToad\EnhancedResources\EnhancedResourcesServiceProvider" --tag="config"
Basic Usage
Extend Laravel’s built-in Resource class with enhanced features (now fully compatible with Laravel 13.x):
use SourceToad\EnhancedResources\Resource;
class UserResource extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'meta' => $this->metaData(), // Custom method
'links' => $this->links(), // Auto-generated links
];
}
}
First Use Case
Replace a standard JsonResource with EnhancedResource to leverage:
?fields=id,name).Use query parameters to control output fields (now optimized for Laravel 13.x query builder):
// In your controller
public function index(Request $request)
{
$users = User::query()->get(); // Laravel 13.x query builder
return new CollectionResource(UserResource::class, $users, $request);
}
Request: GET /users?fields=id,name
Output: Only id and name fields are included.
Automatically resolve nested relationships with Laravel 13.x optimizations:
class UserResource extends Resource
{
public function toArray($request)
{
return [
'id' => $this,
'posts' => PostResource::collection($this->whenLoaded('posts')),
];
}
}
Enhanced Behavior:
posts only if requested).User → Posts → User).Hide/show fields based on logic (now compatible with Laravel 13.x request handling):
public function toArray($request)
{
return [
'name' => $this->name,
'email' => $this->when(fn () => $request->user()->isAdmin(), $this->email),
];
}
Add dynamic metadata to responses (now with Laravel 13.x carbon compatibility):
protected function metaData()
{
return [
'created_at' => $this->created_at->toIso8601String(),
'is_active' => $this->isActive(),
];
}
Extend Laravel’s pagination with extra metadata (now compatible with Laravel 13.x pagination):
return new PaginatedResource(
UserResource::class,
User::paginate(10),
$request,
[
'meta' => [
'total_pages' => ceil(User::count() / 10),
'filters_applied' => $request->query(),
],
]
);
Use traits to support versioned responses (now with Laravel 13.x routing improvements):
use SourceToad\EnhancedResources\Traits\Versionable;
class UserResource extends Resource
{
use Versionable;
protected $version = 'v2';
}
Leverage new Laravel 13.x query builder features:
// Example: Using Laravel 13.x's new query builder methods
$users = User::query()
->when($request->has('active'), fn($q) => $q->where('active', true))
->get();
Circular References
User → Posts → User).->except() or ->only() to break cycles:
class PostResource extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'user' => UserResource::make($this->user)->except('posts'), // Avoid recursion
];
}
}
Performance with Nested Resources
with() in your query (Laravel 13.x optimizations apply):
User::with(['posts.comments' => fn($q) => $q->orderBy('created_at', 'desc')])->get();
Field Filtering Overhead
->only() for static APIs.Laravel 13.x Configuration Conflicts
// config/enhanced-resources.php
'default_fields' => ['id', 'name'], // Override defaults
'laravel_13_compatibility' => true, // Enable if needed
Carbon Compatibility
$this->created_at->toIso8601String(); // Works with Carbon 3.x
Log Resource Output
Use Laravel’s dd() or dump() to inspect the resource structure:
$resource = new UserResource(User::first());
dump($resource->toArray(new Request()));
Check for Deprecated Methods
Enable Query Logging Debug N+1 issues with:
DB::enableQueryLog();
// ... run your request ...
dd(DB::getQueryLog());
Laravel 13.x Route Caching
php artisan route:clear
Custom Directives Extend field filtering with custom directives (now compatible with Laravel 13.x):
// In config/enhanced-resources.php
'directives' => [
'uppercase' => fn ($value) => strtoupper($value),
];
Usage in Resource:
'name' => $this->name->uppercase(),
Middleware for Resources Apply middleware to resource responses (Laravel 13.x middleware improvements):
class TransformResponseMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response instanceof ResourceResponse) {
$response->withHeader('X-Resource-Type', get_class($response->resource));
}
return $response;
}
}
Event Hooks Listen to resource compilation events (now with Laravel 13.x event improvements):
EnhancedResources::listen('compiling', function ($resource, $request) {
if ($request->has('debug')) {
$resource->addMeta('debug', true);
}
});
Testing Resources
Use the ResourceTestCase helper (compatible with Laravel 13.x testing):
use SourceToad\EnhancedResources\Testing\ResourceTestCase;
class UserResourceTest extends ResourceTestCase
{
public function test_fields_are_filtered()
{
$response = $this->get('/users?fields=id,name');
$response->assertJsonStructure(['data' => [[
'id', 'name'
]]]);
}
}
Laravel 13.x Testing Improvements Leverage Laravel 13.x’s new testing features:
public function test_resource_with_laravel_13_features()
{
$response = $this->actingAs(User::factory()->create())
->getJson('/users');
$response->assertOk();
}
**CI/CD
How can I help you explore Laravel packages today?