# Laravel授業4回目(PaizaCloud版) API開発 ## 環境構築 ### 【サーバーの立ち上げ】 #### 1. ログインが完了したら新規サーバ作成をクリックするボタンが表示されます。以下の設定でサーバー作成 ``` サーバ名:デフォルトでOK web開発:PHP,Laravel データベース:MySQL,phpMyAdmin ``` その他は設定不要 新規作成ボタンをクリック ### 【Laravelプロジェクトの立ち上げ】 #### 1. ターミナルを立ち上げてLaravelプロジェクト作成コマンドを入力 `composer create-project laravel/laravel cms 6.* --prefer-dist` #### 2. cms(プロジェクトディレクトリ)にターミナル上で移動 `cd cms` #### 3. ターミナル上CMS階層でComposerコマンド実行 `sudo composer update` #### 4. ターミナル上CMS階層でBuiltInサーバーを起動:動作確認 `php artisan serve` server startedと表示されてURLが生成されればOKです。 左側に地球で8000番ポートでプロジェクトが立ち上がっているはずです。 ブラウザで確認までいきましょう。 ## 共通初期設定 ### 【Laravelプロジェクト初期設定】 #### 1. データベースを作成 エディタ左側の一番上に🔽ボタンをクリックすると下の方にMySQLがあるのでStart MySQLをクリックしてMySQlを起動 phpMyAdminのタブ内のOpen phpMyAdminをクリックして起動 phpMyAdminの管理画面からc9というデータベースを作成。 ``` DB名:c9 照合順:utf8mb4_general_ci ``` #### 2. env(ファイル内の同じ箇所を上書き) *隠しファイル表示はエディタ左側ファイル階層で右クリック ``` DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=c9 DB_USERNAME=root DB_PASSWORD= ``` #### 3. /app/Providers/AppServiceProvider.php ファイルを修正 ``` use Illuminate\Support\Facades\URL; //この行を追加 public function boot() { URL::forceScheme('https'); //この行を追加 } ``` #### 4. サーバーの再起動 envファイルなどの設定を書き換えたときは必ず再起動!! サーバー起動後のターミナル上で `Ctrl + C` #### 5. 表示の仕組みをチェックしてみる! /resouces/views/welcome.blade.php を編集して見よう! ブラウザ・更新で確認 → 変更確認できればOK ## ログイン認証 ### 【ログイン認証実装】 #### 1. マイグレーションを実行 `php artisan migrate` #### 2. laravel/ui パッケージをインストール `composer require laravel/ui:^1.0 --dev` #### 3. artisan コマンドを実行 `php artisan ui vue --auth` #### 4. npmパッケージをインストール `npm install` #### 5. パッケージをビルド `npm run dev` ## APIを使ったCRUDの作成 ### テーブルの作成(Bookモデルとbooks_tableを作成します) #### 1. モデル作成とセットでマイグレーションファイルも作成する `php artisan make:model Book -m` #### 2. booksのマイグレーションファイルの中に以下を追記 ``` public function up() { Schema::create('books', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('title');//追記 $table->text('body');//追記 $table->timestamps(); }); } ``` #### 3. マイグレーション実行 `php artisan migrate` ### モデル、コントローラー、ルーティングを作っていく #### 1. API階層とBooksコントローラーを作成する(API用のメソッドとモデルを自動で設定) `php artisan make:controller Api/BooksController --resource --model=Book` #### 2. routes/api.phpにルーティングを記述 ``` // books用のAPIルーティング Route::group(['middleware' => ['api']], function(){ Route::resource('books', 'Api\BooksController'); }); ``` #### 3. ルーティング一覧を見てみる `php artisan route:list` こんな感じになってるはず ``` +--------+-----------+-----------------------+---------------+--------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+-----------+-----------------------+---------------+--------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/books | books.index | App\Http\Controllers\Api\BooksController@index | api | | | POST | api/books | books.store | App\Http\Controllers\Api\BooksController@store | api | | | GET|HEAD | api/books/create | books.create | App\Http\Controllers\Api\BooksController@create | api | | | GET|HEAD | api/books/{book} | books.show | App\Http\Controllers\Api\BooksController@show | api | | | PUT|PATCH | api/books/{book} | books.update | App\Http\Controllers\Api\BooksController@update | api | | | DELETE | api/books/{book} | books.destroy | App\Http\Controllers\Api\BooksController@destroy | api | | | GET|HEAD | api/books/{book}/edit | books.edit | App\Http\Controllers\Api\BooksController@edit | api | | | GET|HEAD | api/user | | Closure | api,auth:api | +--------+-----------+-----------------------+---------------+--------------------------------------------------+--------------+ ``` 各メソッド大まかな役割分担 ``` index -> 一覧表示(対象のテーブルのデータを全件取得とか) store -> テーブルに対してデータを登録する create -> データ登録画面を表示する show -> 特定IDの1件のデータを取得し表示する update -> データの更新処理 destroy -> データの削除処理 edit -> データの更新画面を表示する ``` #### 4. APIは画面表示ルーティングは不要なので【create】と【edit】はroutes/api.phpから削除 ``` Route::group(['middleware' => ['api']], function(){ Route::resource('books', 'Api\BooksController', ['except' => ['create', 'edit'] ]); }); ``` #### 5. 再度ルーティング一覧を確認 `php artisan route:list` 削除したメソッドのルーティングが消えているはず ``` +--------+-----------+------------------+---------------+--------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+-----------+------------------+---------------+--------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/books | books.index | App\Http\Controllers\Api\BooksController@index | api | | | POST | api/books | books.store | App\Http\Controllers\Api\BooksController@store | api | | | GET|HEAD | api/books/{book} | books.show | App\Http\Controllers\Api\BooksController@show | api | | | PUT|PATCH | api/books/{book} | books.update | App\Http\Controllers\Api\BooksController@update | api | | | DELETE | api/books/{book} | books.destroy | App\Http\Controllers\Api\BooksController@destroy | api | | | GET|HEAD | api/user | | Closure | api,auth:api | +--------+-----------+------------------+---------------+--------------------------------------------------+--------------+ ``` ### CRUD処理を作っていく #### 1. indexメソッド(一覧表示) ``` public function index() { $books = Book::all(); return $books; } ``` #### 2. storeメソッド(登録処理) ``` public function store(Request $request) { $book = new Book; $book->title = $request->title; $book->body = $request->body; $book->save(); } ``` #### 3. showメソッド(特定IDのみ取得) ``` public function show(Book $book) { return $book; } ``` #### 4. updateメソッド(更新処理) ``` public function update(Request $request, Book $book) { $book->title = $request->title; $book->body = $request->body; $book->save(); return $book; } ``` #### 5. destroyメソッド(削除処理) ``` public function destroy(Book $book) { $book->delete(); } ``` #### 6. サーバーを再起動 `Ctrl + C` `php artisan serve --host=0.0.0.0` *ホストを0.0.0.0にするのがポイント!! ## PostmanでAPIのテスト #### 1. postmanにアクセスしてログイン https://identity.getpostman.com/login #### 2. Workspaces>MyWorkspaceに入る #### 3. リクエストを作ってみる(Overviewの横のプラスボタンから新規タブ) GETメソッドで以下のURLを作成して貼り付け `http://{自分のcloud9 の IP アドレス}:8000/api/books` 例:`http://localhost-〇〇.paiza-user-lite.cloud:8000/api/books` SendをクリックしてみてエラーがなければOK #### 4. メソッドをPOSTに変更してデータを登録してみる POSTメソッド `http://{自分の PaizaCloudのアドレス}:8000/api/books` 例:`http://localhost-〇〇.paiza-user-lite.cloud:8000/api/books` 真ん中あたりのBodyからform-dataをクリックして以下を入力 ``` KEY | VALUE -------------- title | テスト body | サンプル ``` Sendを押して登録→別タブでGETで全件取得してみる #### 5. UpdateメソッドをPOSTでデータ更新してみる POSTメソッド `http://{自分の PaizaCloudのアドレス}:8000/api/books/{本のid}` 例:`http://localhost-〇〇.paiza-user-lite.cloud:8000/api/books/1` ``` KEY | VALUE -------------- title | テスト body | サンプル _method | PUT ``` Sendしてリターンをチェック ## PassPortを使ったAPI認証 ### Passportをインストール #### 1. laravel passportのパッケージをインストール `composer require laravel/passport:9.4.0` #### 2. マイグレーションを実行 `php artisan migrate` #### 3. install実行 `php artisan passport:install` ### 諸々の設定 #### 1. app/User.phpにHasApiTokensを追加 ``` <?php namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Passport\HasApiTokens; //追記 class User extends Authenticatable { use HasApiTokens , Notifiable; //変更 省略 } ``` #### 2. app/Providers/AuthServiceProvider.phpにPassportを呼び出す ``` <?php namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; use Laravel\Passport\Passport; //追記 class AuthServiceProvider extends ServiceProvider { 省略 public function boot() { $this->registerPolicies(); Passport::routes(); //追記 } } ``` #### 3.config/auth.phpのapiをpassportに変更 app/Providers/AuthServiceProvider.phpにPassportを呼び出す ``` 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport',<-ここを変更 'provider' => 'users' ], ], ``` ### トークン発行処理を作成 #### 1. コントローラー作成 `php artisan make:controller Api/AuthController ` #### 2. login処理を作成 ``` public function login(Request $request) { $credentials = $request->only('email', 'password'); if(auth()->attempt($credentials)) { $user = auth()->user(); $token = $user->createToken('Laravel Password Grant Client')->accessToken; return ['token' => $token]; } return response([ 'message' => 'Unauthenticated.' ], 401); } ``` ### ルーティングとPostmanでテスト #### 1. routes/api.phpに以下を追記 `Route::post('/login', 'Api\AuthController@login');` #### 2. POSTメソッドで以下のURLにテストデータを送ってみる *事前にユーザーを1名登録しておく POSTメソッドでapi/loginにリクエスト `http://{自分の PaizaCloudのアドレス}:8000/api/login` 例:`http://localhost-〇〇.paiza-user-lite.cloud:8000/api/login`  bodyのform-dataに以下のデータをセットしてSend ``` KEY | VALUE -------------- email | test@test.jp password | testtest ``` 戻り値でtokenが戻ってくれば成功 #### 3. 認証済みのユーザーのみデータが取得できるAPIを叩く GETメソッドでapi/userにリクエスト `http://{自分の PaizaCloudのアドレス}:8000/api/user` 例:`http://localhost-〇〇.paiza-user-lite.cloud:8000/api/user`  Headersに以下のデータをセットしてSend ``` KEY | VALUE -------------- Accept | application/json Authorization | Bearer さっきのトークン ``` ポイントは半角スペース `「Bearer 123456789」` これでログインユーザー情報が返ってきたら成功 ## APIでのリレーション ### テーブルとモデルをリレーション用に修正 #### 1. booksテーブルにカラム追加 `php artisan make:migration add_user_id_to_books_table --table=books` #### 2. マイグレーションファイルに以下を追加 ``` public function up() { Schema::table('books', function (Blueprint $table) { $table->integer('user_id'); //カラム追加 }); } ``` #### 3. マイグレーション実行 `php artisan migrate` #### 4. リレーションをモデルに記述 ##### 1 App/User.phpの中の39行目を改行して以下の内容をコピー ``` // booksテーブルとのリレーション (主テーブル側) public function books() { return $this->hasMany('App\Book'); } ``` ##### 2 App/Book.phpの中の9行目を改行して以下の内容をコピー ``` // Userテーブルとのリレーション (従テーブル側) public function user() { return $this->belongsTo('App\User'); } ``` #### 5. routes/api.phpの/userのルーティングを以下に変更 ``` Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user()->with('books')->get(); //変更した部分 }); ``` #### 6 Postmanでテストしてみる GETメソッドでapi/userにリクエスト `http://{自分の PaizaCloudのアドレス}:8000/api/user` `例:http://localhost-〇〇.paiza-user-lite.cloud:8000/api/user`  Headersに以下のデータをセットしてSend ``` KEY | VALUE -------------- Accept | application/json Authorization | Bearer さっきのトークン ``` ポイントは半角スペース 「Bearer 123456789」 これでログインユーザーの保持しているbooksの情報が返ってくれば成功 #### 7. BooksControllerのstoreをいかに変更 ``` public function store(Request $request) { $book = new Book; $book->title = $request->title; $book->body = $request->body; $book->user_id = Auth::id(); //追記 $book->save(); } ``` #### 8. routes/api.phpのbooksのルーティングを以下に変更 ``` // books用のAPIルーティング Route::group(['middleware' => ['auth:api']], function(){ Route::resource('books', 'Api\BooksController',[ 'except' => ['create', 'edit'] ]); }); ``` これで本のCRUDはログイン済みユーザーのみ使える機能になりました。