[번역]라라벨 Restful API Resources 블로그 > PHP프레임워크

PHP프레임워크

[번역]라라벨 Restful API Resources 블로그 정보

라라벨 [번역]라라벨 Restful API Resources 블로그

본문

https://blog.pusher.com/build-rest-api-laravel-api-resources/

 

Laravel API 리소스로 REST API 개발

 

이 자습서에서는 Laravel API 리소스 기능을 사용하여 REST API를 작성하는 방법을 보여줍니다. API 리소스는 Laravel 5.5에 도입되었습니다. API 리소스가 도입되기 전에 REST API를 작성할 때 JSON 응답을 출력하기 위해 변형 레이어로 프랙탈과 같은 패키지를 사용했습니다. 이 자습서에서는 API 리소스를 사용하여 Laravel에서 강력한 API를 작성하는 방법을 보여 드리겠습니다.

 

선결 요건

 

이 자습서에서는 이미 다음 내용을 전제로합니다.

  • Laravel에 대한 기본 지식.
  • REST API에 대한 기본 지식.
  • Laravel 설치 프로그램을 컴퓨터에 설치하십시오.

API 리소스 란 무엇입니까?

 

API 리소스는 모델을 JSON 응답으로 쉽게 변형 할 수있는 방법을 제시합니다. Eloquent 모델과 API에서 실제로 반환되는 JSON 응답 사이에있는 변환 레이어 역할을합니다. API 자원은 자원 클래스와 자원 콜렉션이라는 두 개의 엔티티로 구성됩니다. 리소스 클래스는 JSON 구조로 변환해야하는 단일 모델을 나타내며 리소스 컬렉션은 모델 컬렉션을 JSON 구조로 변형하는 데 사용됩니다.

리소스 클래스와 리소스 컬렉션은 모두 artisan 명령을 사용하여 만들 수 있습니다.

 

// create a resource class
    $ php artisan make:resource UserResource

    // create a resource collection using either of the two commands
    $ php artisan make:resource Users --collection
    $ php artisan make:resource UserCollection

 

우리가 무엇을 만들 것인가?

 

이 데모를 위해 서평 검토 API( book revies API)를 작성합니다. 사용자는 새 책을 추가하고 책을 업데이트하며 책을 삭제할 수 있습니다. 사용자는 또한 모든 책의 목록을보고 책을 평가할 수 있습니다. 그런 다음 평균 등급은 특정 책의 등급을 기준으로 계산됩니다. 마지막으로 JSON Web Tokens (JWT)로 인증을 추가하여 API 보안을 강화합니다.

 

새 Laravel 앱 만들기

 

새로운 Laravel 앱을 만드는 것으로 시작하겠습니다. 저는 Laravel 설치 프로그램을 사용할 것입니다.

 

$ laravel new book-reviws-api

$ composer create-project laravel/laravel --prefer-dist book-reviews-api

 

모델 및 마이그레이션 만들기

 

서평 API에는 User, Book 및 Rating의 세 가지 모델이 있습니다. 운좋게도 사용자 모델은 기본적으로 Laravel과 함께 제공됩니다. 나머지 2 개와 해당하는 마이그레이션을 만듭니다. Book 모델을 만들어 보겠습니다.

 

$ php artisan make:model Book -m

 

-m 플래그는 모델에 해당하는 마이그레이션 파일을 작성합니다.

 

다음으로, Book 모델을 위해 생성 된 이전 파일을 열고 아래와 같이 up() 메소드를 업데이트하자.

 

    // database/migrations/TIMESTAMP_create_books_table.php

    public function up()
    {
      Schema::create('books', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedInteger('user_id');
        $table->string('title');
        $table->text('description');
        $table->timestamps();
      });
    }

 

자동 증가 ID, 책을 추가 한 사용자의 ID, 책의 제목 및 책의 설명 인 books 테이블의 필드를 정의합니다. 그런 다음 일부 타임 스탬프 (created_at 및 updated_at).

등급 모델에 대해서도 동일한 작업을 수행합니다.

 

$ php artisan make:model Rating -m

 

등급 모델에 대해 생성 된 마이그레이션 파일을 열고 아래와 같이 up() 메소드를 업데이트하십시오.

 

    // database/migrations/TIMESTAMP_create_ratings_table.php

    public function up()
    {
      Schema::create('ratings', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedInteger('user_id');
        $table->unsignedInteger('book_id');
        $table->unsignedInteger('rating');
        $table->timestamps();
      });
    }

 

자동 증분 ID, 책을 평가 한 사용자의 ID, 등급이 매겨진 책의 ID 및 등급 자체 (0-5 범위)에 대한 등급 테이블의 필드를 정의합니다. 그런 다음 일부 타임 스탬프 (created_at 및 updated_at).

아래 명령을 실행하여 마이그레이션을 실행하십시오.

 

$ php artisan migrate

 

위의 명령을 실행하기 전에 데이터베이스 정보를 .env 파일에 입력해야합니다.

 

모델 간의 관계 정의

 

사용자는 원하는만큼 책을 추가 할 수 있지만 책은 한 명의 사용자에게만 속할 수 있습니다. 따라서 User 모델과 Book 모델 간의 관계는 일대 다 관계입니다. 그것을 정의합시다. User 모델 안에 아래 코드를 추가하십시오.

 

    // app/User.php

    public function books()
    {
      return $this->hasMany(Book::class);
    }

 

다음으로, Book 모델에 역관계를 정의 해 보겠습니다.

 

    // app/Book.php

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

 

마찬가지로 다양한 사용자가 책을 평가할 수 있으므로 책은 여러 등급을 가질 수 있습니다. 평점은 한 권의 책에만 속할 수 있습니다. 이것은 일대 다 관계이기도합니다. Book 모델에 아래 코드를 추가하십시오.

 

    // app/Book.php

    public function ratings()
    {
      return $this->hasMany(Rating::class);
    }

 

그런 다음 Rating 모델 내부에 역관계를 정의합니다.

 

    // app/Rating.php

    public function book()
    {
      return $this->belongsTo(Book::class);
    }

 

일부 필드에서 대량 할당 허용

 

우리는 create() 메서드를 사용하여 새 모델을 한 줄에 저장합니다. Laravel이 기본적으로 대량 할당 지정 오류를 피하려면 대량 할당할 열을 지정해야합니다. 이렇게 하려면 아래의 스니펫을 각각 모델에 추가하십시오.

 

    // app/Book.php

    protected $fillable = ['user_id', 'title', 'description'];
    // app/Rating.php

    protected $fillable = ['book_id', 'user_id', 'rating'];

 

사용자 인증 추가

 

앞서 언급했듯이 JWT를 사용하여 사용자 인증을 추가하여 API를 보안합니다. 이를 위해 jwt-auth라는 패키지를 사용합니다. 설치하고 설정해 보겠습니다.

 

    $ composer require tymon/jwt-auth "1.0.*"

 

참고 : Laravel 5.4 이하를 사용하는 경우 app.php 구성 파일의 providers 배열에 서비스 공급자를 추가하여 수동으로 등록해야합니다.

 

설치가 끝나면 아래 명령을 실행하여 패키지의 config 파일을 게시하십시오.

 

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

 

이렇게하면 config / jwt.php 파일이 생성되어 패키지의 기본 설정을 할 수 있습니다.

그런 다음 아래 명령을 실행하여 비밀 키를 생성하십시오.

 

    $ php artisan jwt:secret

 

이것은 .env 파일을 JWT_SECRET=some_random_key와 같은 것으로 업데이트 할 것입니다. 이 키는 토큰에 서명하는 데 사용됩니다.

jwt-auth 패키지를 사용하기 전에 다음과 같이 Tymon\JWTAuth\Contracts\JWTSubject 계약을 구현하도록 User 모델을 업데이트해야합니다.

 

    // app/User.php

    use Tymon\JWTAuth\Contracts\JWTSubject;

    class User extends Authenticatable implements JWTSubject
    {
      ...
    }

 

이를 위해서는 getJWTIdentifier()와 getJWTCustomClaims()의 두 가지 메소드를 구현해야한다. 그래서 아래 코드를 User 모델에 추가하십시오.

 

    // app/User.php

    public function getJWTIdentifier()
    {
      return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
      return [];
    }

 

첫 번째 방법은 JWT의 주체 클레임에 저장 될 식별자를 가져오고 두 번째 방법은 JWT에 추가 할 사용자 지정 클레임을 추가 할 수있게합니다. 이 자습서에서는 사용자 지정 클레임을 추가하지 않습니다.

다음으로, auth guard가 jwt guard를 사용하도록 설정하십시오. 다음과 같이 config / auth.php를 업데이트하십시오 :

 

    // config/auth.php

    'defaults' => [
      'guard' => 'api',
      'passwords' => 'users',
    ],

    ...

    'guards' => [
      'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
      ],
    ],

 

여기에서는 API 가드에게 jwt 드라이버를 사용하도록 지시하고 있으며 API 가드를 기본값으로 설정하고 있습니다.

이제 jwt-auth 패키지를 사용할 수 있습니다. 새 AuthController 만들기 :

 

 $ php artisan make:controller AuthController

 

그런 다음 아래에 코드를 붙여 넣으십시오.

 

    // app/Http/Controllers/AuthController.php

    // remember to add this to the top of the file
    use App\User;

    public function register(Request $request)
    {
      $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => bcrypt($request->password),
      ]);

      $token = auth()->login($user);

      return $this->respondWithToken($token);
    }

    public function login(Request $request)
    {
      $credentials = $request->only(['email', 'password']);

      if (!$token = auth()->attempt($credentials)) {
        return response()->json(['error' => 'Unauthorized'], 401);
      }

      return $this->respondWithToken($token);
    }

    protected function respondWithToken($token)
    {
      return response()->json([
        'access_token' => $token,
        'token_type' => 'bearer',
        'expires_in' => auth()->factory()->getTTL() * 60
      ]);
    }

 

새 사용자를 등록하고 사용자를 각각 기록하는 방법을 정의합니다. 두 메소드는 토큰 배열 구조를 가져 오는 respondWithToken() 메소드를 호출하여 JWT로 응답을 리턴합니다.

다음으로 등록 및 로그인 경로를 추가합시다. 아래 코드를 routes/api.php에 추가하십시오.

 

    // routes/api.php

    Route::post('register', 'AuthController@register');
    Route::post('login', 'AuthController@login');

 

API 경로 정의

 

우리 노선을 정의합시다. routes/api.php를 열고 아래 줄을 추가하십시오 :

 

    // routes/api.php

    Route::apiResource('books', 'BookController');
    Route::post('books/{book}/ratings', 'RatingController@store');

 

API를 작성 중이므로 API 전용 경로를 생성하기 위해 apiResource ()를 사용합니다. 또한 지정된 책을 평가하는 데 사용할 경로를 정의합니다. 예를 들어, /books/53/ratings은 53의 ID로 책을 평가하는 데 사용됩니다.

 

팁 : Laravel로 API를 빌드 할 때 apiResource () 메소드를 사용하여 리소스가 많은 경로를 정의하는 것이 좋습니다. API 전용 경로 (인덱스, 저장, 표시, 업데이트 및 삭제) 만 생성됩니다. API 특정 경로를 생성하는 것 외에도 resource () 메소드를 사용할 때와 달리 API를 만들 때 필요하지 않은 경로 생성 및 수정을 생성합니다.

 

책 리소스 만들기

 

BooksController를 만들기 전에 책 리소스 클래스를 만들어 보겠습니다. 우리는 artisan 명령 make:resource를 사용하여 새로운 책 리소스 클래스를 생성합니다. 기본적으로 리소스는 애플리케이션의 app/Http/Resources 디렉토리에 배치됩니다.

 

$ php artisan make:resource BookResource

 

일단 생성되면, 그것을 열고 다음과 같이 toArray() 메소드를 업데이트하자.

 

    // app/Http/Resources/BookResource.php

    public function toArray($request)
    {
      return [
        'id' => $this->id,
        'title' => $this->title,
        'description' => $this->description,
        'created_at' => (string) $this->created_at,
        'updated_at' => (string) $this->updated_at,
        'user' => $this->user,
        'ratings' => $this->ratings,
      ];
    }

 

이름에서 알 수 있듯이, 이것은 리소스를 배열로 변환합니다. 배열은 응답을 보낼 때 JSON으로 변환 할 속성으로 구성됩니다. 따라서 책에 대한 세부 정보를 포함하는 것 외에도 책을 추가 한 사용자와 책의 모든 등급이 응답에 포함됩니다. JSON 응답에 포함시키지 않으려는 세부 정보는 toArray () 메서드에서 제거하면됩니다. 우리는 날짜 (created_at 및 update_at)를 문자열로 캐스팅하는 것을 볼 수 있습니다. 그렇지 않으면 응답에서 날짜가 객체로 반환되기 때문입니다.

보시다시피, $ this 변수에서 직접 모델 특성에 액세스 할 수 있습니다. 자원 클래스가 속성 및 메소드 액세스를 기본 모델에 자동으로 프록시하여 편리하게 액세스 할 수 있기 때문입니다. 이제 컨트롤러에서 BookResource 클래스를 사용할 수 있습니다.

 

책 컨트롤러 만들기

 

BookController를 만들어 보겠습니다. 이를 위해 Laravel 5.6에서 소개 된 API 컨트롤러 생성 기능을 사용합니다.

 

    $ php artisan make:controller BookController --api

 

다음으로 열어 다음 코드를 붙여 넣습니다.

 

    // app/Http/Controllers/BookController.php

    // add these at the top of the file
    use App\Book;
    use App\Http\Resources\BookResource;

    public function index()
    {
      return BookResource::collection(Book::with('ratings')->paginate(25));
    }

    public function store(Request $request)
    {
      $book = Book::create([
        'user_id' => $request->user()->id,
        'title' => $request->title,
        'description' => $request->description,
      ]);

      return new BookResource($book);
    }

    public function show(Book $book)
    {
      return new BookResource($book);
    }

    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', 'description']));

      return new BookResource($book);
    }

    public function destroy(Book $book)
    {
      $book->delete();

      return response()->json(null, 204);
    }

 

index() 메소드는 추가 된 책 목록을 가져 와서 리턴합니다. 이전에 만든 BookResource를 사용하고 있습니다. 책 목록을 가져 오므로 리소스 클래스에서 사용할 수있는 collection()을 사용합니다. 이를 통해 우리는 자원의 컬렉션을 가져올 수 있습니다. 콜렉션과 함께 반환 된 메타 데이터를 사용자 정의 할 수있는 추가 자원 콜렉션 (예 : php artisan make:resource BookCollection)을 만들 수 있지만 리턴 된 메타 데이터를 사용자 정의하지 않기 때문에 우리는 collection().

store() 메서드는 현재 인증 된 사용자의 ID로 책의 세부 정보와 함께 새 책을 만들고 데이터베이스에 보관합니다. 그런 다음 새로 생성 된 책을 기반으로 책 리소스를 반환합니다.

show() 메소드는 Book 모델을 받아들이고 (여기서 우리는 경로 모델 바인딩을 사용하고있다), 지정된 책에 기반한 책 리소스를 반환한다.

update() 메서드는 먼저 책을 업데이트하려는 사용자가 책의 소유자인지 확인합니다 (즉, 사용자는 책을 만든 사람입니다). 사용자가 책의 소유자가 아닌 경우 적절한 오류 메시지를 반환하고 HTTP 상태 코드를 403으로 설정합니다 (금지됨 - 사용자는 인증되었지만 작업을 수행 할 수있는 권한이 없음). 그렇지 않으면 책을 새로운 세부 정보로 업데이트하고 업데이트 된 세부 정보로 책 리소스를 반환합니다.

마지막으로, destroy() 메소드는 데이터베이스에서 지정된 책을 삭제합니다. 지정된 책이 삭제되어 더 이상 사용할 수 없기 때문에 응답의 HTTP 상태 코드를 204로 설정합니다 (내용 없음 : 액션이 성공적으로 실행되었지만 반환 할 내용이 없음).

 

레이팅 자원 생성

 

BookResource에서했던 것처럼 레이팅 리소스 클래스도 만들 것입니다.

 

    $ php artisan make:resource RatingResource

 

일단 생성되면, 그것을 열고 다음과 같이 toArray() 메소드를 업데이트하자.

 

    // app/Http/Resources/RatingResource.php

    public function toArray($request)
    {
      return [
        'user_id' => $this->user_id,
        'book_id' => $this->book_id,
        'rating' => $this->rating,
        'created_at' => (string) $this->created_at,
        'updated_at' => (string) $this->updated_at,
        'book' => $this->book,
      ];
    }

 

다시 응답을 보낼 때 JSON으로 변환 할 속성을 전달합니다. 응답에는 평가가 적용되는 도서도 포함됩니다.

 

레이팅 컨트롤러 생성

 

다음으로 RatingResource를 사용할 RatingController를 만듭니다.

 

    $ php artisan make:controller RatingController

 

다음으로 열어 다음 코드를 붙여 넣습니다.

 

    // app/Http/Controllers/RatingController.php

    // add these at the top of the file
    use App\Book;
    use App\Rating;
    use App\Http\Resources\RatingResource;

    public function store(Request $request, Book $book)
    {
      $rating = Rating::firstOrCreate(
        [
          'user_id' => $request->user()->id,
          'book_id' => $book->id,
        ],
        ['rating' => $request->rating]
      );

      return new RatingResource($rating);
    }

 

store ()는 지정된 책을 평가하는 데 사용됩니다. firstOrCreate ()를 사용하여 사용자가 이미 지정된 책을 평가했는지 확인합니다. 사용자가 가지고있는 경우 등급에 따라 등급 리소스를 반환하기 만하면됩니다. 그렇지 않으면 사용자 등급을 지정된 책에 추가하고이를 데이터베이스에 보관합니다. 그런 다음 새로 추가 된 등급에 따라 등급 리소스를 반환합니다.

 

평균 레이팅 받기

 

그만큼 API의 모든 기능이 거의 완료되었습니다. 마지막으로 남은 기능은 책에 대한 평균 평점을 얻는 것입니다. API가 이미 잘 구조화되어 있기 때문에 이것은 간단합니다.

아래의 코드 행을 app/Http/Resources/BookResource.php의 toArray() 메소드에 추가하십시오.

 

    // app/Http/Resources/BookResource.php

    'average_rating' => $this->ratings->avg('rating')

 

Google은 도서 모델에 정의 된 평가 관계를 사용하여 지정된 책에 대한 모든 평가를 가져옵니다. 그런 다음 컬렉션 avg()를 사용하여 등급의 평균을 구합니다. rating을 avg() 함수에 전달하면 책 등급을 기준으로 평균을 계산할 수 있습니다.

이제 BookResource가 사용될 때마다 응답에는 책의 평균 등급이 포함됩니다.

샘플 책 리소스 응답은 다음과 같습니다.

 

800591923_1546286306.2804.png

 

샘플 레이팅 리소스 응답은 다음과 같습니다.

 

800591923_1546286378.7827.png

 

응답 형식이 올바른지 확인할 수 있습니다.

 

API 엔드 포인트 보안

 

이 자습서를 끝내기 전에 미들웨어를 사용하여 API 끝점을 보호하십시오. 서점 종점을 보호하려면 app/Http/Controllers/BookController.php에 아래 코드를 추가하십시오.

 

    // app/Http/Controllers/BookController.php

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

 

보시다시피 auth:api 미들웨어를 사용하고 있습니다. 여기에서는 index () 및 show () 메소드가 미들웨어를 사용하는 것을 면제하고 있습니다. 그렇게하면 사용자는 인증 할 필요없이 모든 책 및 특정 책의 목록을 볼 수 있습니다.

책을 평가할 끝점을 확보하고 app/Http/Controllers/RatingController.php에 아래 코드를 추가해 보겠습니다.

 

    // app/Http/Controllers/RatingController.php

    public function __construct()
    {
      $this->middleware('auth:api');
    }

 

처리 리소스를 찾을 수 없습니다.

 

기본적으로 지정된 모델을 찾을 수없는 경우 Laravel은 ModelNotFoundException을 발생시키고 404 페이지를 렌더링합니다. API를 작성 중이므로 예외를 처리하고 API에 친숙한 오류 메시지를 표시하려고합니다.

아래 코드를 app/Exceptions/Handler.php의 render 메소드에 추가하십시오.

 

    // app/Exceptions/Handler.php

    if ($exception instanceof ModelNotFoundException && $request->wantsJson()) {
      return response()->json([
        'error' => 'Resource not found'
      ], 404);
    }

 

이 예외는 Throw 된 예외가 ModelNotFoundException의 인스턴스이고 요청에서 JSON이 필요한지 확인한 다음 오류 메시지가없는 응답을 반환하고 HTTP 상태 코드를 404로 설정합니다 (Not Found - 서버에없는 Request-URI와 일치하는 것을 찾음).

 

팁 : 위의 작업을 수행하려면 API 요청에 Accept : application/json 헤더가 필요합니다.

 

결론

 

그게 다야! 이 자습서에서는 API 리소스가 무엇인지, API 리소스를 사용하여 API를 빌드하는 방법을 살펴 보았습니다. 또한 Laravel의 API에 JWT를 사용하여 인증을 추가하는 방법을 설명했습니다.

API 리소스에 대해 자세히 알아 보려면 공식 문서를 확인하십시오. 이 자습서의 전체 코드는 GitHub에서 사용할 수 있습니다.

추천
1

댓글 0개

전체 223 |RSS
PHP프레임워크 내용 검색

회원로그인

진행중 포인트경매

  1. 참여1 회 시작24.03.28 11:15 종료24.04.04 11:15
(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT