LumenでAPIを作ったんですが、APIってCRUDベースで作れば事足りる機能がほとんどかなと思い、継承を使ってサクッと作ってみました。
継承を使えば記述量もぐっと減るし、うまく使えれば大変便利です
それにバシーっと決まれば個人的にめっさ気持ち良いですよね
構成
上記図の通り親クラスとなる ApiController に具体的な処理を書き
それを継承するようにします
継承先はControllerとModelがあり紐づいてます
CRUDをベースとなるコントローラに作成する
メソッドはCRUDを基とし以下のようになっています
- index→一覧
- show→詳細
- store→登録
- update→更新
- destroy→削除
app/Http/Controllers/ApiController.php
<?php
namespace App\Http\Controllers;
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class ApiController extends BaseController
{
protected static $model = "";
public function index()
{
$response = static::$model::all();
return response()->json($response);
}
public function show($id = 0)
{
if(! $id) {
$response["status"] = "ng";
$response["messages"] = "引数が不正です";
return response()->json($response);
}
$response = static::$model::find($id);
if(count($response) < 1) {
$response["status"] = "ng";
$response["messages"] = "情報が見つかりません";
return response()->json($response);
}
$response["status"] = "ok";
return response()->json($response);
}
public function store(Request $request)
{
$validator = static::$model::validation($request);
$response = [];
if ($validator->fails()) {
$response["status"] = "ng";
$response["messages"] = $validator->errors()->all();
return response()->json($response);
}
static::$model::create($request->all());
$response["status"] = "ok";
return response()->json($response);
}
public function update(Request $request, $id)
{
$updates = $request->all();
unset($updates['api_key']);
$response = false;
$response = static::$model::where('id', '=', $id)->update($updates);
if ($response === 0) {
$response["status"] = "ng";
$response["messages"] = "パラメータが不正です";
return response()->json($response);
}
$response["status"] = "ok";
return response()->json($response);
}
public function destroy($id)
{
$result = static::$model::destroy($id);
if ($result === 0) {
$response["status"] = "ng";
$response["messages"] = "パラメータが不正です";
return response()->json($response);
}
$response["status"] = "ok";
return response()->json($response);
}
}
HTTPレスポンスコードの定義してへんやんとかページネーションは?とかのツッコミは一旦なしで
モデルの定義
protected static $model = "";
上記の通り、モデルは継承先で定義するため、親クラスでは空で設定します
バリデーションの定義
<?php
namespace App\Http\Controllers;
use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
class ApiController extends BaseController
{
〜省略〜
public function store(Request $request)
{
$validator = static::$model::validation($request);
$response = [];
if ($validator->fails()) {
$response["status"] = "ng";
$response["messages"] = $validator->errors()->all();
return response()->json($response);
}
static::$model::create($request->all());
$response["status"] = "ok";
return response()->json($response);
}
〜省略〜
}
$validator = static::$model::validation($request);
バリデーションもモデル側で定義することにより継承をやりやすくしております
モデルの定義
app/Company.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Validator;
class Company extends Model
{
protected $table = 'companies';
protected $fillable = ['name'];
public static function validation($request)
{
return Validator::make($request->all(), [
'name' => 'required|max:256|unique:companies',
]);
}
}
とりあえずCompanyモデルを例としています
上記の通りバリデーションを書いてます
LumenはデフォルトでModelディレクトリがないのでこのパスになってますが、Modelディレクトリ作っても良いかもですね。
コントロラーの定義
<?php
namespace App\Http\Controllers;
use App\Company;
class CompanyController extends ApiController
{
protected static $model = "App\Company";
}
モデルと同様にCompanyコントローラを例としています
最初に作成した ApiController を継承しています
そして$modelをComapnyモデルを使うように上書きしています
一点注意としてクラス名を動的に設定する場合はnamespaceを含め設定する必要があります
確認
これでAPIの作成は終わったのでcurlなりPostmanなりで
ドメイン/company/
や
ドメイン/company/store
にアクセスし正常に動作すれば完成です
コントロラーを増やしたければCompanyを基にモデルとコントロラーを作成すれば簡単に増やせます
以上です