tomhart / laravel-restful-controller
Laravel Restful Controller
Requires
- php: ^7.2
- guzzlehttp/guzzle: ^6.5
- illuminate/database: ~5.5.0|~5.6.0|~5.7.0|~5.8.0|~6.0|^7.0
- illuminate/routing: ~5.5.0|~5.6.0|~5.7.0|~5.8.0|~6.0|^7.0
- illuminate/support: ~5.5.0|~5.6.0|~5.7.0|~5.8.0|~6.0|^7.0
Requires (Dev)
- barryvdh/laravel-debugbar: ^3.2
- orchestra/testbench: ^3.8 || ^4.0 || ^5.0
- phpstan/phpstan: ^0.12.0
- phpunit/phpunit: ^8.0
- squizlabs/php_codesniffer: *
- dev-master
- 1.6.6
- 1.6.5
- 1.6.4
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6.0
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.1
- 1.0.0
- dev-dependabot/composer/symfony/http-kernel-5.4.20
- dev-dependabot/composer/guzzlehttp/guzzle-6.5.8
- dev-dependabot/composer/league/flysystem-1.1.4
- dev-dependabot/composer/laravel/framework-7.30.3
- dev-feature/issue_2/api_consumer
- dev-feature/add_options_support_for_links
- dev-feature/issue_2/fix_has_many_pagination
- dev-bugfix/issue-4/pagination_filtering_on_page
- dev-feature/issue_4/_links_to_view_relationship
- dev-feature/has_links_and_access_children
This package is auto-updated.
Last update: 2025-03-29 01:01:11 UTC
README
This library adds an AbstractRestfulController
to to be basic heavy lifting of a CRUD controller.
Installation
You can install this package via composer using this command:
composer require tomhart/laravel-restful-controller
Usage
- Create a controller extending from this, and implement the method
getModelClass
use TomHart\Restful\AbstractRestfulController; class BlogController extends AbstractRestfulController { /** * What Model class to search for entities. * @return string */ protected function getModelClass(): string { return Blog::class; } }
- If you want it to render views for index, show, or store, add a
$views
property
/** * The views to render. * @var array */ protected $views = [ 'index' => 'blog/index', 'show' => 'blog/show', 'store' => 'blog/store' ];
If $views
is empty, the specified view doesn't exist, or the Accept
header is application/json
, then JSON is returned
- Define a resource route
Route::resource('blogs', 'BlogController');
Note this also would define a blogs.show.extra
, and blogs.show.options
route
which will be explained later.
Example response for: /blogs/1
{ "id": 1, "title": "My Blog Post", "content": "<h1>Title</h1><p>Some Content</p>" }
Relationships
Loading Relationships
The show route can return your models relationships. If you send a X-Load-Relationship
header,
with a comma separated value list of headers to load. See the testRelationshipsCanBeReturned
test
for an example.
Example response for: /blogs/1
with X-Load-Relationship: comments
{ "id": 1, "title": "My Blog Post", "content": "<h1>Title</h1><p>Some Content</p>", "comments": [ { "id": 1, "comment": "Great post!" }, { "id": 2, "comment": "I enjoyed reading this" } ] }
Accessing Relationships
You can drill into a relationship using the .show.extra
route mentioned above. If the first comment
had an author
and you wanted to see, via the blog resources, you can call /blogs/1/comments[0]/author
{ "id": 1, "name": "Joe Bloggs" }
You can dynamically build the route using
route('blogs.show.extra', [ 'blog' => 1, 'extra' => 'comments[0]/author' ]);
Restricting Access to Models
You'll most likely want to restrict access to certain models, e.g. only load the logged in users posts. To do that, there's a few methods you can overwrite.
Index Page
In order to restrict the models returned by the index route, e.g. a paginated list of many models,
overwrite the createModelQueryBuilder
method.
Show, Update, and Destroy Pages
In order to restrict which indiviual models can be shown, updated, or deleted, overwrite the
findModel
method.
Manipulating models before saving or updating
If you want to manipulate the model before they are saved, or updated, e.g. setting the user_id
to the current logged in user, override the saveModel
method.
Pagination
By default the index
route, and any relationships it's trying to load will be paginated if possible.
Example response for: /blogs
{ "total": 50, "per_page": 15, "current_page": 1, "last_page": 4, "first_page_url": "http://laravel.app?page=1", "last_page_url": "http://laravel.app?page=4", "next_page_url": "http://laravel.app?page=2", "prev_page_url": null, "path": "http://laravel.app", "from": 1, "to": 15, "data":[ { "id": 1 }, { "id": 2 } ] }
Filtering
You can filter the index
route via a query string, e.g. ?name=test
.
HasLinks
This library also provides HasLinks
interface, and a HasLinksTrait
to provide a default implementation. If you apply
those to your models, the responses will contain a _links
key to help your consumers navigate around and use your API.
Example _links
for /blogs/1
:
{ "id": 1, "title": "My Blog", "content": "See some _links!", "_links": { "index": { "method": "get", "href": { "relative": "/blogs/", "absolute": "https://api.example.com/blogs/" } }, "create": { "method": "get", "href": { "relative": "/blogs/", "absolute": "https://api.example.com/blogs/" } }, "store": { "method": "post", "href": { "relative": "/blogs/", "absolute": "https://api.example.com/blogs/" } }, "show": { "method": "get", "href": { "relative": "/blogs/1", "absolute": "https://api.example.com/blogs/1" } }, "update": { "method": "put", "href": { "relative": "/blogs/1", "absolute": "https://api.example.com/blogs/1" } }, "destroy": { "method": "delete", "href": { "relative": "/blogs/1", "absolute": "https://api.example.com/blogs/1" } } } }
The .options
route mentioned earlier will simply return the index
, create
, and store
_links
for the resource
so you can query the endpoint and get the URLs needing to interfacing with the API.
If you send {"id": X}
, it'll also build the show
, update
, and delete
routes with the ID supplied.
Builder
This library also includes a Builder
class to interface with the API from a consumer view.
It supports the standard get
, insert
, update
, and delete
methods.
Example:
use TomHart\Restful\Builder; $models = Builder::model(MyModel::class)->where('name', 'test')->get(); // Collection $modelWasInserted = Builder::model(MyModel::class)->insert(['name' => 'test']); //bool $modelWasUpdated = Builder::model(MyModel::class)->update(1, ['name' => 'test']); //bool $modelWasDeleted = Builder::model(MyModel::class)->delete(1); //bool
To use it with your model simply add implements Restful
, and use the trait InteractsWithRest