Laravel Eloquentは、データベースとの対話を楽にしてくれる仕組みです。テーブルと対話するモデルを提供することでデータベースの複雑さを簡略化する、オブジェクト関係マッピング(ORM)です。
Laravel Eloquentには、開発をサポートするAPIを作成しテストする優れた機能があります。今回の記事では、Laravelを使用して簡単にAPIを作成し、テストする方法をご紹介します。
このデモでは、まずAPIとデータベーステーブルを構築するためのモデルを作成します。次に、ビジネスロジックの層としてコントローラを追加し、APIを完成させるためのルートを追加する方法を説明します。その後、Postmanを使用してAPIをテストする方法を確認し、最後に認証とエラー処理に焦点を当てます。
前提条件
はじめに、必要なものは以下の通りです。
- Laravelバージョン8または9
- Composer
- Postman
- XAMPP
- APIとPHPの基礎知識
APIの基礎知識
まずはcomposer
でLaravelのプロジェクトを新規作成します。
composer create-project laravel/laravel laravel-api-create-test
サーバーを起動するには、以下のコマンドを実行し、ポート8000でアプリケーションサーバーを実行します。
cd laravel-api-create-test
php artisan serve
以下の画面が表示されるはずです。
次に、以下のコードで-m
フラグを付してマイグレーションのモデルを作成します。
php artisan make:model Product -m
次に、必須フィールドを含むようにマイグレーションファイルをアップグレードします。database/migrations/{date_stamp}_create_products_table.phpファイル内に、商品モデルのタイトルと説明フィールド、および以下の2つのテーブルフィールドを追加します。
$table->string('title');
$table->longText('description');
次に、フィールドを入力可能にしましょう。app/Models/Product.phpの中で、title
とdescription
を入力可能なフィールドとして定義します。
protected $fillable = ['title', 'description'];
コントローラの作成
次に、以下のコマンドを実行し、商品のコントローラファイルを作成します。これで、app/Http/Controllers/Api/ProductController.phpファイルが作成されます。
php artisan make:controller ApiProductController --model=Product
そして、商品の作成と取得のためのロジックを追加します。index
メソッドの中に、以下のコードを追加して、すべての商品を取得します。
$products = Product::all();
return response()->json([
'status' => true,
'products' => $products
]);
その後、新しい商品をデータベースに保存するためにStoreProductRequest
クラスを追加します。同じファイルの一番上に次のクラスを追加してください。
public function store(StoreProductRequest $request)
{
$product = Product::create($request->all());
return response()->json([
'status' => true,
'message' => "Product Created successfully!",
'product' => $product
], 200);
}
続いて、リクエストを作成します。これは以下のコマンドで実行できます。
php artisan make:request StoreProductRequest
バリデーションを追加したい場合は、app/Http/Requests/StoreProductRequest.phpファイルを使用します。このデモでは、バリデーションは実装しません。
ルートを作成する
APIをテストする前の最後のステップとして、ルートを追加します。routes/api.phpファイル内に以下のコードを追加します。ファイルの冒頭にuse
を、本文にRoute
を追加します。
use AppHttpControllersApiProductController;
Route::apiResource('products', ProductController::class);
APIのテストを開始する前に、productsテーブルがデータベースに存在することを確認してください。存在しない場合は、XAMPPのようなコントロールパネルを使って作成します。また、以下のコマンドで、データベースのマイグレーションも可能です。
php artisan migrate
APIをテストする
APIをテストする前に、app/Http/Requests/StoreProductRequest.php内のauthorize
メソッドがtrue
を返すように設定されていることを確認して下さい。
これで、Postmanを使って新しい商品を作ることができます。まず、URL「http://127.0.0.1:8000/api/products/」に対してPOST
リクエストを出します。これは新しい商品を作るためのPOST
リクエストですので、タイトルと説明を記述したJSONオブジェクトを渡します。
{
"title":"Apple",
"description":"Best Apples of the world"
}
「Send」ボタンをクリックすると、以下のように表示されるはずです。
続いて、GET
リクエストを使用して、作成した商品を取得します。URLは同じです。結果は以下のようになります。
Sanctumを使用してAPIを認証する
APIを保護する上で、認証は非常に重要です。LaravelではミドルウェアとしてSanctumトークンを使用できます。ユーザーが正しい認証情報を使ってログインすると、トークンが生成され、これを使うことでAPIを保護します。トークンなしでは保護の適用されたAPIにアクセスできません。
認証を実装する最初のステップとして、以下のコードを使用してSanctumパッケージを追加します。
composer require laravel/sanctum
そして、Sanctumの設定ファイルを公開します。
php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"
その後、ミドルウェアとしてSanctumのトークンを追加します。app/Http/Kernel.phpファイル内で、以下のクラスを使用し、保護対象のミドルウェアグループのAPIで、middlewareGroups
を以下のコードに置き換えます。
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
次に、UserController
を作成し、トークンを取得するコードを追加します。
php artisan make:controller UserController
UserController
を作成したら、app/Http/Controllers/UserController.phpファイルに移動して、既存のコードを次のコードに置き換えます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
//
function index(Request $request)
{
$user= User::where('email', $request->email)->first();
// print_r($data);
if (!$user || !Hash::check($request->password, $user->password)) {
return response([
'message' => ['These credentials do not match our records.']
], 404);
}
$token = $user->createToken('my-app-token')->plainTextToken;
$response = [
'user' => $user,
'token' => $token
];
return response($response, 201);
}
}
認証をテストする前に、シーダーでユーザーを採用します。次のコマンドで、UsersTableSeederファイルを作成します。
php artisan make:seeder UsersTableSeeder
database/seeders/UsersTableSeeder.phpファイルの中で、既存のコードを次のコードに置き換えて、シーディングによりユーザーを作成します。
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('users')->insert([
'name' => 'John Doe',
'email' => '[email protected]',
'password' => Hash::make('password')
]);
}
}
次に、このコマンドを使用してシーダーを実行します。
php artisan db:seed --class=UsersTableSeeder
認証フローの最後のステップとして、作成したミドルウェアを使用してルートを保護します。routes/api.phpファイルに移動して、ミドルウェアの中にproductsルートを追加します。
use App\Http\Controllers\UserController;
Route::group(['middleware' => 'auth:sanctum'], function () {
Route::apiResource('products', ProductController::class);
});
Route::post("login",[UserController::class,'index']);
ミドルウェアにルートを追加した後、商品をフェッチしようとすると次のように内部サーバーエラーが発生します。
ログインしてトークンを取得し、それをヘッダーに使用すれば、認証され、動作が開始します。http://127.0.0.1:8000/api/loginに以下のようなボディでPOSTリクエストを送信します。
{
"email":"[email protected]",
"password":"password"
}
受け取ったトークンをBearerトークンとして使用し、これをAuthorizationヘッダとして追加します。
APIエラーの処理
サーバーにリクエストを送信するとレスポンスが返ってきます。レスポンスと同時に、レスポンスの性質に応じたステータスコードも送信されます。例えば、200のステータスコードはリクエストが成功したことを示し、404はリクエストされたリソースがサーバーに見つからないことを意味します。
しかし、ステータスコードだけでは十分ではありません。人間が読めるようなエラーメッセージが必要です。Laravelには、エラーを処理する多くの機能が用意されています。try-catchブロック、fallbackメソッドを使用したり、カスタムレスポンスを送信したりすることができます。UserController
の次のコードがこれを処理しています。
if (!$user || !Hash::check($request->password, $user->password)) {
return response([
'message' => ['These credentials do not match our records.']
], 404);
}
まとめ
LaravelのEloquentにより、APIを簡単に作成、検証、テストできます。オブジェクト関係マッピングのおかげで、データベースとのやり取りが簡単に行えます。
さらに、ミドルウェアとして機能するLaravelのSanctumトークンは、APIを素早く保護するのに役立ちます。
さらなる最適化をお求めであれば、Kinstaのデータベースホスティングソリューションがおすすめです。すべてのウェブプロジェクトのデータベースのセットアップと管理を簡素化する選択肢となっています。
コメントを残す