博客列表 >laravel 商城实战开发 Dingoapi 用户管理

laravel 商城实战开发 Dingoapi 用户管理

初见
初见原创
2021年11月24日 17:15:04710浏览

Dingoapi

模型注入

app/Http/Kernel.php

  1. protected $routeMiddleware = [
  2. ......
  3. 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
  4. ];

去除data

https://packagist.org/packages/liyu/dingo-serializer-switch

  1. $api->version('v1',
  2. ['middleware' => 'serializer:array'],
  3. function ($api) {
  4. });

Laravel API 认证:JWT 认证

  • 为什么要用JWT
  • JWT 是什么

文档

什么是 jwt ?

JWT 全称叫 JSON Web Token, 是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。

安装 jwt-auth

  1. composer require tymon/jwt-auth:1.0.x-dev

发布配置

运行以下命令以发布包配置文件:

  1. php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

您现在应该有一个config/jwt.php文件,允许您配置此包的基础知识。

生成密钥

我已经包含了一个帮助命令来为你生成一个密钥:

  1. php artisan jwt:secret

更新您的用户模型

首先,您需要Tymon\JWTAuth\Contracts\JWTSubject在 User 模型上实现合同,这需要您实现 2 个方法getJWTIdentifier()getJWTCustomClaims().

下面的示例应该让您了解它的外观。显然,您应该根据自己的需要进行任何更改。

  1. <?php
  2. namespace App;
  3. use Tymon\JWTAuth\Contracts\JWTSubject;
  4. use Illuminate\Notifications\Notifiable;
  5. use Illuminate\Foundation\Auth\User as Authenticatable;
  6. class User extends Authenticatable implements JWTSubject
  7. {
  8. use Notifiable;
  9. // Rest omitted for brevity
  10. /**
  11. * Get the identifier that will be stored in the subject claim of the JWT.
  12. *
  13. * @return mixed
  14. */
  15. public function getJWTIdentifier()
  16. {
  17. return $this->getKey();
  18. }
  19. /**
  20. * Return a key value array, containing any custom claims to be added to the JWT.
  21. *
  22. * @return array
  23. */
  24. public function getJWTCustomClaims()
  25. {
  26. return [];
  27. }
  28. }

配置身份验证保护

在该config/auth.php文件中,您需要进行一些更改以配置 Laravel 以使用jwt防护来支持您的应用程序身份验证。

对文件进行以下更改:

  1. 'defaults' => [
  2. 'guard' => 'api',
  3. 'passwords' => 'users',
  4. ],
  5. ...
  6. 'guards' => [
  7. 'api' => [
  8. 'driver' => 'jwt',
  9. 'provider' => 'users',
  10. ],
  11. ],

这里我们告诉api守卫使用jwt驱动程序,我们将api守卫设置为默认值。

我们现在可以使用 Laravel 内置的 Auth 系统,由 jwt-auth 在幕后完成工作!

因为我们用的dingoapi 我们还需要在 config/api.php 里面修改:

  1. 'auth' => [
  2. 'jwt' => 'Dingo\Api\Auth\Provider\JWT',
  3. ],

创建路由文件

  1. <?php
  2. use App\Http\Controllers\Api\UserController;
  3. use App\Http\Controllers\Auth\LoginController;
  4. use App\Http\Controllers\Auth\RegisterController;
  5. $api = app('Dingo\Api\Routing\Router');
  6. $api->version(['v1','v2'], ['middleware' => 'api.throttle', 'limit' => 100, 'expires' => 5],function ($api) {
  7. $api->group(['prefix' => 'auth'], function ($api) {
  8. // 注册
  9. $api->post('register', [RegisterController::class, 'store']);
  10. $api->post('login', [LoginController::class, 'login']);
  11. });
  12. });

创建控制器

  1. php artisan make:controller Auth/LoginController
  2. php artisan make:controller Auth/RegisterController

RegisterController

  1. /**
  2. * 用户注册
  3. */
  4. public function store(RegisterRequest $request)
  5. {
  6. $user = new User();
  7. $user->name = $request->input('name');
  8. $user->email = $request->input('email');
  9. $user->password = bcrypt($request->input('password'));
  10. if ($request->input('openid')) $user->openid = $request->input('openid');
  11. if ($request->input('avatar')) $user->avatar = $request->input('avatar');
  12. $user->save();
  13. return $this->response->created();
  14. }

RegisterRequest

创建数据注册数据验证

  1. php artisan make:request Auth/RegisterRequest
  1. /**
  2. * Get the validation rules that apply to the request.
  3. *
  4. * @return array
  5. */
  6. public function rules()
  7. {
  8. return [
  9. 'name' => 'required|max:16',
  10. 'email' => 'required|email|unique:users',
  11. 'password' => 'required|min:6|max:16|confirmed',
  12. 'openid' => 'sometimes|required|unique:users,openid'
  13. ];
  14. }
  15. public function messages()
  16. {
  17. return [
  18. 'name.required' => '昵称 不能为空',
  19. 'name.max' => '昵称 不能超过16个字符',
  20. 'openid.required' => 'openid 不能为空',
  21. 'openid.unique' => 'openid 已绑定其他用户',
  22. ];
  23. }

完成登录

LoginController

文档

因为我们用户有禁用的功能 所以我们还需要调整一下

  1. /**
  2. * Get a JWT via given credentials.
  3. *
  4. * @return \Illuminate\Http\JsonResponse
  5. */
  6. public function login()
  7. {
  8. $credentials = request(['email', 'password']);
  9. if (! $token = auth()->attempt($credentials)) {
  10. return response()->json(['error' => 'Unauthorized'], 401);
  11. }
  12. return $this->respondWithToken($token);
  13. }
  14. /**
  15. * Get the authenticated User.
  16. *
  17. * @return \Illuminate\Http\JsonResponse
  18. */
  19. public function me()
  20. {
  21. return response()->json(auth()->user());
  22. }
  23. /**
  24. * Log the user out (Invalidate the token).
  25. *
  26. * @return \Illuminate\Http\JsonResponse
  27. */
  28. public function logout()
  29. {
  30. auth()->logout();
  31. return response()->json(['message' => 'Successfully logged out']);
  32. }
  33. /**
  34. * Refresh a token.
  35. *
  36. * @return \Illuminate\Http\JsonResponse
  37. */
  38. public function refresh()
  39. {
  40. return $this->respondWithToken(auth()->refresh());
  41. }
  42. /**
  43. * Get the token array structure.
  44. *
  45. * @param string $token
  46. *
  47. * @return \Illuminate\Http\JsonResponse
  48. */
  49. protected function respondWithToken($token)
  50. {
  51. return response()->json([
  52. 'access_token' => $token,
  53. 'token_type' => 'bearer',
  54. 'expires_in' => auth()->factory()->getTTL() * 60
  55. ]);
  56. }
  1. /**
  2. * 登录
  3. */
  4. public function login(LoginRequest $request)
  5. {
  6. $credentials = request(['email', 'password']);
  7. if (!$token = auth('api')->attempt($credentials)) {
  8. return $this->response->errorUnauthorized();
  9. }
  10. // 检查用户状态
  11. $user = auth('api')->user();
  12. if ($user->is_locked == 1) {
  13. return $this->response->errorForbidden('被锁定');
  14. }
  15. return $this->respondWithToken($token);
  16. }

LoginRequest

  1. php artisan make:request Auth/LoginRequest
  1. /**
  2. * Get the validation rules that apply to the request.
  3. *
  4. * @return array
  5. */
  6. public function rules()
  7. {
  8. return [
  9. 'email' => 'required|email',
  10. 'password' => 'required|min:6|max:16',
  11. ];
  12. }

退出登录

路由

  1. $api->group(['middleware' => 'api.auth'], function ($api) {
  2. $api->post('logout', [LoginController::class, 'logout']);
  3. });
  1. /**
  2. * 退出登录
  3. */
  4. public function logout()
  5. {
  6. auth('api')->logout();
  7. return $this->response->noContent();
  8. }

刷新TOKEN

  1. // 刷新token
  2. $api->post('refresh', [LoginController::class, 'refresh']);
  1. /**
  2. * 刷新token
  3. */
  4. public function refresh()
  5. {
  6. return $this->respondWithToken(auth('api')->refresh());
  7. }

辅助函数

自定义全局辅助函数

app 目录下新建 helpers.php 文件, 并修改 composer.json, 加入到自动加载中:

  1. "autoload": {
  2. "psr-4": {
  3. "App\\": "app/",
  4. "Database\\Factories\\": "database/factories/",
  5. "Database\\Seeders\\": "database/seeders/"
  6. },
  7. "files": [
  8. "app/helpers.php"
  9. ]
  10. },

刷新自动加载:

  1. $ composer dump-autoload

后台用户列表

创建后台控制器

  1. php artisan make:controller Admin/UserController --api

路由

  1. $api->group(['prefix' => 'admin'], function ($api){
  2. // 当前登录用户详情
  3. $api->get('user', [\App\Http\Controllers\Admin\UserController::class, 'userInfo'])->name('user.info');
  4. // 禁用用户/启用用户
  5. $api->patch('users/{user}/lock', [\App\Http\Controllers\Admin\UserController::class, 'lock'])->name('users.lock');
  6. // 用户管理资源路由
  7. $api->resource('users', \App\Http\Controllers\Admin\UserController::class, [
  8. 'only' => ['index', 'show', 'store', 'update']
  9. ]);
  10. });
  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Http\Controllers\BaseController;
  4. use App\Models\User;
  5. use App\Transformers\UserTransformer;
  6. use Illuminate\Http\Request;
  7. class UserController extends BaseController
  8. {
  9. /**
  10. * 用户个人信息详情
  11. */
  12. public function userInfo()
  13. {
  14. return $this->response->item(auth('api')->user(), new UserTransformer());
  15. }
  16. /**
  17. * 用户列表
  18. */
  19. public function index(Request $request)
  20. {
  21. $name = $request->input('name');
  22. $email = $request->input('email');
  23. $phone = $request->input('phone');
  24. $users = User::when($name, function ($query) use ($name) {
  25. $query->where('name', 'like', "%$name%");
  26. })
  27. ->when($email, function ($query) use ($email) {
  28. $query->where('email', $email);
  29. })
  30. ->when($phone, function ($query) use ($phone) {
  31. $query->where('phone', $phone);
  32. })
  33. ->orderBy('updated_at', 'desc')
  34. ->paginate($request->query('pageSize', 10), ['*'], 'current');
  35. return $this->response->paginator($users, new UserTransformer());
  36. }
  37. /**
  38. * 添加用户
  39. */
  40. public function store(Request $request)
  41. {
  42. $request->validate([
  43. 'name' => 'required|max:16',
  44. 'email' => 'required|email|unique:users',
  45. 'password' => 'required|min:6',
  46. ]);
  47. User::create($request->all());
  48. return $this->response->created();
  49. }
  50. /**
  51. * 更新用户
  52. */
  53. public function update(Request $request, User $user)
  54. {
  55. $request->validate([
  56. 'name' => 'required|max:16',
  57. 'email' => 'required|email',
  58. ]);
  59. if ($user->id == 1 || $user->id == 2) return $this->response->errorBadRequest('禁止操作系统数据');
  60. $user->update($request->all());
  61. return $this->response->noContent();
  62. }
  63. /**
  64. * 用户详情
  65. */
  66. public function show(User $user)
  67. {
  68. return $this->response->item($user, new UserTransformer());
  69. }
  70. /**
  71. * 禁用和启用用户
  72. */
  73. public function lock(User $user)
  74. {
  75. if ($user->id == 1 || $user->id == 2) return $this->response->errorBadRequest('禁止操作系统数据');
  76. $user->is_locked = $user->is_locked == 0 ? 1 : 0;
  77. $user->save();
  78. return $this->response->noContent();
  79. }
  80. }

Transformers

  1. <?php
  2. namespace App\Transformers;
  3. use App\Models\User;
  4. use League\Fractal\TransformerAbstract;
  5. class UserTransformer extends TransformerAbstract
  6. {
  7. public function transform(User $user)
  8. {
  9. return [
  10. 'id' => $user->id,
  11. 'name' => $user->name,
  12. 'email' => $user->email,
  13. 'phone' => $user->phohe,
  14. 'avatar' => $user->avatar,
  15. 'openid' => $user->openid,
  16. ];
  17. }
  18. }

分类管理

  1. /**
  2. * 分类管理
  3. */
  4. // 分类禁用和启用
  5. $api->patch('category/{category}/status', [\App\Http\Controllers\Admin\CategoryController::class, 'status'])->name('category.status');
  6. // 分类管理资源路由
  7. $api->resource('category', \App\Http\Controllers\Admin\CategoryController::class, [
  8. 'except' => ['destroy']
  9. ]);

控制器

  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Http\Controllers\BaseController;
  4. use App\Models\Category;
  5. use Illuminate\Http\Request;
  6. class CategoryController extends BaseController
  7. {
  8. /**
  9. * 分类列表
  10. */
  11. public function index(Request $request)
  12. {
  13. $type = $request->input('type');
  14. if ($type == 'all') {
  15. return cache_category_all();
  16. } else {
  17. return cache_category();
  18. }
  19. }
  20. /**
  21. * 添加分类 最大2级分类
  22. */
  23. public function store(Request $request)
  24. {
  25. $insertData = $this->checkInput($request);
  26. if (!is_array($insertData)) return $insertData;
  27. Category::create($insertData);
  28. return $this->response->created();
  29. }
  30. /**
  31. * 分类详情
  32. */
  33. public function show(Category $category)
  34. {
  35. return $category;
  36. }
  37. /**
  38. * 更新分类
  39. */
  40. public function update(Request $request, Category $category)
  41. {
  42. if ($category->id < 42) return $this->response->errorBadRequest('系统数据禁止编辑, 请自行创建数据');
  43. $updateData = $this->checkInput($request);
  44. if (!is_array($updateData)) return $updateData;
  45. $category->update($updateData);
  46. return $this->response->noContent();
  47. }
  48. /**
  49. * 验证提交的参数
  50. */
  51. protected function checkInput($request)
  52. {
  53. // 验证参数
  54. $request->validate([
  55. 'name' => 'required|max:16'
  56. ], [
  57. 'name.required' => '分类名称 不能为空'
  58. ]);
  59. // 获取分组
  60. $group = $request->input('group', 'goods');
  61. // 获取pid
  62. $pid = $request->input('pid', 0);
  63. // 计算level
  64. $level = $pid == 0 ? 1 : (Category::find($pid)->level + 1);
  65. // 不能超过3级分类
  66. if ($level > 2) {
  67. return $this->response->errorBadRequest('不能超过二级分类');
  68. }
  69. return [
  70. 'name' => $request->input('name'),
  71. 'pid' => $pid,
  72. 'level' => $level,
  73. 'group' => $group
  74. ];
  75. }
  76. /**
  77. * 状态禁用和启用
  78. */
  79. public function status(Category $category)
  80. {
  81. if ($category->id < 42) return $this->response->errorBadRequest('系统数据禁止编辑, 请自行创建数据');
  82. $category->status = $category->status == 1 ? 0 : 1;
  83. $category->save();
  84. return $this->response->noContent();
  85. }
  86. }

Helpers.php

  1. /**
  2. * 缓存没被禁用的分类
  3. */
  4. if (!function_exists('cache_category')) {
  5. function cache_category ()
  6. {
  7. return cache()->rememberForever('cache_category', function () {
  8. return categoryTree('goods', 1);
  9. });
  10. }
  11. }
  12. /**
  13. * 缓存所有的分类
  14. */
  15. if (!function_exists('cache_category_all')) {
  16. function cache_category_all ()
  17. {
  18. return cache()->rememberForever('cache_category_all', function () {
  19. return categoryTree('goods');
  20. });
  21. }
  22. }
  1. /**
  2. * 清空分类缓存
  3. */
  4. if (!function_exists('forget_cache_category')) {
  5. function forget_cache_category ()
  6. {
  7. cache()->forget('cache_category');
  8. cache()->forget('cache_category_all');
  9. cache()->forget('cache_category_menu');
  10. cache()->forget('cache_category_menu_all');
  11. }
  12. }
  1. class CategoryTransformer extends TransformerAbstract
  2. {
  3. public function transform(Category $category)
  4. {
  5. return [
  6. 'id' => $category->id,
  7. 'pid' => $category->pid,
  8. 'name' => $category->name,
  9. ];
  10. }
  11. }
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议