{"id":13805738,"url":"https://github.com/liyu001989/lumen-api-demo","last_synced_at":"2025-04-12T20:46:45.708Z","repository":{"id":85942062,"uuid":"44219096","full_name":"liyu001989/lumen-api-demo","owner":"liyu001989","description":"Lumen rest api demo with Dingo/Api, JWT, CORS, PHPUNIT","archived":false,"fork":false,"pushed_at":"2022-09-03T03:51:48.000Z","size":1076,"stargazers_count":852,"open_issues_count":7,"forks_count":219,"subscribers_count":57,"default_branch":"master","last_synced_at":"2025-04-04T00:10:05.916Z","etag":null,"topics":["dingo-api","laravel","lumen","lumen-framework"],"latest_commit_sha":null,"homepage":"http://lumen.lyyw.info/apidoc/","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/liyu001989.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}},"created_at":"2015-10-14T02:29:06.000Z","updated_at":"2025-03-18T18:14:42.000Z","dependencies_parsed_at":"2023-03-04T11:15:26.609Z","dependency_job_id":null,"html_url":"https://github.com/liyu001989/lumen-api-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liyu001989%2Flumen-api-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liyu001989%2Flumen-api-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liyu001989%2Flumen-api-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liyu001989%2Flumen-api-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liyu001989","download_url":"https://codeload.github.com/liyu001989/lumen-api-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631713,"owners_count":21136559,"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":["dingo-api","laravel","lumen","lumen-framework"],"created_at":"2024-08-04T01:01:04.368Z","updated_at":"2025-04-12T20:46:45.686Z","avatar_url":"https://github.com/liyu001989.png","language":"PHP","funding_links":["https://paypal.me/liyu001989"],"categories":["PHP","Demos"],"sub_categories":[],"readme":"# lumen-api-demo\n\n这是一个比较完整用 lumen 5.7 写的的 REST API 例子。使用了 `dingo/api` ，jwt 实现登录，功能上很简单，登录，注册，发帖，评论，单元测试(正在补充)。\n\n[![StyleCI](https://styleci.io/repos/44219096/shield)](https://styleci.io/repos/44219096)\n[![License](https://img.shields.io/github/license/liyu001989/lumen-api-demo.svg)](LICENSE)\n[![donate](https://img.shields.io/badge/paypal-donate-red.svg)](https://paypal.me/liyu001989)\n[![donate](https://img.shields.io/badge/%E7%BA%A2%E5%8C%85-donate-red.svg)](https://cloud.githubusercontent.com/assets/2981799/25706351/cfba493c-3112-11e7-9985-aec05ff9734c.png)\n\nlumen5.x 请看对应的分支\n\n有需要随时联系我\n\n- lumen/laravel/restful 交流群: 216721539 (备注 laravel 或 lumen)\n- email: liyu001989@gmail.com\n\n[ENGLISH README](./EN_README.md)\n\n## 教程\n\n[Laravel 教程 - 实战构架 API 服务器](https://laravel-china.org/courses/laravel-advance-training-5.5)\n\n## USEFUL LINK\n\n读文档很重要，请先仔细读读文档 laravel, dingo/api，jwt，fractal 的文档。\n\n- dingo/api [https://github.com/dingo/api](https://github.com/dingo/api)\n- dingo api 中文文档 [dingo-api-wiki-zh](https://github.com/liyu001989/dingo-api-wiki-zh)\n- jwt(json-web-token) [https://github.com/tymondesigns/jwt-auth](https://github.com/tymondesigns/jwt-auth)\n- transformer [fractal](http://fractal.thephpleague.com/)\n- apidoc 生成在线文档 [apidocjs](http://apidocjs.com/)\n- rest api 参考规范 [jsonapi.org](http://jsonapi.org/format/)\n- api 调试工具 [postman](https://www.getpostman.com/)\n- 有用的文章 [http://oomusou.io/laravel/laravel-architecture](http://oomusou.io/laravel/laravel-architecture/)\n- php lint [phplint](https://github.com/overtrue/phplint)\n- Laravel 理念 [From Apprentice To Artisan](https://my.oschina.net/zgldh/blog/389246)\n- 我对 REST 的理解 [http://blog.lyyw.info/2017/02/09/2017-02-09%20%E5%AF%B9rest%E7%9A%84%E7%90%86%E8%A7%A3/](http://blog.lyyw.info/2017/02/09/2017-02-09%20%E5%AF%B9rest%E7%9A%84%E7%90%86%E8%A7%A3/)\n\n## USAGE\n\n```\n$ git clone git@github.com:liyu001989/lumen-api-demo.git\n$ composer install\n$ 设置 `storage` 目录必须让服务器有写入权限。\n$ cp .env.example .env\n$ vim .env\n    DB_*\n        填写数据库相关配置 your database configuration\n    JWT_SECRET\n        php artisan jwt:secret\n    APP_KEY\n        lumen 取消了key:generate 所以随便找个地方生成一下吧\n        md5(uniqid())，str_random(32) 之类的，或者用jwt:secret生成两个copy一下\n\n$ php artisan migrate\n$ php artisan db:seed (默认添加了10个用户，50篇帖子, 100条评论)\n\n头信息中可以增加 Accept:application/vnd.lumen.v1+json 切换v1和v2版本\n\napi文档在public/apidoc里面有一份，网络不好的可以直接查看本地的文档, 也可以看上面的 `项目api在线文档`\n\n我是这样生成的: apidoc -i App/Http/Controllers/Api/V1/ -o public/apidoc/\n\n```\n如果访问一直不对，可以进入public 目录执行 `php -S localhost:8000 -t public`，然后尝试调用几个接口，从而确定是否为web服务器的配置问题。\n\n## REST API DESIGN\n\n大概举个例子说明一下 rest api 吧\n\ngithub 的 api 真的很有参考价值 [github-rest-api](https://developer.github.com/v3/)\n\n        例子： 用户，帖子，评论\n        get    /api/posts              \t 帖子列表\n        post   /api/posts              \t 创建帖子\n        get    /api/posts/5            \t id为5的帖子详情\n        put    /api/posts/5            \t 替换帖子5的全部信息\n        patch  /api/posts/5            \t 修改部分帖子5的信息\n        delete /api/posts/5            \t 删除帖子5\n        get    /api/posts/5/comments     帖子5的评论列表\n        post   /api/posts/5/comments     添加评论\n        get    /api/posts/5/comments/8   id为5的帖子的id为8的评论详情\n        put    /api/posts/5/comments/8   替换帖子评论内容\n        patch  /api/posts/5/comments/8   部分更新帖子评论\n        delete /api/posts/5/comments/8   删除某个评论\n        get    /api/users/4/posts        id为4的用户的帖子列表\n        get    /api/user/posts           当前用户的帖子列表\n\n        // 登录，刷新，登出\n        // 或许可以有更好的命名\n        post    /api/authorizations  创建一个token\n        put     /api/authorizations/current  刷新当前 token\n        delete  /api/authorizations/current  删除当前 token\n\n## 问题总结\n\n\u003cdetails\u003e\n  \u003csummary\u003eLumne 和 Laravel 选哪个\u003c/summary\u003e\n\n  首先建议大家使用 Laravel，参考超哥的答案 [https://laravel-china.org/articles/5079/laravel-or-lumen](https://laravel-china.org/articles/5079/laravel-or-lumen)。Laravel 提供了更全的功能，更容易使用，非常方便。Lumen 只是为了Api 而生，而我们通常的业务场景会是一套 Api 和一套后台管理系统，使用 Laravel 会让你更快更好的完成需求。非常非常不建议新手直接使用 Lumen。\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ejwt 使用\u003c/summary\u003e\n\nlumen 5.2 取消了session，没有了 auth 的实例，所以使用jwt的时候需要配置一下，注意 config/auth.php 中的配置，而且 user 的 model 需要实现 `Tymon\\JWTAuth\\Contracts\\JWTSubject`;\n\n基本用法, jwt 会 encode 对应模型的 id，生成token，客户端拿到 token，放在 Authorization header 中\n\n```\nAuthorization: Bearer token\n```\n\n验证的逻辑就是 decode token 拿到id，然后找到对应的用户。当然了，你可能需要 encode 额外的字段，那么可以使用 CustomClaims。\n\ntoken 有两个时间，一个是过期时间(ttl)，一个是可刷新时间(refresh_ttl)。怎么理解，比如 ttl 是 1 天，refresh_ttl 是1周，那么 token 一天后过期，但是1周之内你仍然可以用这个 token 换取一个新的 token，而这个新 token 又会在 1 天后过期，1周内可刷新。\n\n举个例子，用户登录了你的应用，并且每天都会打开你的应用，你的应用如果发现这个 token 过期了，会主动刷新一次，如果成功那么用户依然是登录的。当用户1周都没有登录过你的应用，那么他就需要重新登录了。\n\n客户端的逻辑应该是，首先判断这个 token 是否过期了，1是通过两个 ttl 判断，因为客户端是知道这两个时间的，2是调用需要授权的接口返回的状态码（401），判断过期了则主动尝试刷新，刷新成功了，重置token和时间，失败了，则跳转到登录页面。\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e使用mail\u003c/summary\u003e\n\n  写了个例子，注册之后给用户发送邮件, 可以参考一下。\n\n- composer 加 illuminate/mail 和 guzzlehttp/guzzle 这两个库\n- 在 bootstrap/app.php 或者 provider 中注册 mail 服务\n- 增加配置 mail 和 services, 从 laravel 项目里面 cp 过来\n- 在 env 中增加 `MAIL_DRIVER`，账户，密码等配置\n  \u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003etransformer 的正确使用\u003c/summary\u003e\n\n  transformer 是个数据转换层，帮助你格式化资源。还可以帮助你处理资源之间的引用关系。\n\n  试着体会一下以下几个url的也许就明白了\n\n  - [http://lumen.lyyw.info/api/posts](http://lumen.lyyw.info/api/posts)  所有帖子列表\n  - [http://lumen.lyyw.info/api/posts?include=user](http://lumen.lyyw.info/api/posts?include=user) 所有帖子列表及发帖用户\n  - [http://lumen.lyyw.info/api/posts?include=user,comments](http://lumen.lyyw.info/api/posts?include=user,comments) 帖子列表及发帖的用户和发帖的评论\n  - [http://lumen.lyyw.info/api/posts?include=user,comments:limit(1)](http://lumen.lyyw.info/api/posts?include=user,comments:limit(1)) 帖子列表及发帖的用户和发帖的1条评论\n  - [http://lumen.lyyw.info/api/posts?include=user,comments.user](http://lumen.lyyw.info/api/posts?include=user,comments.user) 帖子列表及发帖的用户和发帖的评论，及评论的用户信息\n  - [http://lumen.lyyw.info/api/posts?include=user,comments:limit(1),comments.user](http://lumen.lyyw.info/api/posts?include=user,comments:limit(1),comments.user)  帖子列表及发帖的用户和发帖的1条评论，及评论的用户信息，及评论的用户信息\n\n\n  是不是很强大，我们只需要提供资源，及资源之间的引用关系，省了多少事\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003etransformer 如何自定义格式化资源\u003c/summary\u003e\n\ndingo/api 使用了 [Fractal](http://fractal.thephpleague.com/) 做数据转换，fractal 提供了3种基础的序列化格式，Array，DataArray，JsonApi，在这里有详细的说明 [http://fractal.thephpleague.com/serializers/](http://fractal.thephpleague.com/serializers/)。DataArray 是默认的，也就是所有资源一定有data和meta。当然也可以按下面这样自定义：\n\n        只需要在 bootstrap/app.php 中设置 serializer 就行了。具体见 bootstrap/app.php 有注释\n        $app['Dingo\\Api\\Transformer\\Factory']-\u003esetAdapter(function ($app) {\n            $fractal = new League\\Fractal\\Manager;\n            // 自定义的和fractal提供的\n            // $serializer = new League\\Fractal\\Serializer\\JsonApiSerializer();\n            $serializer = new League\\Fractal\\Serializer\\ArraySerializer();\n            // $serializer = new App\\Serializers\\NoDataArraySerializer();\n            $fractal-\u003esetSerializer($serializer);,\n            return new Dingo\\Api\\Transformer\\Adapter\\Fractal($fractal);\n        });\n\n个人认为默认的 DataArray 就很好用了，基本满足了 API 的需求\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e422 错误提示\u003c/summary\u003e\n\n  参考了 github 的错误提示，这样可能更方便 app 对接，格式固定有field 和code，field为字段名，code为错误提示。\n\n  如果想用默认的，在 BaseController 中使用下面的代码即可\n  `throw new ValidationHttpException($validator-\u003eerrors());`\n\u003c/details\u003e\n\n## TODO\n- [ ] 单元测试\n\n## 坑\n- [https://github.com/dingo/api/issues/672](https://github.com/dingo/api/issues/672)  `transformer include`\n- 如果 .env 的某个值中有空格会报错 log not found。env 中的值有空格需要引号包裹\n\n## License\n\n[MIT license](http://opensource.org/licenses/MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliyu001989%2Flumen-api-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliyu001989%2Flumen-api-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliyu001989%2Flumen-api-demo/lists"}