CÁCH TẠO API VỚI RESOURCE TRONG LARAVEL

 API resources là gì?

laravel API resources hoạt động như một lớp chuyển đổi nằm giữa các model Eloquent của bạn và các phản hồi JSON được trả về cho người dùng ứng dụng của bạn.
Laravel’s resource classes cho phép bạn chuyển đổi rõ ràng và dễ dàng các mô hình và bộ sưu tập mô hình của bạn thành JSON. Để hiểu rõ hơn về cách chúng hoạt động, bạn có thể xem laravel documentation. Trước khi chúng tôi tạo tài nguyên chúng tôi sẽ sử dụng, chúng tôi phải xác định các Model mà chúng sẽ triển khai.
Đối với hướng dẫn này, chúng tôi sẽ có các Book, Rating and user models. Để tạo model Book, hãy chạy lệnh này

php artisan make: model Book -m

flag -m tạo một file migration tương ứng cho model. Lặp lại quy trình cho rating model. Chúng ta không cần phải tạo một user model  vì nó ra khỏi kệ trong laravel.

Tiếp theo, chúng ta sẽ edit ‘up’ functions trong migrations mà chúng ta vừa tạo. Trên thư mục chỉnh sửa //database/migrations/TIMESTAMP_create_books_table.php sẽ trông như thế này:

class CreateBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->Integer('user_id')->unsigned();
            $table->string('title');
            $table->string('author');
            $table->text('description');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });

    }

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

Chúng ta xác định trường của bảng sách cũng như ID của người dùng đã thêm vào Books table. ID người dùng là khóa ngoại tham chiếu trường ‘id’ trong bảng ‘users’.

Tiếp theo,  Ratin migration,// database/migrations/TIMESTAMP_create_ratings_table.php

và điều chỉnh nó để trông như thế này,

<?php

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

class CreateRatingsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ratings', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('book_id');
            $table->unsignedInteger('rating');
            $table->timestamps();
        });
    }

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


Trong file migraiton này, chúng tôi đã xác định các trường mà rating table  sẽ lấy, đó là ID, là khóa chính của ratings table, user_id của user đã đăng một rating, the book_id mà rating được đăng, bản thân rating(trong số 5) và timestamps ,rating đã được tạo hoặc cập nhật.

Sau khi chạy tất cả các cách trên, hãy chạy migration của chúng ta, nhưng trước khi thực hiện, hãy điều hướng đến file app \ developers \ AppServiceProvider.php và chỉnh sửa chức năng khởi động bằng cách thêm defaultStringthLpm để nó trông như thế này

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Schema::defaultStringLength(191);
    }
}

 

TẠO Book Resource

Tạo các lớp resource trong laravel được đơn giản hóa bằng cách sử dụng các lệnh thủ công.

Để tạo resource class run

php artisan make:Resource BookResource

được tạo trong thư mục app / http / Resources / BookResource.php.

Điều hướng ở đây và chỉnh sửa phương thức toArray () để nó trông như thế này:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class BookResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        //transforms the resource into an array made up of the attributes to be converted to JSON
        return [
            'id'=> $this->id,
            'title'=> $this->title,
            'author' => $this->author,
            'description'=>$this->description,
            'created_at' => (string) $this->created_at,
            'updated_at' => (string) $this->updated_at,
            'user' => $this->user,
            'ratings' => $this->ratings,
            'average_rating' => $this->ratings->avg('rating')
        ];

    }
}

Mỗi class resourse định nghĩa một phương thức toArray trả về mảng các thuộc tính sẽ được chuyển đổi thành JSON khi gửi phản hồi. Tất cả các thuộc tính của model book chúng ta cần chuyển đổi thành JSON đều được xác định, chúng ta cũng có thể xóa các thuộc tính mà chúng ta không cần phải được tuần tự hóa thành JSON. Lưu ý rằng chúng ta có thể truy cập các thuộc tính model trực tiếp từ biến $this variable. . Điều này (ý định chơi chữ) là do resource class sẽ tự động ủy quyền  thuộc tính và phương thức truy cập xuống model bên dưới để truy cập thuận tiện. Khi resource  được xác định, nó có thể được trả về từ môt route hoặc controller. Bây giờ chúng ta có thể sử dụng lớp BookResource trong BookContoder mà chúng ta sẽ tạo.

Creating the Book Controller

BookController của chúng ta sẽ sử dụng tính năng tạo bộ API controller,bằng việc chay lệnh

php artisan make:controller BookController --api

Mở controller nên nó nằm ở:
app\Http\Controller\BookController.php

<?php

namespace App\Http\Controllers;

use App\Book;
use Illuminate\Http\Request;
use App\Http\Resources\BookResource;

class BookController extends Controller
{
   public function __construct()
   {
    $this->middleware('auth:api')->except(['index', 'show']);
   }

    /**
     * Display all books that have been added
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
      return BookResource::collection(Book::with('ratings')->paginate(25));
    }
  /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate($request, [
            'title' => 'required',
            'description' => 'required',
            'author' => 'required',
        ]);
        $book = new Book;
        $book->user_id = $request->user()->id;
        $book->title = $request->title;
        $book->description = $request->description;
        $book->author = $request->author;
        $book->save();

        return new BookResource($book);
}
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show(book $book)
    {
        return new BookResource($book);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Book $book)

    {

      // check if currently authenticated user is the owner of the book

      if ($request->user()->id !== $book->user_id) {

        return response()->json(['error' => 'You can only edit your own books.'], 403);

      }



      $book->update($request->only(['title','author', 'description']));



      return new BookResource($book);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Request $request,Book $book)
    {
      if($request->user()->id != $book->user_id){
        return response()->json(['error' => 'You can only delete your own books.'], 403);
      }
        $book ->delete();
        return response()->json(null,204);
    }
}

Defining API routes

Cuối cùng chúng ta xác đinh API route. Mở 
routes\api.php 

và thêm ở phía dưới

Route::apiResource('books', 'BookController');