{"id":15025113,"url":"https://github.com/matthenning/eloquent-api-filter","last_synced_at":"2025-04-12T12:52:25.842Z","repository":{"id":62525239,"uuid":"87320941","full_name":"matthenning/eloquent-api-filter","owner":"matthenning","description":" Awesome and simple way to filter Eloquent queries right from the API URL. ","archived":false,"fork":false,"pushed_at":"2024-01-26T22:53:09.000Z","size":225,"stargazers_count":11,"open_issues_count":2,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-04-29T19:07:12.885Z","etag":null,"topics":["api","eloquent","eloquent-orm","eloquent-relationships","laravel","laravel-framework"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matthenning.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2017-04-05T14:43:41.000Z","updated_at":"2023-07-31T13:59:20.000Z","dependencies_parsed_at":"2024-01-26T12:49:38.606Z","dependency_job_id":"8c52a82e-3717-450c-8047-abae69b124b3","html_url":"https://github.com/matthenning/eloquent-api-filter","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthenning%2Feloquent-api-filter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthenning%2Feloquent-api-filter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthenning%2Feloquent-api-filter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthenning%2Feloquent-api-filter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matthenning","download_url":"https://codeload.github.com/matthenning/eloquent-api-filter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248571605,"owners_count":21126519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","eloquent","eloquent-orm","eloquent-relationships","laravel","laravel-framework"],"created_at":"2024-09-24T20:01:32.091Z","updated_at":"2025-04-12T12:52:25.822Z","avatar_url":"https://github.com/matthenning.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e \u003cimg src=\"logo.png\" width=\"200px\"\u003e\u003c/p\u003e\n\u003ch1 align=\"center\"\u003eEloquent API Filter\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\nAwesome and simple way to create, query and modify Eloquent models through your API - with only a few lines of code.\n\u003c/p\u003e\n\n\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\n\n# Concept\n\nWhen developing API applications, you'll often end up with lots of duplicate code within your controllers. Eloquent API Filter offers a simple way to expose your models through the API by defining a route and a tiny controller.\nYour controller only needs to use a few traits and you'll have a full CRUD implementation for your model exposed through you API.\n\n\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\n\n## Table of Contents\n\n- [Concept](#concept)\n- [Installation](#installation)\n- [Queries](#queries)\n- [Responses](#responses)\n- [What if I need more?](#what-if-i-need-more)\n\n# Installation\n## Package installation\n```bash\ncomposer require matthenning/eloquent-api-filter\n```\n\n## Controller setup\n\nYou have the choice to use either of the following methods to leverage the filter.\nThe easiest method out of the box is to simply extend the included controller.\n\n### Option 1: Extend the controller (recommended)\n\nThe easiest way to use the Eloquent API Filter is to extend its controller.\nFor this example, let's say you have a model named Person. You'll just have to create a matching controller and use the included traits to enable the default methods for index, show, store, update, destroy:\n```php\nuse Matthenning\\EloquentApiFilter\\Controller;\n\nclass PersonController extends Controller\n{\n    use UsesDefaultIndexMethodTrait,\n        UsesDefaultShowMethodTrait,\n        UsesDefaultStoreMethodTrait,\n        UsesDefaultUpdateMethodTrait,\n        UsesDefaultDestroyMethodTrait;\n\n} \n```\n\nNext you can expose your controller by adding a new route:\n\n```php\nRoute::resource('persons', \\App\\Http\\Controllers\\PersonController::class);\n```\n\nEloquent API Filter will automatically find the matching model class as long as you follow the naming scheme of this example. If you have custom names or namespaces, you can override the modelName property within your controller:\n\n```php\nprotected ?string $modelName = Person::class;\n```\n\nAnd you're done! Start querying your API following the method guidelines.\nSee https://laravel.com/docs/10.x/controllers#actions-handled-by-resource-controller for actions store, show, index, update, destroy:\n```http\nPOST /api/persons\n{\n    \"name\": \"Alexander\",\n    \"age\": 23\n}\n\nGET /api/persons/1\n\nGET /api/persons/?filter[age]=23\n\nPUT /api/persons/1\n{\n    \"age\": 24\n}\n\nDELETE /api/persons/1\n```\n\n#### Custom Resource\n\nIf you're using custom resources (https://laravel.com/docs/master/eloquent-resources) you can define a resourceName property on your models. Otherwise the default resource will be used.\nMake sure to override the toArray and call enrich() with your data. The enrich method will make sure all eager loaded relations (/model?with[]=relation1,relation2) are also transformed by their respective resource.\n\nIn your Person model:\n\n```php\npublic static ?string $resourceName = PersonResource::class;\n```\n\nIn your PersonResource:\n\n```php\nclass PersonResource extends \\Matthenning\\EloquentApiFilter\\Resource\n{\n\n    public function toArray(Request $request): array\n    {\n        return $this-\u003eenrich([\n            'id' =\u003e $this-\u003eresource-\u003eid,\n            // ... map your fields here\n        ]);\n    }\n\n}\n```\n\n### Option 2: Use the trait\n\nIf you'd like to handle the controller and resource logic yourself entirely, can use the FiltersEloquentApi trait in your controller.\n\n```php\nclass PersonController extends Matthenning\\EloquentApiFilter\\Controller\n{  \n    \n    use Matthenning\\EloquentApiFilter\\Traits\\FiltersEloquentApi;\n    \n    public function index(Request $request)\n    {\n        $persons = Person::query();\n        \n        return $this-\u003efilterApiRequest($request, $persons);\n    }\n}\n```\n\n### Option 3: Query the filter directly\n\nIf traits are not to your taste you can also initialize Eloquent API Filter yourself.\n\n```php\nuse Matthenning\\EloquentApiFilter\\EloquentApiFilter;\n\nclass PersonController extends Controller\n{    \n    public function index(Request $request)\n    {\n        $query = Person::query();\n        \n        $filtered = (new EloquentApiFilter($request, $query))-\u003efilter();\n        \n        return $filtered-\u003eget();\n    }\n}\n```\n\n\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\n\n# Queries\n\n## Filtering\n\n### URL Syntax\n\nFilter with specific operator: \n```http\nGET /model?filter[field]=operator:comparison\n```\n\nFilter for equality:\n```http\nGET /model?filter[field]=operator\n```\n\n### Operators:\n* eq (equal, can be omitted)\n* ne (not equal)\n* ge (greater or equal)\n* gt (greater)\n* le (lower or equal)\n* lt (lower)\n* in (expects a comma separated array as value)\n* notin (expects a comma separated array as value)\n* null\n* notnull,\n* like\n* notlike\n* today (for timestamps)\n* nottoday (for timestamps)\n\n### Examples\nMatches all entities where name starts with Rob and deceased is null:\n\n```http\nGET /persons?filter[name]=like:Rob*\u0026filter[deceased]=null:\n```\n\nMultiple filters on one field can be chained.\nMatches all entities where created_at is between 2016-12-10 and 2016-12-08:\n\n```http\nGET /persons?filter[created_at]=lt:2016-12-10:and:gt:2016-12-08`\n```\n\nFilter by related models' fields by using the dot-notaion.\nMatches all Posts of Persons where Post name contains \"API\"\n\n```http\nGET /persons?filter[posts.name]=like:*API*\n```\n\nGet all persons with name Rob and Bob\n\n```http\nGET /persons?filter[name]=in:Rob,Bob\n```\n\n### Special filters\n\n#### Timestamps\nMatches all persons whos' birthdays are today\n\n```http\nGET /persons?filter[birthday]=today\n```\n\n\u003cp\u003e\u003c/p\u003e\n\n## Sorting\n\n### URL Syntax\n\n```http\nGET /model?orderBy[field]=direction\n```\n\n### Examples\n\nLimit and sorting.\nMatches the top 10 persons with age of 21 or older sorted by name in ascending order\n\n```http\nGET /persons?filter[age]=ge:21\u0026order[name]=asc\u0026limit=10\n```\n\n\u003cp\u003e\u003c/p\u003e\n\n## Select fields\n\nSelect only specific columns. Might need additional work on your model transformation.\n\n### URL Syntax\n\n```http\nGET /model?select=column1,column2\n```\n\n### Examples\n\n```http\nGET /persons?select=name,email\n```\n\n\u003cp\u003e\u003c/p\u003e\n\n## Joins\n\n### URL Syntax\n\n```http\nGET /model?with[]=relation1\nGET /model?with[]=relation1\u0026filter[relation1.field]=operator:comparison\n```\n\n### Examples\n\nJoin posts-relation on persons\n\n```http\nGET /persons?with[]=posts\n```\n\n\u003cp\u003e\u003c/p\u003e\n\n## Complex filter values\n\nIf you need to filter for a value with special characters, you can base64 encode the field to avoid breaking the filter syntax.\n\n### URL Syntax\n\n```http\nGET /model?filter[field]={{b64(value)}}\n```\n\n### Examples\n\n```http\nGET /model?filter[field]=lt:{{b64(MjAxNy0wNy0yMiAyMzo1OTo1OQ==)}}\n```\n\n\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\n\n# Responses\n\nResponses always contain two JSON objects data and meta.\nData contains the queried models and meta contains for example pagination details.\n\n### Example\n\n```json\n{\n    \"meta\": {\n        \"pagination\": {\n            \"items\": 10,\n            \"total_items\": 113,\n            \"total_pages\": 12,\n            \"current_page\": 1,\n            \"per_page\": 10\n        }\n    },\n    \"data\": [\n        {\n            \"id\": 1,\n            \"name\": \"Alexander\",\n            \"age\": 23\n        },\n        { /*...*/ }, { /*...*/ }\n    ]\n}\n```\n\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\n\n# What if I need more?\n\nIn case you need complex queries which are not covered by this library, you can use the EloquentApiFilter trait in your custom controller and further filter the query before retrieving the models.\nThat way you can still use the filter features and only need to add your custom filtering before returning the retrieved models.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthenning%2Feloquent-api-filter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatthenning%2Feloquent-api-filter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthenning%2Feloquent-api-filter/lists"}