Laravel5.3でAPIを簡単に作ってみる
今年の8月にLaravel5.3がリリースしましたね。
色々な変更がありましたが、個人的にはルーティングのファイルが別れたこともなかなか嬉しかったです。
大規模なプロジェクトになるとエンドポイントがたくさん増えてroute.phpがどんどん大きくなってしまいました。またRailsであってもroutes.rbが大きくなってしまっていました。
今回開発中の弊社の新サービスのLaravelのバージョンを5.3にあげたのでLaravelでの入門的なAPIの書き方について書こうと思います。
ルーティングの設定
まず、app/Providers/RouteServiceProvider.phpへルーティングファイルを登録します。
class RouteServiceProvider extends ServiceProvider { protected $namespace = 'App\Http\Controllers';
public function boot()
{
//
parent::boot();
}
public function map()
{
$this->mapWebRoutes();
$this->mapApiRoutes();
}
protected function mapWebRoutes()
{
// 普通のルーティング
}
protected function mapApiRoutes()
{
Route::group([
// Kernel.phpでapiに登録されているミドルウェアを適応
'middleware' => 'api',
// Controllers/Api以下にあるクラスに限定する
'namespace' => "{$this->namespace}\Api",
// エンドポイントを/api/somethingの形にする
'prefix' => 'api',
], function ($router) {
// api.phpを登録する
require base_path('routes/api.php');
});
}
}
これでroutes/api.phpへルーティングを書くことができるようになりました。
コントローラを書く
Laravelには様々な機能があり、コントローラを書く上ではValidatorが特に重宝していると思います。
試しに"/api/test?id=1&date=2016-09-28&title=MatchinGood"という感じでアクセスできるAPIのコントローラを描いてみます。
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request; use App\Http\Controllers\Controller;
class TestController extends Controller { public function test(Request $request) { $validator = Validator::make($request->all(), [ // 必須パラメータかつ整数 'id' => 'required|integer', // 必須パラメータかつY-m-dの形 'date' => 'required|date_format:"Y-m-d"', // 必須パラメータかつ文字列 'title' => 'required|string' ]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
return response()->json(['status' => 'successful']);
}
}
こんな感じでどうでしょうか。煩雑になりがちなパラメータのバリデーションはすべてLaravelのValidatorに任せられます。公式ドキュメントには色々なバリデーションの種類がありますので適切なものを選択します。
APIなのでバリデーションが失敗した時の返り値もjsonである必要がありますが、$validator->errors()を使うとエラーの内容が取得できるのでそれを使うと楽できます。
ルーティング
<?php Route::get('test', 'TestController@test'); RouteServiceProviderでnamespaceをApp\Http\Controllers\Apiで設定してあるのでnamespaceの先頭のApiは省くことができます。
おまけ
実はLaravelには$request->wantsJson()でリクエストヘッダーに"ContentType: application/json"がセットされているかどうか調べることができます。なので単純にcompanyというリソースの詳細画面に行くURIが"/company/1"で、わざわざ別のコントローラにAPIを書きたくないと思った時は
public function show(Company $company, Request $request) { if ($request->wantsJson()) { return $company; } return view('company.detail')->with('company', $company); } というふうにすることでリクエストのヘッダーに応じてjsonで返すことができます。
ここで、なぜ単純にEloquentのモデルをコントローラの返り値として返しているかというと、LaravelのEloquentのソースでは、
abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable { . . . public function __toString() { return $this->toJson(); } } となっていて、stringにキャストする際にtoJson()を呼んでいることがわかります。toJson()ではモデルの各カラムの値とリレーションをjsonの文字列にして返します。なのでこれでモデルをそのままjsonの形式で返すことができています。
より詳しい実装がきになる方は実際にソースコードを読むことをお勧めします。
laravel/framework Contribute to framework development by creating an account on GitHub. https://github.com/laravel/framework/blob/5.3/src/Illuminate/Database/Eloquent/Model.php