spatie/laravel-resource-endpoints
Abandoned package that adds controller-based “links” and collection “meta” links to Laravel API Resources. Automatically generates URLs for actions like index/show/edit/update/delete, so resources can expose REST endpoints without manually building routes.
Installation:
composer require spatie/laravel-resource-links
Publish the config (if needed):
php artisan vendor:publish --provider="Spatie\ResourceLinks\ResourceLinksServiceProvider"
Basic Usage:
Extend your JsonResource with the traits:
use Spatie\ResourceLinks\HasLinks;
use Spatie\ResourceLinks\HasMeta;
First Use Case:
Define a controller action (e.g., show) and reference it in your resource:
class UserResource extends JsonResource
{
use HasLinks;
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'links' => $this->links('show', 'edit', 'delete'),
];
}
}
The links() method will auto-generate URLs for the specified actions.
Action Naming:
Ensure controller methods follow Laravel conventions (index, show, store, update, destroy, etc.). Custom action names (e.g., export) must be explicitly defined in the config or via ResourceLinksServiceProvider.
Dynamic Link Generation:
Use the links() method in your resource to dynamically include URLs for actions:
$this->links('index', 'show', 'edit', 'delete')
Nested Resources:
For nested routes (e.g., users/{user}/posts), specify the parent resource:
$this->links('posts.index', 'posts.store')
Customizing Links:
Override the getLinks() method to customize link generation:
public function getLinks()
{
return [
'self' => ['url' => route('users.show', $this->id)],
'custom' => ['url' => route('users.custom', $this->id)],
];
}
API Responses: Include links in API responses for consistency and discoverability:
return UserResource::collection(User::all());
HATEOAS: Use the package to implement HATEOAS (Hypermedia as the Engine of Application State) in your API:
$this->links('self', 'related', 'collection')
Meta Data:
Combine with HasMeta to include pagination, filters, or other metadata:
use Spatie\ResourceLinks\HasMeta;
public function meta()
{
return [
'pagination' => ['total' => User::count()],
];
}
Route Caching: Cache routes for better performance:
php artisan route:cache
API Versioning:
Ensure routes are versioned (e.g., v1.users) to avoid conflicts across API versions.
Testing: Test link generation in PHPUnit:
public function test_links_are_generated()
{
$user = User::factory()->create();
$resource = new UserResource($user);
$this->assertEquals(
route('users.show', $user),
$resource->links('show')['show']['url']
);
}
Abandoned Package: The package is archived and no longer maintained. Consider alternatives like:
spatie/laravel-hal (for HAL+JSON).darkaonline/l5-swagger (for OpenAPI/Swagger docs).route() helper.Route Existence:
The package assumes routes exist for the specified actions. Missing routes will throw errors or return null.
Config Overrides:
Default action names (e.g., index, show) are hardcoded. Custom actions require manual configuration in config/resource-links.php:
'actions' => [
'export' => 'users.export',
],
Nested Resource Confusion:
Incorrectly specifying nested routes (e.g., posts.index for a UserResource) may lead to 404 errors. Verify route names match your routes/web.php or routes/api.php.
Check Route Lists:
Use php artisan route:list to verify route names and paths.
Log Link Generation:
Temporarily log the output of links() to debug:
\Log::info('Generated links:', $this->links('show'));
Clear Route Cache: If links break after route changes, clear the cache:
php artisan route:clear
Custom Link Providers: Extend the package by creating a custom link provider:
use Spatie\ResourceLinks\LinkProvider;
class CustomLinkProvider implements LinkProvider
{
public function getLinks($resource, $request)
{
return [
'custom' => ['url' => route('custom.route', $resource)],
];
}
}
Bind it in the service provider:
ResourceLinks::extend('custom', function () {
return new CustomLinkProvider();
});
Override Default Actions:
Modify the actions array in config/resource-links.php to map custom controller methods to route names:
'actions' => [
'customAction' => 'users.custom',
],
Conditional Links: Dynamically include/exclude links based on user roles or resource state:
$links = [];
if ($this->canEdit()) {
$links[] = 'edit';
}
$this->links(...$links);
Avoid Over-Fetching: Generate links only when needed (e.g., in API responses) to reduce overhead.
Memoization:
Cache the result of links() if called repeatedly (e.g., in loops):
private $linksCache = [];
public function links(...$actions)
{
$key = md5(serialize($actions));
if (!isset($this->linksCache[$key])) {
$this->linksCache[$key] = parent::links(...$actions);
}
return $this->linksCache[$key];
}
How can I help you explore Laravel packages today?