経緯
普段はフロントエンド、vueやnuxtの開発を中心にやっています。今回はバックエンドも含めて開発する案件を受注したことをきっかけに、最近流行ってるlaravelでバックエンドを作ってみるか、ということになりました。
もともと、LAMP環境の構築やphp,mysqlは経験がある古のエンジニアです。
以前は素のphp+mysqlでフレームワークを使わずゴリゴリ書いていました。
開発環境はlinux(CentOS)をベアメタルサーバーにインストールして、phpやmysqlをソースからインストールしたりして使う、そういう時代のエンジニアです。HTTPサーバーといえばapacheでしょ?という時代から、最近のAWSは便利だよね〜という時代を生きてきた人です。
ちなみにデータセンターにオンプレミス環境を構築して月間数億PVのアクセスがあるソシャゲの開発運用とかを一人でやったりしていました。AWSに移行してからはRDSの負荷分散のためmemcachedサーバーにキャッシュレイヤーを作ったり、懐かしい。
話はそれてしまいましたが、最近はフロントエンド中心の開発案件をやっています。
バックエンドとのやり取りはAPIでやることが主流の時代になってきました。
久しぶりにバックエンド作るので、最新のモダンで人気なフレームワークをいっちょやってやるか!と思い人気のlaravelに目をつけたわけです。
laravelを選んだ理由
- 日本語で書かれたドキュメントやサンプルが多い
- AWSとの連携が組み込み済み
- API用のレイヤーが標準装備
- Model経由でのDBとの密な連携
この辺です。テーブル作成はphpmyadminで、PHPの中にSQLを直書きしていた私からすると、アプリケーション内からModelでDBと密接に結合しているのは新鮮です。
フロントエンドとはAPIで連携するので、その辺の機能も標準装備していることに魅力を感じました。
開発環境構築
Laravel環境構築はこちらの神リポジトリをcloneしてdockerで一発です。すごい便利な時代になったものですなぁ、昔はLinuxのインスト(ry
laravelのtableを作ってみて、表示させてみる
えっ!DBのテーブルってphpmyadminでチマチマ作るんじゃないんですか?
なるほど、作成、変更履歴も残せるマイグレーションと言うのがあるのか…
larvel passportでAPI認証のバックエンド側基本を作る→やめた
シンプルなjwtに切り替えました。
composer dumpautoloadってなんだ?
おかしくなったときはこれ。でもあまり使わない。
laravel上でvueベースの認証画面を作る
基本のapiのやりとり。
nodeが無いと言われたのでこちらでDockerを再構築
http://127.0.0.1/register
にアクセスしてみる
npm run devが抜けていたため、以下のファイルが見つからんかった
/css/app.css 178 KiB /js/app [emitted] /js/app
/js/app.js 1.4 MiB /js/app [emitted] /js/app
再度アクセスするとうまくいった
Personal access client not found. Please create one. エラーがでる
php artisan passport:client --personal
上記コマンドならうまくいく、
その後webで再度やるとうまく行った。なんでや?
makefileのinitに以下のコマンドを追加した→削除
docker-compose exec app php artisan passport:install
laravelのアクセスがやったら重いんですけど
Docker for Mac限定の問題。
色々試しましたけど、最終的には直接php artisan serveすることで解決。
dockerのvolumeのマウントが原因。 :delegatedをつけたら少し軽くなった。
/api/userにアクセスしてもなにも起こらない
忘れがち
なお、JSONが返されるのはLaravel5.3のデフォルトではヘッダーにX-Requested-With: XMLHttpRequestがある、またはAcceptヘッダーでjsonが指定されている場合です。(fetchにネイティブ対応しているブラウザではそれを使用した場合明示的にAcceptを指定してやらないと前者の対象にはならずにリダイレクトが発生し200になります。宇宙。)
https://blog.hinaloe.net/2016/09/15/try-passport-laravel-5-3/
Acceptヘッダとauth Bearerヘッダを追加して再確認、うまくいった。
よく考えたら、backendフォルダ内で直接laravel動かしたらいいんじゃね?
→動いた。ローカルなので応答も早い。
DBの接続情報を変更する必要がある。Dockerコンテナは環境変数を変更しているため。
DB_DATABASE=laravel_local
DB_USERNAME=phper
DB_PASSWORD=secret
.envの更新を反映させるにはコマンドが必要
php artisan cache:clear
php artisan config:cache
passportやめたい
composer.jsonを編集して composer update
認証APIをjwtで作り直し
参考
https://re-engines.com/2019/06/03/laravelで認証apiを作る/
うごかないなんでや
https://github.com/tymondesigns/jwt-auth/issues/1484
replace
'expires_in' => auth()->factory()->getTTL() * 60
by
'expires_in' => auth('api')->factory()->getTTL() * 60
うごいた。ここでtokenの有効期限も設定できるっぽい
認証APIにregisterを移植した
バリデーションも合わせて実装した
userのcrudをAPIで実装する
参考
https://qiita.com/sutara79/items/cd4371b246b44a2cf87f
putのrequestが空っぽなんなんでや??
postmanの設定だった
PUT時にuserが見つからない場合に出るModelNotFoundExceptionエラーをカスタマイズする
abortの第一引数にresponceを渡さないとstach traceが出るみたいだぞ?
その他、細かく設定する場合
https://qiita.com/sakuraya/items/af38c4cf84459a8b5967
基本形
public function render($request, Throwable $exception)
{
if ($exception instanceof ModelNotFoundException)
{
abort(response()->json(['message' => 'not found'], 404));
}
return parent::render($request, $exception);
}
コードフォーマッタとリンターがないので入れる
開発用のメールサーバー
ブラックホールメールサーバーのDockerコンテナを開発用に立てる
http://127.0.0.1:1080 で送信したメールが全部見れる。なんて便利な世の中や・・
seederでダミーデータを適当に作る。マスタデータも作れる。
Route::resources で全部使わないよ!って場合
もはや個別にmodel,controllerとか作らなくても良くない?全部まとめて作れるで
管理画面をlaravel-adminで作る
https://laravel-admin.org/docs/#/
https://tac-blog.tech/index.php/2018/09/29/laravel-admin-add-crud/
管理設定をmigrationできるようにseederに追加する
基本のDBクエリビルド
Laravel debaggerを入れる
apiResource
純粋なAPIで使用するCRUDの場合はapiResourceを使用します。
Route::apiResource('users', 'UsersController');
これで、index,store,show,update,destroyが使用できるようになります。
複数のコントローラーをまとめて指定する場合はapiResourcesを使用します。
Route::apiResources([
'tasks' => 'Api\TaskController',
'users' => 'Api\UserController'
]);
api用のデータ整形、リレーションデータの追加。
apiCollectionの作成
php artisan make:resource UserCollection
php artisan make:resource User
JsonResouseに追加したい
public function toArray($request)
{
$data = parent::toArray($request);
$data["staff"] = StaffResource::collection($this->staff);
$data["doctor"] = DoctorResource::collection($this->doctor);
return $data;
}
apiのセキュリティ 自分のデータ以外は編集できてはいけない
Policyの設定を行う。
$this->authorize('update', $user);
APIで返却するJSONを共通フォーマットにしたい
Modelでバリデーションをする
中間テーブルを通した多対多リレーション
Tips: primarykeyを使わない場合
https://www.yuulinux.tokyo/15552/#i-5
多対多リレーション時のデータ修正・追加
例えばusers-> user_role -> roles というふうに
中間テーブルを経由してroleを管理している場合、roleを変更したい場合は
roleテーブルのidを配列で渡すだけで良い
roles = [1,2,3]
$user->roles()->sync($request->roles);
神か!!!
この辺から自力で調べつつ、公式リファレンスを読めば大体構築イメージがつかめるようになってきました。
概ね3日でLaravelの基本は理解できたと言えます。
素晴らしいフレームワークですが、レイヤーも多いため、基本のSQLの知識も必要、PHPの基礎も。
やっぱ基礎って大事だな、と思いました。