Skip to content

模拟用户数据

/Users/luxiaoqing/project/api-test/cp/database/seeders/DatabaseSeeder.php

User::factory(10)->create();
$user = User::find(1);
$user->email = 'aaaa@qq.com';
$user->name = '超级管理员';
$user->save();
php
userFactory 
password =>Hask::make('admin88')

单个 php artisan db:seed --class=TopicsTableSeeder

php artisan migrate:refresh --seed

/Users/luxiaoqing/project/api-test/cp/database/factories/UserFactory.php

工程制造模拟数据

api工具加入提起token操作

image-20240123115246964

后置操作->变量名称(token) ->$.data.token

根目录-> auth->Bearer Token->

任务2 api 登录接口

任务一:用户登录控制器和API #1、创建登录控制器

php artisan make:controller LoginController

#2、设置登录API #3、设置Controller基类成功返回信息的统一格式:

 protected function success($message='',$data=[],$code=0){
        return response()->json([
            'code'=>$code,
            'status'=>'success',
            'message'=>$message,
            'data'=>$data
        ]);
    }

#4、生成token并返回token

#5、开启sanctume鉴权服务提供者:

/Users/luxiaoqing/project/api-test/cp/app/Http/Kernel.php

kernel文件中,api组:

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 开启

#6、api工具验证接口

Route::post('login',\App\Http\Controllers\LoginController::class);
php
class LoginController extends Controller
{
    //
    public function __invoke(Request $request)
    {
        $request->validate([
            'email'=>['required','email'],
            'password' =>['required','min:3']
        ]);
        $user = User::whereEmail($request->email)->first();
        if($user && Hash::check($request->password,$user->password)) {
            $token = $user->createToken('token')->plainTextToken;
            return $this->success('成功',[
                'token'=>$token,
                'user'=>$user
            ]);
        }
        return $this->success(ValidationException::withMessages(['password'=>'密码错误'])->getMessage(),[],0);
    }
}

任务三:Request验证和响应Response #1、创建LoginRequest验证并设置。

php artisan make:request LoginRequest
php
class LoginRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }
    public function rules(): array
    {
        return [
            'email'=>['required','email'],
            'password' =>['required','min:3']
        ];
    }
}

ps : laravel 做表单验证失败后返回到首页的问题

http 请求头加上 Accept application/json

#2、创建UserResource并演示。

php artisan make:resource UserResource
php
class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return ['city' => 'beijing'] + parent::toArray($request); //array_merge(arr1,arr2)
    }
}

['city' => 'beijing'] + parent::toArray($request); 作用是前面覆盖后面 array_merge(arr1,arr2) 后面覆盖前面

return $this->success('成功',[
'token'=>$token,
'user'=> new UserResource($user)
]);
user": {
"city": "beijing", // resource 添加的属性
"id": 1,
"name": "超级管理员",
...,
}

任务4:创建用户注册控制和API #1、创建用户注册控制RegisterController

php
// RegisterRequest
public function rules(): array
{
  return [
  'email'=>['required','email'],
  'password' =>['required','min:3','confirmed']
  ];
}

confirmed 需要在接口传 password_confirmation的字段(能修改吗?)

php
class RegisterController extends Controller
{
    public function __invoke(RegisterRequest $request,User $user)
    {
        $data = ['password' => Hash::make($request->password)] + $request->input();
        $user->fill($data)->save();
        return $this->success('成功',['user'=>$user->refresh()]);
    }
}

#2、实现注册接口

任务5:邮件验证码服务 #1、创建服务CodeService并声明

class AppServiceProvider extends ServiceProvider
{
    public function register(): void{
        $this->app->instance(CodeService::class,new CodeService()); //产生一个实例
        // $this->app->bind() //调用一次产生一个实例
    }
    public function boot(): void{}
}
namespace App\Services;
class CodeService {
    public function send() {
        return '000';
    }
}
//调用实例方法
Route::get('send/register/code', function () { 
    return app(CodeService::class)->send();
});
Route::get('/', function () {
    $user = User::factory()->make();
    return (new ValidateEmailCodeNotification())->toMail($user);
});

Ps : make 和 create的区别,make创建在内存不在表,create直接创建在表

#2、创建邮件验证码通知类,并设置邮件通知模板:(new ValidateEmailCodeNotifiaction(333333))->toMail($user); 设置邮件模板。

php artisan make:notification ValidateEmailCodeNotification
php
class CodeService {
        public function send($email) {
            $user = User::factory()->make([
                'email'=>$email
            ]);
            if(Cache::get($email)) abort('403','验证码已发送');

            Notification::send($user,  new ValidateEmailCodeNotification($code = $this->getCode()));
            Cache::put($email,$code,config('time.expire_time'),60);
            return $code;
        }

        public function getCode(): int
        {
            return mt_rand(100000,999999);
        }

        public function check() {

        }
    }

#3、发送邮件验证码,并缓存。

php
class CodeService {
    public function send($email) {
        // 发送邮件
        $user= User::factory()->make([
            'email'=>$email
        ]);
        if(Cache::get($email)) abort(403, '验证码已发送'); // 打断
        Notification::send($user, new ValidateEmailCodeNotification($code = $this->getCode()));
        Cache::put($email,$code,config('time.expire_time'), 60); // config目录下的time文件下的expire_time
    }
    public function getCode() {
        return mt_rand(100000,999999);
    }
    public function check($email,$code) {}
}

Ps: 直接在代码调用 env('CACHE_EXPIRE_TIME'),能直接获取值,但不建议

因为在上线之前,需要打包构建,产生缓存,加快访问速度,env会被固定化,到时候访问不到

#4、config的使用

Cache::put($email,$code,config('time.expire_time'), 60);

任务6:创建验证码服务器 #1、创建验证码服务器CodeController

public function registerCode(RegisterCodeRequest $request) {
  $code = app(CodeService::class)->send($request->email);
  return $this->success('发送成功',[
  'code'=>$code
  ]);
}

#2、env邮件地址设置 : MAIL_HOST=localhost #3、mailhog模拟的邮件提供商,端口号为:8025,homestead自带

RegisterCodeRequest
'email'=>['required','email',Rule::unique('users','email')]

没成功,不在homestead环境

任务8:注册用户验证码认证 #1 添加code验证字段 #2 创建CodeRule验证规则,验证栏以new CodeRule形式调用。

php artisan make:rule CodeCheckRule
php
// request 直接调用
class CodeCheckRule implements Rule{
    public function __construct(){}
    public function passes($attribute, $value){ return Cache::get(request('email')) == $value; }
    public function message() { return '验证码输入错误';}
}
// 和视频不一样,mac
public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        //
    }
php
// \cp\app\Http\Requests\RegisterRequest.php
public function rules(): array
    {
        return [
            'email'=>['required','email'],
            'password' =>['required','min:3'],
            'code'=>['required',new CodeCheckRule()]
        ];
    }

#3 api工具演示

ps: 设置 编辑器 实时模版 设置快捷代码块

任务9:找回密码功能 #1 创建UserController --api,配置接口

php artisan make:controller UserController --api

#2 创建artisan make:request UserFindPasswordRequest 验证 #3 创建找回密码邮件验证码功能 artisan make:request FindPasswordCodeRequest

php
UserFindPasswordRequest 
public function rules(): array
    {
        return [
            'email'=>['required','email',Rule::exists('users','email')],
            'password'=>['required','confirmed','min:3'],
            'code'=>['required',new CodeCheckRule()]
        ];
    }

Ps: rule 目前有unique 和 exists

php
public function findPassword(FindPasswordRequest $request) {
        $user = User::whereEmail($request->email)->firstOrFail();
        $user->password = Hash::make($request->password);
        $user->save();
        return $this->success('重置密码成功',[
            'user'=>$user
        ]);
    }

任务10:用户的列表显示和单个用户信息查看

php aritisan make:controller UserController --api

// 查看全部路由 
php artisan route:list
// 筛选
php artisan route:list | grey user
Route::apiResource('users',\App\Http\Controllers\UserController::class);
php artisan route:list | grep users

#1 用户列表的显示

php
public function __controller() {
	$this->middleware(['auth:sanctum'])->only(['update','destory'])
}
public function index() {
	return UserResource::collection(User::latest()->paginate())
}

//UserResource 的使用
 return $this->success('登陆成功',[
'token'=>$user->createToken('token')->plainTextToken,
'user'=>new UserResource($user),//单个的使用
]);
// 列表的使用
UserResource::collection

#2 单个用户信息查看

任务11:Policy管理用户操作的权限

#1 创建判定超管的全局函数

php
if(!function_exists('isSuperAdmin')) {
    function isSuperAdmin() {
        return Auth::user() && Auth::id() == 1;
    }
}

#2 生成UserPolicy

 php artisan make:policy UserPolicy --model=User
php
class UserPolicy
{
	 public function before(): bool
    {
        // true 下面不执行,false 后面不用看,完全没有权限,undefined是执行下面的方法
       	if(isSuperAdmin()) return true;
    }
    public function viewAny(User $user): bool
    {
        //
    }
    public function view(User $user, User $model): bool
    {
        //
    }
    public function create(User $user): bool
    {
        //
    }
    public function update(User $user, User $model): bool
    {
        //user(登录用户) model(模型用户,修改的数据)
        return $user->id === $model->id;
    }
    public function delete(User $user, User $model): bool
    {
        
    }
    public function restore(User $user, User $model): bool
    {
        //
    }
    public function forceDelete(User $user, User $model): bool
    {
        //
    }
}
php
class UserController extends Controller {
    public function __construct() {
        $this->middleware(['auth:sanctum'])->only(['update','destroy','getCurrentUserInfo','logout']);
    }
    //显示所有用户
    public function index() {
        return UserResource::collection(User::latest()->paginate());
    }

    //显示单用户信息
    public function show(User $user) {
        return $this->success(data:new UserResource($user));
    }

    //更新单用户信息
    public function update(UpdateUserRequest $request,User $user) {
        $this->authorize('update',$user);
        $user->fill($request->input())->save();
        return $this->success('用户信息更新成功',[
           'user'=>$user
        ]);

    }

    //删除单用户信息
    public function destroy(User $user) {
        $this->authorize('delete',$user);
        $user->delete();
        return $this->success('删除成功');
    }

    //找回用户密码
    public function findPassword(FindPasswordRequest $request) {
        $user = User::whereEmail($request->email)->firstOrFail();
        $user->password = Hash::make($request->password);
        $user->save();
        return $this->success('重置密码成功',[
            'user'=>$user
        ]);
    }
    public function getCurrentUserInfo(){
        return $this->success(data:new UserResource(Auth::user()));
    }

    public function logout(){
        if($user = Auth::user()){
            $user->tokens()->delete();
        }
    }

    public function getOneTopics(Request $request){

        $topics = Topic::with('user')
            ->when(request('u_id'),function($query){
                return $query->where('user_id',request('u_id'));
            })
            ->latest()
            ->paginate(5);
        return TopicResource::collection($topics);
    }
    public function getOneComments(Request $request){
        $comments = Comment::with('user')
            ->when(request('u_id'),function($query){
                return $query->where('user_id',request('u_id'));
            })
            ->latest()
            ->paginate(5);
        return CommentResource::collection($comments);
    }
}

#3 在api 调试

Lucking