{"id":41706816,"url":"https://github.com/phpsa/laravel-api-controller","last_synced_at":"2026-01-24T21:33:04.409Z","repository":{"id":34913198,"uuid":"189528768","full_name":"phpsa/laravel-api-controller","owner":"phpsa","description":"Laravel Api Quickstart ","archived":false,"fork":false,"pushed_at":"2025-05-18T22:01:19.000Z","size":558,"stargazers_count":47,"open_issues_count":2,"forks_count":18,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-22T00:51:29.612Z","etag":null,"topics":["api","laravel","rest-api"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phpsa.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"phpsa"}},"created_at":"2019-05-31T04:42:01.000Z","updated_at":"2025-05-18T22:01:22.000Z","dependencies_parsed_at":"2023-01-15T10:18:07.480Z","dependency_job_id":"163be5e6-9796-4d7d-8fdb-c9681da19985","html_url":"https://github.com/phpsa/laravel-api-controller","commit_stats":{"total_commits":248,"total_committers":14,"mean_commits":"17.714285714285715","dds":0.5362903225806452,"last_synced_commit":"c81106f9dac2ea8b9a3c896f09f98675947a9b6d"},"previous_names":[],"tags_count":181,"template":false,"template_full_name":null,"purl":"pkg:github/phpsa/laravel-api-controller","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpsa%2Flaravel-api-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpsa%2Flaravel-api-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpsa%2Flaravel-api-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpsa%2Flaravel-api-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phpsa","download_url":"https://codeload.github.com/phpsa/laravel-api-controller/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpsa%2Flaravel-api-controller/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28737323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T21:19:41.845Z","status":"ssl_error","status_checked_at":"2026-01-24T21:13:38.675Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","laravel","rest-api"],"created_at":"2026-01-24T21:33:03.876Z","updated_at":"2026-01-24T21:33:04.400Z","avatar_url":"https://github.com/phpsa.png","language":"PHP","funding_links":["https://github.com/sponsors/phpsa"],"categories":[],"sub_categories":[],"readme":"# Laravel Api Controller\n\n[[_TOC_]]\n\n[![For Laravel 9 to 10][badge_laravel]](https://github.com/phpsa/laravel-api-controller/issues)\n[![Build Status](https://api.travis-ci.com/phpsa/laravel-api-controller.svg?branch=master)](https://travis-ci.com/phpsa/laravel-api-controller)\n[![Coverage Status](https://coveralls.io/repos/github/phpsa/laravel-api-controller/badge.svg?branch=master)](https://coveralls.io/github/phpsa/laravel-api-controller?branch=master)\n[![Packagist](https://img.shields.io/packagist/v/phpsa/laravel-api-controller.svg)](https://packagist.org/packages/phpsa/laravel-api-controller)\n[![Packagist](https://poser.pugx.org/phpsa/laravel-api-controller/d/total.svg)](https://packagist.org/packages/phpsa/laravel-api-controller)\n[![Packagist](https://img.shields.io/packagist/l/phpsa/laravel-api-controller.svg)](https://packagist.org/packages/phpsa/laravel-api-controller)\n[![Github Issues][badge_issues]](https://github.com/phpsa/laravel-api-controller/issue)\n\nBasic CRUD API Methods that can be extended for your models by default has a list, show, update, add and delete endpoint to interact with your model.\n\n## Installation\n\nInstall via composer\n\n```bash\ncomposer require phpsa/laravel-api-controller\n```\n\n### Publish Configuration File (optional - if you need to change any of the default configurations)\n\n```bash\nphp artisan vendor:publish --provider=\"Phpsa\\LaravelApiController\\ServiceProvider\" --tag=\"config\"\n```\n\n## Usage\n\n**CLI Commands**\n\n* `artisan make:api:controller {ControllerName}` to generate the controller\n* `artisan make:api:policy {PolicyName} -m {Model}` to generate a policy file\n* `artisan make:api:resource {ResourceName|CollectionName}` to geneate the response resource\n\nThis will create a Api/ModelNameController for you and you will have the basic routes in place as follows:\n\n- GET `api/v1/{model_name}` - list all/paged/filtered (class::index)\n- GET `api/v1/{model_name}/$id` - Show a specified id (class::show)\n- POST `api/v1/{model_name}` - Insert a new record (class::store)\n- PUT `api/v1/{model_name}/$id` - Replace an existing record (class::update)\n- PATCH `api/v1/{model_name}/$id` - Update an existing record (class::update)\n- DELETE `api/v1/{model_name}/$id` - Delete an existing record (class::destroy)\n\nIf you specify `--soft-deletes` option on `make:api:controller` it will also create an additional `restore` controller endpoint \u0026 route:\n- PATCH `api/v1/{model_name}/$id` - Restore a soft-deleted record (class::restore). This only works for models with Soft Deletes enabled.\n\nYou can override the methods by simply putting in your own methods to override - method names in braces above\n\n## Events\n\n- POST (class::store) - triggers a new `Phpsa\\LaravelApiController\\Events\\Created` Event which has the new record available as `$record`\n- PUT (class::update) - triggers a new `Phpsa\\LaravelApiController\\Events\\Updated` Event which has the updated record available as `$record`\n- DELETE (class::destroy) - triggers a new `Phpsa\\LaravelApiController\\Events\\Deleted` Event which has the deleted record available as `$record`\n\n## Policies\n\nPolicies: https://laravel.com/docs/6.x/authorization#generating-policies\n\nGenerate with `php artisan make:policy PostPolicy --model=Post`\n\n- Get list - calls the `viewAny` policy\n- Get single - calls the `view` policy\n- Post New - calls the `create` policy\n- Put Update - calls the `update` policy\n- Delete item - calls the `delete` policy\n\nQuery/Data modifiers in policies for the api endpoints\n\n- `qualifyCollectionQueryWithUser($user, $repository)` -\u003e return void - add any queries to the repository (ie -\u003ewhere('x','))\n- `qualifyItemQueryWithUser($user, $repository)`-\u003e return void - add any queries to the repository (ie -\u003ewhere('x','))\n- `qualifyStoreDataWithUser($data)` - return the updated data array\n- `qualifyUpdateDataWithUser($data)` - return the updated data array\n\n## Resources / Collections (Transforming)\n\nResources: https://laravel.com/docs/6.x/eloquent-resources\n\nGenerate with\n`php artisan make:apiresource UserResource` and `php artisan make:api:resource UserCollection`\n\nChange the Resource to extend from:\n\nuse `Phpsa\\LaravelApiController\\Http\\Resources\\ApiResource` for your resource\nuse `Phpsa\\LaravelApiController\\Http\\Resources\\ApiCollection` for your resource collection\n\nin your controller override the following params:\n\n```php\n\tprotected $resourceSingle = UserResource::class;\n\tprotected $resourceCollection = UserCollection::class;\n```\n\n## Snake vs Camel\n\n- middleware to convert all camel to snake: `Phpsa\\LaravelApiController\\Http\\Middleware\\SnakeCaseInputs`\n- set request header `X-Accept-Case-Type` to either `snake` or `camel` to alter your data response\n\n## Filtering\n\n ### stable option that will be removed once experimental stable\n\nFor the get command you can filter by using the following url patterns\n\n| Seperator | Description                                     | Example                | Result                                    |\n| --------- | ----------------------------------------------- | ---------------------- | ----------------------------------------- |\n| _`=`_     | Equals                                          | ?filter[field]=hello   | select ... where field = 'hello'          |\n| _`!=`_    | Not Equals                                      | ?filter[field!]=hello  | select ... where field != 'hello'         |\n| _`\u003c\u003e`_    | Not Equals (alt)                                | ?filter[field\u003c\u003e]=hello | select ... where field != 'hello'         |\n| _`\u003e`_     | Greater Than                                    | ?filter[field\u003e]=5      | select ... where field \u003e 5                |\n| _`\u003e=`_    | Greater Or Equal to                             | ?filter[field\u003e=]=5     | select ... where field \u003e= 5               |\n| _`\u003c`_     | Less Than                                       | ?filter[field\u003c]=5      | select ... where field \u003c\u003e 5               |\n| _`\u003c=`_    | Less Or Equal to                                | ?filter[field\u003c=]=5     | select ... where field \u003c= 5               |\n| _`~`_     | Contains (LIKE with wildcard on both sides)     | ?filter[field~]=hello  | select ... where field like '%hello%'     |\n| _`^`_     | Starts with (LIKE with wildcard on end)         | ?filter[field^]=hello  | select ... where field like 'hello%'      |\n| _`$`_     | Ends with (LIKE with wildcard on start)         | ?filter[field$]=hello  | select ... where field like 'hello%'      |\n| _`!~`_    | Not Contains (LIKE with wildcard on both sides) | ?filter[field!~]=hello | select ... where field not like '%hello%' |\n| _`!^`_    | Not Starts with (LIKE with wildcard on end)     | ?filter[field!^]=hello | select ... where field not like 'hello%'  |\n| _`!$`_    | Not Ends with (LIKE with wildcard on start)     | ?filter[field!$]=hello | select ... where field not like 'hello%'  |\n\n# In / Not In\n\nYou can pass to the filters an array of values\nie: `filter[user_id]=1||2||||4||7` or `filter[user_id!]=55||33`\n\n# Null / Not Null (introduced 1.23.0)\n\nIf you need to filter on whether a field is null or not null, you can use the filter param as of version 1.23.0 EG: `filter[age]=NULL` or `filter[age!]=NULL`. Note that NULL must be uppercase.\n\n**Older versions**\nAdd a scope to your model: eg\n\n```php\n\npublic function scopeAgeNull(Builder $builder, $isNull = true){\n  $isNull ? $builder-\u003ewhereNull('age') : $builder-\u003ewhereNotNull('age');\n}\n```\n\nAdd to your allowedScopes and can then be called in url as `?ageNull=1` for where null and `?ageNull=0` for where age not null\n\n\n\n### Filtering \n\n- use the url pattern `filters[column][operator]=value` eg `filters[age][\u003e]=18\u0026filters[title][contains]=testing`\n\n| Seperator | Description                                     | Example                | Result                                    |\n| --------- | ----------------------------------------------- | ---------------------- | ----------------------------------------- |\n| empty / _`=`_ / `is` / `equals`    | Equals                                          | ?filters[field]=hello / ?filters[field][is]=hello  | select ... where field = 'hello'          |\n| _`!=`_ / `!is` / `!equals` / `not_equals`  | Not Equals                                      | ?filters[field][!is]=hello  | select ... where field != 'hello'         |\n| _`\u003e`_ / `greater_than`    | Greater Than                                    | ?filters[field][greater_than]=5      | select ... where field \u003e 5                |\n| _`\u003e=`_ / `greater_than_or_equal_to` / `greater_or_equal` / `gte`  | Greater Or Equal to                             | ?filters[field][greater_or_equal]=5     | select ... where field \u003e= 5               |\n| _`\u003c`_  / `less_than`   | Less Than                                       | ?filters[field][\u003c]=5      | select ... where field \u003c\u003e 5               |\n| _`\u003c=`_ / `less_than_or_equal_to` / `less_or_equal` / `lte`  | Less Or Equal to                                | ?filters[field][less_or_equal]=5     | select ... where field \u003c= 5               |\n| _`~`_  / `contains`   | Contains (LIKE with wildcard on both sides)     | ?filters[field][contains]=hello  | select ... where field like '%hello%'     |\n| _`^`_  / `starts_with`   | Starts with (LIKE with wildcard on end)         | ?filters[field][starts_with]=hello  | select ... where field like 'hello%'      |\n| _`$`_  / `ends_with`   | Ends with (LIKE with wildcard on start)         | ?filters[field][ends_with]=hello  | select ... where field like 'hello%'      |\n| _`!~`_ / `!contains` / `not_contains`  | Not Contains (LIKE with wildcard on both sides) | ?filters[field][!contains]=hello | select ... where field not like '%hello%' |\n| _`!^`_ / `!starts_with` / `not_starts_with`   | Not Starts with (LIKE with wildcard on end)     | ?filters[field][!^]=hello | select ... where field not like 'hello%'  |\n| _`!$`_ / `!ends_with` /   `not_ends_with`   | Not Ends with (LIKE with wildcard on start)     | ?filters[field][!$]=hello | select ... where field not like 'hello%'  |\n| `in`   | in    | ?filters[field][in]=1,2,3 | select ... where field in(1,2,3)  |\n| `not_in`  / `!in`  | NOT in    | ?filters[field][in]=1,2,3 | select ... where field not in(1,2,3)  |\n| `has`   | has    | ?filters[field][has] | select ... where exists(field join)  |\n| `not_has`  / `!has`  | NOT has    | ?filters[field][!has] | select ... where not exists (field join)  |\n\n* Null = `filters[age]=NULL` will generate `where age is null`\n\n* Json columns = `filters[meta-\u003eseo][is]=enabled` will generate\n```\nwhere json_unquote(json_extract(`meta\\`, '$.\"seo\"')) = 'enabled'\n```\n\n* Relations: `filters[relationName][has]` or `filters[relationName][!has]` or `filters[relation_name][not_has]`\n* Relations filtering `filters[tags][has][slug]=my_slug`\n* Relations `filters[tags]=true` or `filters['tags.slug']=myslug` `filters[tags.slug][!]=myslug` `filters[tags.slug][!][contains]=money`\n\nEnforced scopes / query filters on a controller override the\n```\nprotected function getNewQuery(): Builder\n    {\n        return resolve($this-\u003emodel())-\u003enewQuery();\n    }\n```\nmethod in your controller to include any additional queries / scopes etc.\n\n## Requests\n\nWe have added a request macro to enable you to set these on your request as needed:\n\neg:\n```php\n    public function index(Request $request)\n    {\n\n        $request-\u003eapiFilter('user_id', auth()-\u003eid());\n        $request-\u003eapiFilter('owner_id', 'not_equals', auth()-\u003eid());\n        $request-\u003eapiFilter('age', '\u003e=', 5);\n        $request-\u003eapiFilter('age', '\u003c=', 10);\n        $request-\u003eapiInclude(['owner','user']);\n        $request-\u003eapiAddFields(['x','y','z']);\n\n```\n\n* filter method is `apiFilter($column, $value)` or `apiFilter($column, $operator, $value)`\n* addfields method is `apiAddFields(array|string $fieldsOrAttributesToInclude)`\n* include method is `apiInclude(array|string $relations)`\n\n\n\n\nIn your controller, we generally use `request-\u003eall()` for the filling of models. Should you wish to use a more strict option, you can opt into using validated values only by calling `$this-\u003esetOnlyValidated()` in your controller which will then use the `request-\u003evalidated()` to get the data (Note: this means it will not take any merged information from postValidation).\n\n## Scopes\n\nIn addition to filtering, you can use Laravel's Eloquent [Query Scopes](https://laravel.com/docs/6.x/eloquent#local-scopes) to do more complex searches or filters.\nSimply add an `$allowedScopes` to your `ApiResource`, and that scope will be exposed as a query parameter.\n\nAssuming you have a `scopeFullname` defined on your Eloquent Model, you can expose this scope to your API as follows:\n\n```php\nprotected static $allowedScopes = [\n  'fullname'\n];\n```\n\nGiven the above `$allowedScopes` array, your API consumers will now be able to request `?fullname=John`. The query parameter value will be passed to your scope function in your Eloquent Model.\n\n## Filtering on related models\n\nYou can easily filter using any related model that is configured for `include`. Simply specify `?filter[model.field]=123` in your query string. The same filter options above apply to related fields.\n\n## Grouped Filtering Scopes\n\n`filter_by_relation_group[a][name]=weight\u0026filter_by_relation_group[a][value][\u003e]=900\u0026filter_by_relation_group[b][name]=color\u0026filter_by_relation_group[b][value]=color`\n\n```\n public function scopeFilterByRelationGroup(Builder $builder, array $wheres): void\n    {\n        $where =  collect($wheres)-\u003emap(fn ($child) =\u003e\n           $this-\u003eparseFiltersArray($child)\n        )-\u003eeach(\n            fn($group, $key) =\u003e $builder-\u003ewhereHas('Relation', function ($subQ) use ($group, $key) {\n                $group-\u003eeach(\n                    fn($filter, $column) =\u003e collect($filter)-\u003eeach(fn($value, $comparison) =\u003e $this-\u003ebuildQuery($column, $comparison, $value, $subQ))\n                );\n            }\n            )\n        );\n\n    }\n  ```\n\n# Fields, Relationships, Sorting \u0026 Pagination\n\n## Fields\n\nBy default all fields are returned, you can limit that to specific fields in the following ways:\n\n- Api Controller parameter `$defaultFields` default as `protected $defaultFields = ['*'];` - switch to include an array of fields\n- fields param in url querystring: ie `fields=id,name,age` = will only return those, this will also override the above.\n- in your response resource you can set the static::allowedFields to lock down which fields are returnable.\n  - This also controls which related resources are returnable. Include the key that is used in `$mapResources` (see \"Relationships\" below).\n- `addfields` and `removefields` params in url querystring will work with these.\n- Use laravel [eloquent model `$appends`](https://laravel.com/docs/6.x/eloquent-serialization#appending-values-to-json) property to automatically include custom attribute accessors.\n\n### Gated Response Fields\n\nGates can be used to control access to fields and related resources, by defining `$gatedFields`:\n\n```\nprotected static array $fieldGates = [\n    'gate-one' =\u003e [\n        'fieldA',\n        'fieldB',\n     ],\n     'gate-two' =\u003e [\n       'fieldA',\n       'fieldC,\n       'relatedResourceD'\n     ]\n];\n```\n\nEach specified gate will be used to determine whether that set of fields will be included.\n\nEach gate will be passed the resource as well as the user, so it can test whether the user should be allowed to access that specific resource.\n\nExample gate definition:\n\n```\n  Gate::define(\n      'supervises-the-group',\n      fn ($user, Group $group) =\u003e (int) $user-\u003eid === $group-\u003esupervisor_id\n  );\n```\n\n## Relationships\n\n- Using the relationships defined in your models, you can pass a comma delimited list eg `include=join1,join2` which will return those joins (one or many).\n\nSimply add a `protected static $mapResources` to your `Resource` to define which resources to assign your related data. E.e., for a one to many relationship, you should specify a collection, and a one-to-one relationship specify the related resource directly. This will allow the API to properly format the related record.\n\n```\n    protected static $mapResources = [\n        'notes' =\u003e NotesCollection::class,\n        'owner' =\u003e OwnerResource::class\n    ];\n```\n\n- You can automatically update and create related records for most types of relationships. Just include the related resource name in your POST or PUT request.\n- Important: if you are using `$defaultFields` and/or `$allowedFields` in your resource, the related resource key from `$mapResources` must also be included in those lists for that related resource to be included.\n\nFor `BelongsToMany` or `MorphToMany` relationships, you can choose the sync strategy. By default, this will take an _additive_ strategy. That is to say, related records sent will be ADDED to any existing related records. On a request-by-request basis, you can opt for a _sync_ strategy which will remove the pivot for any related records not listed in the request. Note the actual related record will not be removed, just the pivot entry.\n\nTo opt for the _sync_ behavaiour, set `?sync[field]=true` in your request.\n\n## Sorting\n\n- Sorts can be passed as comma list aswell, ie `sort=age asc` or `sort=age asc,name desc,eyes` - generates sql of `sort age asc` and `sort age asc, name desc, eyes asc` respectively\n- Default sort can also be added on the controller using by overrideing the `protected $defaultSort = null;` parameter\n\n## Pagination\n\n- pagination can be enabled/disbled on the controller by overriding the `protected $defaultLimit = 25;` on the controller\n- pagination can also be passed via the url using `limit=xx\u0026page=y`\n- pagination can also be limited to a max per page by overriding the `protected $maximumLimit = false;` parameter\n\n## Validation\n\n- When Posting a new record, validation can be done by adding a `rulesForCreate` method to your controller returning an array eg\n\n```php\n[\n    'email' =\u003e 'required|email',\n    'games' =\u003e 'required|numeric',\n]\n```\n\nsee https://laravel.com/docs/5.8/validation#conditionally-adding-rules\n\n- for updating a record, add a method `rulesForUpdate` per above.\n\n## Defaults\n\nThe following parameters are set in the Base Api controller and can be overwritten by your Controller on a case by case basis:\n- `protected $resourceSingle = JsonResource::class;` Collection to use for your single resource\n- `protected $resourceCollection = ResourceCollection::class;` Collection to use for your resource collection\n- `protected $defaultFields = ['*'];` Default Fields to respond with\n- `protected $defaultSort = null;` Set the default sorting for queries.\n- `protected $defaultLimit = 25;` Number of items displayed at once if not specified. (0 = maximumLimit)\n- `protected $maximumLimit = 0;` Maximum limit that can be set via \\$\\_GET['limit']. - this ties in with the defaultLimit aswell, and if wanting to disable pagination , both should be 0. ) will allow all records to be returned in a single call.\n- `protected $unguard = false;` Do we need to unguard the model before create/update?\n\n## Scopes\n\n### SoftDeleted Records\n\nadd the `Phpsa\\LaravelApiController\\Model\\Scopes\\WithSoftDeletes` trait to your model,\nadd to your resource file:\n\n```php\nclass MyModelResource extends ApiResource\n{\n\n protected static $allowedScopes = [\n        'withTrashed',\n        'onlyTrashed'\n    ];\n```\n\nyou can now append `withTrashed=1` or `onlyTrashed=1` to your query.\n\n## Responses\n\nyou can override responses for each point by overriding the following protected methods:\n\n- handleIndexResponse\n- handleStoreResponse\n- handleShowResponse\n- handleUpdateResponse\n- handleDestroyResponse\n\n## Perforance Tips\n\n### Cache Table column definitions\n-- introduced https://github.com/phpsa/laravel-api-controller/pull/118/files\nadd the ability to cache the table definitions to reduce calls to fetch table columns, to enable either enable in the config file or set the `PHPSA_API_CACHE_TABLE_COLUMNS` variable to true.\n\n### Raw Pagination gets\n\n-- handleIndexAction will use full eloquent models, handleIndexActionRaw will bypass eloquent and use raw responses from the database.\n\n## Scramble Intergration\n\nin your scramble config file add  `\\]hpsa\\LaravelApiController\\Scramble\\ApiResourceOpenApi::class` to the extensions array. this will enhance the documentation for apiResources.\n\n## Security\n\nIf you discover any security related issues, please email\ninstead of using the issue tracker.\n\n## Credits\n\n- [Craig G Smith](https://github.com/phpsa)\n- [Sam Sehnert](https://github.com/samatcd)\n- [Phil Taylor](https://github.com/codeberry)\n- [All contributors](https://github.com/phpsa/laravel-api-controller/graphs/contributors)\n\n## Sponsors\n\n- [Custom D](https://customd.com)\n\n[badge_laravel]: https://img.shields.io/badge/Laravel-8.7%20to%209-blue.svg\n[badge_issues]: https://img.shields.io/github/issues/phpsa/laravel-api-controller\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpsa%2Flaravel-api-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphpsa%2Flaravel-api-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpsa%2Flaravel-api-controller/lists"}