{"id":36372142,"url":"https://github.com/gregorip02/restql","last_synced_at":"2026-01-11T14:01:51.843Z","repository":{"id":45161847,"uuid":"247979398","full_name":"gregorip02/restql","owner":"gregorip02","description":"📦 A data resolution package for your Laravel models.","archived":false,"fork":false,"pushed_at":"2022-01-04T15:48:07.000Z","size":953,"stargazers_count":128,"open_issues_count":3,"forks_count":6,"subscribers_count":6,"default_branch":"stable","last_synced_at":"2025-05-23T11:30:12.672Z","etag":null,"topics":["eloquent","laravel","rest-api","restql"],"latest_commit_sha":null,"homepage":"https://github.com/gregorip02/restql/wiki","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/gregorip02.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"custom":["https://www.buymeacoffee.com/BgHiZ9b"]}},"created_at":"2020-03-17T13:39:09.000Z","updated_at":"2025-04-10T12:20:00.000Z","dependencies_parsed_at":"2022-09-10T00:40:12.066Z","dependency_job_id":null,"html_url":"https://github.com/gregorip02/restql","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/gregorip02/restql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorip02%2Frestql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorip02%2Frestql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorip02%2Frestql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorip02%2Frestql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gregorip02","download_url":"https://codeload.github.com/gregorip02/restql/tar.gz/refs/heads/stable","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorip02%2Frestql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28306985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T11:18:18.743Z","status":"ssl_error","status_checked_at":"2026-01-11T11:07:56.842Z","response_time":60,"last_error":"SSL_read: 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":["eloquent","laravel","rest-api","restql"],"created_at":"2026-01-11T14:01:39.183Z","updated_at":"2026-01-11T14:01:51.809Z","avatar_url":"https://github.com/gregorip02.png","language":"PHP","funding_links":["https://www.buymeacoffee.com/BgHiZ9b"],"categories":[],"sub_categories":[],"readme":"# RestQL\n\n[![License](https://poser.pugx.org/gregorip02/restql/license)](//packagist.org/packages/gregorip02/restql)\n[![Latest Stable Version](https://poser.pugx.org/gregorip02/restql/v)](//packagist.org/packages/gregorip02/restql)\n[![Total Downloads](https://poser.pugx.org/gregorip02/restql/downloads)](//packagist.org/packages/gregorip02/restql)\n[![Actions Status](https://github.com/gregorip02/restql/workflows/tests/badge.svg)](https://github.com/gregorip02/restql/actions)\n\nRestQL is a Laravel eloquent-based data resolution package. This package tries to adopt **GraphQL** principles solving only the data that the client requests. RestQL uses your **Laravel** models as an entry point to add queries to then based in the eloquent methods. \n\n**Please see the [documentation](https://github.com/gregorip02/restql/wiki).**\n\n\u003cimg src=\"./example.png\" alt=\"Laravel RestQL\"/\u003e\n\n## **Why?**\n\nImagine you have an application that manages authors, these authors can publish articles and those articles can have comments from different authors. You have a web client, for example, that uses **fetch** to consume the data offered by your service and somewhere in your code, you need a list of the **author's names only**.\n\nThey wear something like that.\n\n```js\nfetch('https://laravel.app/api/authors')\n  .then((res) =\u003e res.json())\n  .then(({ data }) =\u003e console.log(data.authors));\n```\n\nSo, you have a route like this.\n\n`routes/api.php`\n\n```php\n\u003c?php\n\nuse App\\Author;\nuse Illuminate\\Http\\Request;\n\nRoute::get('/authors', function (Request $request) {\n  $authors = Author::take(25)-\u003eget();\n\n  return ['data' =\u003e compact('authors')];\n});\n```\n\nMost likely you will use a controller, then use the author model and query the data.\nFinally you would have a response similar to this.\n\n```javascript\n{\n    \"data\": {\n        \"authors\": [\n            {\n                \"id\": 1,\n                \"name\": \"Lazaro Kohler\",\n                \"email\": \"greenfelder.jenifer@example.org\",\n                \"email_verified_at\": \"2020-03-19T18:11:36.000000Z\",\n                \"created_at\": \"2020-03-19T18:11:36.000000Z\",\n                \"updated_at\": \"2020-03-19T18:11:36.000000Z\"\n              },\n              {\n                \"id\": 2,\n                \"name\": \"Miss Anastasia Klocko DVM\",\n                \"email\": \"lemke.trinity@example.org\",\n                \"email_verified_at\": \"2020-03-19T18:11:36.000000Z\",\n                \"created_at\": \"2020-03-19T18:11:36.000000Z\",\n                \"updated_at\": \"2020-03-19T18:11:36.000000Z\"\n              },\n              { /* 23 more authors */ }\n        ]\n    }\n}\n```\n\nBut what if you only need a **author's names** collection for example? Imagine that your application becomes huge and your user model handles a large number of attributes.\n\n## **Get started**\n\nInstall RestQL using composer.\n\n```bash\ncomposer require gregorip02/restql\n```\n\nPublish the package configuration.\n\n```bash\nphp artisan restql:schema\n```\n\nAdd the `RestqlAttributes` trait to your eloquent models.\n\n\u003e **2.2** This is recomended because you can determine the selectable attributes with `onSelectFillable`.\n\n```php\n\u003c?php\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Restql\\Traits\\RestqlAttributes;\n\nclass Author extends Model\n{\n    use RestqlAttributes;\n\n    // ...\n}\n```\n\nGenerate an `authorizer` for your `App\\Models\\Author` model.\n\n```bash\nphp artisan restql:authorizer AuthorAuthorizer\n```\n\nThis creates a new class in the namespace `App\\Restql\\Authorizers\\AuthorAuthorizer` like the following.\n\n```php\n\u003c?php\n\nnamespace App\\Restql\\Authorizers;\n\nuse Restql\\Authorizer;\n\nfinal class AuthorAuthorizer extends Authorizer\n{\n    // ...\n}\n```\n\nThen add the available HTTP methods to your authorizer as follows.\n\n```php\n\u003c?php\n\nnamespace App\\Restql\\Authorizers;\n\nuse Restql\\Authorizer;\n\nfinal class AuthorAuthorizer extends Authorizer\n{\n    /**\n     * Can get one or more author resources.\n     *\n     * @param  array $clausules\n     * @return bool\n     */\n    public static function get(array $clausules = []): bool\n    {\n        // You could replace this with permission checks or validations.\n        return true;\n    }\n}\n```\n\nThen, set your schema definition.\n\n\u003e Since version 2.x of this package the configuration has been updated to increase flexibility and internal behavior modification.\n\nYou must define your entire schema in the config file, RestQL will then interpret it and execute the queries based on this file. With this there is a possibility that you can remove internal functions, modify them or even create your own implementations. See \u003ca href=\"https://github.com/gregorip02/restql/wiki/Install#schema-definition\"\u003eSchema definition.\u003c/a\u003e\n\n`config/restql.php`\n\n```php\n\u003c?php\n\nuse App\\Models\\Author;\nuse App\\Restql\\Authorizers\\AuthorAuthorizer;\n\nreturn [\n    // ...\n\n    'schema' =\u003e [\n        'authors' =\u003e [\n           'class'  =\u003e Author::class,\n           'authorizer' =\u003e AuthorAuthorizer::class,\n           'middlewares' =\u003e []\n        ]\n    ],\n\n    // ...\n];\n```\n\nThe developer must specify the return type of the relationships defined in the eloquent model. **You should set the return type of your associative methods** (relationships). For example.\n\n`app/Models/Author.php`\n\n```php\n\u003c?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\n\nclass Author extends Model\n{\n    /**\n     * Get the author articles.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n     */\n    public function articles(): {} // Bad\n    public function articles(): HasMany {} // Good\n}\n```\n\nConfigure your endpoint.\n\n`routes/api.php`\n\n```php\n\u003c?php\n\nuse Restql\\Restql;\nuse Illuminate\\Http\\Request;\n\nRoute::get('/restql', fn (Request $request) =\u003e Restql::resolve($request));\n```\n\n## **Refactor time**\n\nNow, you can re-factor your client's code so that it sends a parameter in the request with the data it needs, in this case a collection of author names. They wear something like that.\n\n```js\nconst { stringify } = require('qs');\n\n// Define your queries.\nconst getAuthorsQuery = {\n    authors: {\n        select: ['name']\n    }\n};\n\n// Consume the restql endpoint.\nfetch(`https://laravel.app/restql?${stringify(getAuthorsQuery)}`)\n    .then((res) =\u003e res.json())\n    .then((res) =\u003e console.log(res));\n```\n\nThe parameters of the query should be a parsed objects that defines the clauses accepted by your schema definition. For your web clients **we recommend [qs](https://www.npmjs.com/package/qs).** Instead of having a long JSON response with unnecessary data, you would get something like this.\n\n```javascript\n{\n  \"data\": {\n    \"authors\": [\n        { \"id\": 1, \"name\": \"Kasey Yost\" },\n        { \"id\": 2, \"name\": \"Ike Barton\" },\n        { \"id\": 3, \"name\": \"Emie Daniel\" },\n        { /* 22 more authors */ }\n      ]\n  }\n}\n```\n\nLikewise, this will considerably optimize your queries to the database management system. In this case, it will run just a `select id, name from authors` for example.\n\n\n\n## **The good parts**\n\nSo, let's say you now have a requirement in your application that tells you to have the `id` and `title` of the last **two** articles published by each author.\n\n```js\nconst { stringify } = require('qs');\n\n// Define your queries.\nconst getAuthorsAndTwoLatestArticlesQuery = {\n    authors: {\n        select: ['name'],\n        with: {\n            articles: {\n                take: 2\n                select: 'title',\n                sort: {\n                    column: 'published_at',\n                    direction: 'desc'\n                },\n            }\n        }\n    }\n};\n\n// Consume the restql endpoint.\nfetch(`https://laravel.app/restql?${stringify(getAuthorsAndTwoLatestArticlesQuery)}`)\n    .then((res) =\u003e res.json())\n    .then((res) =\u003e console.log(res));\n```\n\nYou wold get a response like this.\n\n```json\n{\n  \"data\": {\n    \"authors\": [\n        {\n            \"id\": 1,\n            \"name\": \"Kasey Yost\",\n            \"articles\": [\n                {\n                    \"id\": 3434,\n                \t\"title\": \"My awesome article\"\n                }\n            ]\n        },\n        { /* 24 more authors */ }\n      ]\n  }\n}\n```\n\n\n\n## **How it works**\n\nBasically, RestQL filters the keys of the models received in the HTTP request and compares them with the keys of the user configuration. These keys represent a specific eloquent model. The values of these keys are eloquent clauses (methods) accepted by RestQL and the arguments of these clauses are sent as values.\n\nFor example, if a params like the following is sent in the request.\n\n```javascript\n{\n  \"authors\": {\n    \"select\": \"name\",\n    \"with\": {\n      \"articles\": {\n        \"select\": \"title\"\n      }\n    }\n  }\n}\n```\n\nRestQL will interpret this as the following.\n\n```php\n\u003c?php\n\n// Assuming that the parent model we want to obtain is the author's data.\n// The variable $query represents the query constructor of the parent model,\n// in this example, the Author model.\n$query-\u003eselect(['name'])-\u003ewith([\n  'articles' =\u003e static function (Relation $relation) {\n    $relation-\u003eselect(['title']);\n  }\n]);\n```\n\nYou can read more about the RestQL Clausules \u003ca href=\"https://github.com/gregorip02/restql/wiki/Clausules\"\n                                                title=\"RestQL Documentation\"\u003ehere\u003c/a\u003e.\n\n# **What's next?**\n\nAre you interested on contrib to this project? see the \u003ca href=\"./NEXT.md\"\n                                                         title=\"Next features\"\u003eNEXT.md\u003c/a\u003e file.\n\n# **Contributing**\n\nThanks for consider contrib to this project, please see the development docs at this\n\u003ca href=\"https://github.com/gregorip02/restql/wiki/Development\"\u003epage\u003c/a\u003e.\n\n# **Please support it**\n\nThis is a personal project that can be very useful, if you believe it, help me\ndevelop new functionalities and create a pull request, I will be happy to review\nand add it. So, You can also contribute to the team by buying a coffee.\n\n\u003ca href=\"https://www.buymeacoffee.com/BgHiZ9b\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://cdn.buymeacoffee.com/buttons/default-red.png\"\n        style=\"border-radius: 5px;\"\n        alt=\"Buy Us A Coffee\"\n        width=\"300\"\n        height=\"80\"/\u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregorip02%2Frestql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgregorip02%2Frestql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregorip02%2Frestql/lists"}