Rest Api CRUD in Laravel with Api Resources

执行:

php artisan make:model Task –mf

批注 2020-04-14 030417

执行:

php artisan make:controller TaskController -r

批注 2020-04-14 030434

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->string('title');
            $table->text('description');
            $table->dateTime('due');
            $table->timestamps();
        });
        Schema::table('tasks', function (Blueprint $table) {
            $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

CreateTasksTable.php

执行:

php artisan migrate

TaskController修改index方法:

public function index()
{
    //
    $tasks = Task::all();
    return response($tasks, 200);
}

api.php添加:

Route::resource('task', ‘TaskController');

然后我们用PostMan发送请求测试:

批注 2020-04-14 133543

因为目前我们数据库中没有添加任何数据,所以返回为空,尝试用factory添加一些数据:

修改一下task的migration文件:

public function up()
{
    Schema::create('tasks', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('user_id');
        $table->string('title');
        $table->text('description')->nullable();
        $table->dateTime('due')->nullable();
        $table->timestamps();
    });
    Schema::table('tasks', function (Blueprint $table) {
        $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
    });
}

然后执行:

php artisan migrate:fresh

强制删除所有数据表并重新生成。

打开TaskFactory.php 修改如下:

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Task;
use Faker\Generator as Faker;

$factory->define(Task::class, function (Faker $faker) {
    return [
        //
        'title' => $faker->company,
        'description' => $faker->paragraph(20),
        'user_id' => 1,
    ];
});

执行:

php artisan passport:install

批注 2020-04-14 134715

然后

批注 2020-04-14 134427

添加用户数据后,执行

php artisan tinker

在tinker中执行:

factory(App\Task::class,5)->create();

添加5条任务数据。

批注 2020-04-14 134858

然后测试如下:

批注 2020-04-14 134943

改进:

一个用户只能查看属于自己的任务。

所以先定义User模型与Task模型之间的关系:

User.php中添加:

public function tasks()
{
    return $this->hasMany(Task::class);
}

Task.php中添加:

public function user()
{
    return $this->belongsTo(User::class);
}

完善Task.php:

添加

protected $fillable = ['user_id', 'title', 'description', 'due'];


terminal中键入exit退出tinker控制台。

批注 2020-04-14 135741

执行:

参考资料:API 资源

从本质上来说,资源的作用很简单。它们只需要将一个给定的模型转换成一个数组。所以每一个资源都包含一个 toArray 方法用来将你的模型属性转换成一个可以返回给用户的 API 友好数组

php artisan make:resource TaskResource

批注 2020-04-14 135722

修改api.php:

将之前的

Route::resource('task', ‘TaskController');

修改为

Route::apiResource('tasks', 'TaskController')->middleware('auth:api');

修改TaskController的index方法如下:

public function index()
{
    //
    $tasks = TaskResource::collection(auth()->user()->tasks()->latest()->paginate(4));
    return response($tasks, 200);
}

现在我们需要先登录,获取用户token

批注 2020-04-14 141052

然后用这个token放置于authorization中,

批注 2020-04-14 141254

然后发送请求获取属于user的对应的全部task资源数据。

如果没有这个token会显示:

批注 2020-04-14 141349

接下来完善store方法,注意我们是api方式所以不需要几个show form方法:

批注 2020-04-14 141745批注 2020-04-14 141829

删除掉就行。

创建资源前需要验证,然后验证用户通过模型关联创建task即可,最后返回一个taskresource实例。

public function store(Request $request)
{
    $validated = Validator::make($request->all(), [
        'title' => 'required|max:255',
    ]);
    if ($validated->fails()) {
        return response($validated->errors()->all());
    }
    $task = auth()->user()->tasks()->create($request->all());

    return new TaskResource($task->load('user'));
}

最后返回的时候,我们用了load方法,这里不能用with,具体区别在于with是一次,load是分开,因为我们先获取生成的task,所以是分开的,只能用load。

PostMan测试如下:

Token我们已经登录后然后配置了:

批注 2020-04-14 144140

发送请求:

批注 2020-04-14 144530

show方法修改如下:

批注 2020-04-14 144826

postman测试:

批注 2020-04-14 144911

update方法:

public function update(Request $request, Task $task)
{
    //
    $validated = Validator::make($request->all(), [
        'title' => 'required|max:255',
    ]);
    if ($validated->fails()) {
        return response($validated->errors()->all());
    }

    if (!auth()->user()->tasks->contains($task)) {
        return response('No permission!', 422);
    }

    $task->update($request->all());

    return new TaskResource($task->load('user'));

}

Postman测试:

批注 2020-04-14 145920

或发送:

批注 2020-04-14 151154

数据库查看结果:

批注 2020-04-14 145951

在destroy方法之前我们还是给模型添加一个软删除的支持,

批注 2020-04-14 150155

批注 2020-04-14 150214

以及对应的migrate添加:

批注 2020-04-14 150528

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddSoftdeteleToUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            //
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            //
            $table->dropSoftDeletes();
        });
    }
}

批注 2020-04-14 150609

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddSoftdeteleToTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('tasks', function (Blueprint $table) {
            //
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('tasks', function (Blueprint $table) {
            //
            $table->dropSoftDeletes();
        });
    }
}

执行:

php artisan migrate

批注 2020-04-14 150922

destory方法:

public function destroy(Task $task)
{
    //
    if (!auth()->user()->tasks->contains($task)) {
        return response('No permission!', 422);
    }
    $task->delete();

    return response(['message' => 'Success deleted!']);
}

最后Postman测试结果:

批注 2020-04-14 150848

数据库结果:

批注 2020-04-14 151034

due修正后:

store方法:

public function store(Request $request)
{
    $validated = Validator::make($request->all(), [
        'title' => 'required|max:255',
    ]);
    if ($validated->fails()) {
        return response($validated->errors()->all());
    }
    $input = $request->all();
    if ($request->has('due')) {
        $input['due'] = Carbon::parse($request->get('due'))->toDateTimeString();
    }
    $task = auth()->user()->tasks()->create($input);

    return new TaskResource($task->load('user'));
}

update方法:

public function update(Request $request, Task $task)
{
    //
    $validated = Validator::make($request->all(), [
        'title' => 'required|max:255',
    ]);
    if ($validated->fails()) {
        return response($validated->errors()->all());
    }

    if (!auth()->user()->tasks->contains($task)) {
        return response('No permission!', 422);
    }
    $input = $request->all();

    if ($request->has('due')) {
        $input['due'] = Carbon::parse($request->get('due'))->toDateTimeString();
    }
    $task->update($input);

    return new TaskResource($task->load('user'));

}

PostMan测试结果:

批注 2020-04-14 152044

以及:

批注 2020-04-14 152504

数据库查看:

批注 2020-04-14 152557

posted @ 2020-04-14 03:16  dzkjz  阅读(177)  评论(0编辑  收藏  举报