Laravel体験記: 不安が多い中はじめて自力で作ってみたControllerの一部
Laravelの学習をしていたのですが、勉強が嫌いすぎて力尽きてしまいました。
とりあえずそれっぽくは扱えるんじゃないかな?というレベルまで勉強したので、実践に入りたいと思います。
つくったもの
ゲームアプリ用の汎用ランキングシステムです。
ユニークなアプリ側のUIDを渡してあげれば、スコアと順位がjsonで返却されるようにしてみました。
気になったこと
- データが存在しなかったとき、returnしちゃったけどいいのだろうか。いわゆるエラーハンドリングが雑。
- コントローラー側でwhereしまくってて、検索ロジックが密結合してる気がする。普通なのだろうか?個人的には別クラスにまとめたいのだが、その場合はどこに置けばいいのだろうか・・・。
- ORMが組み立てるSQLって、インデックスに沿ったSQLになっているのだろうか・・・。
補足
- app_id = 汎用なので、いろんなアプリから叩かれる想定。
- label = 汎用なので、いろんなカテゴリのスコアがある想定。
もしよかったら
ここおかしいよ、こうしたらいいよ、という助言ください・・・。
ソースコード
class RankingController extends Controller{
public function userData(Request $request){
$app_id = $request->app_id;
$user_uid = $request->user_uid;
$user_data = UserData::where('app_id', $app_id)->where('user_uid', $user_uid)->first();
if(!$user_data){
// 1.データがなかった場合のエラー処理ってこれでいいのだろうか・・・。とりあえず-1を返してみる
return ['status_code' => -1];
}
$user_id = $user_data->user_id;
$label = $request->label ? $request->label : "default";
// 2. コントローラーに検索ロジック入りすぎじゃないかしら・・・。
$ranking_data = RankingData::where('app_id', $app_id)->where('label', $label)->where('user_id', $user_id)->first();
$score = 0;
if($ranking_data){
$score = $ranking_data->score;
}
$sort = '>';
if($request->sort == 'ASC'){
$sort = '<';
}
$rank = RankingData::where('app_id', $app_id)->where('label', $label)->where('score', $sort, $score)->count() + 1;
$res = [
'status_code' => 1,
'user_id' => $user_id,
'label' => $label,
'score' => $score,
'rank' => $rank,
];
return $res;
}
}
さらに補足
インデックスも含めたDB構造です。
DB構造もあんまり自信ないです。データが大量になる予定なので、インデックスを考慮したORMの実装になっているか不安です。
first( )
で最初のデータを取得していますが、もしなければFailするfirstOrFail( )
というメソッドがありますので、そちらを利用してみてはいかがでしょうか?おっしゃる通り、データ取得のロジックが結構大きいですね。
考えられる解決策としては以下2つですね
[1] データベース設計の見直し
もう少し簡単にランキングデータを取得できないか、そもそもの設計から見直してみてはいかがでしょうか?
例えば、特定のゲームをランキングデータ集めるのに、
user_id
って必要なのか?などです。(これは実際に作っているサービス概要がわかっていないので、検討違いかもしれません)
[2]Modelの中にScopeを登録
Scopeとはデータベースにクエリを発行するときの「制約・ルール」です。
これを定義することによって、Controller側をもう少し簡単に書くことができると思います。
https://laravel.com/docs/6.x/eloquent#query-scopes
上記のサイトを参考にしてみてください
このメソッドのレスポンスは連想配列のような気がします。
JSONで返したい場合は、以下のサイトを参考にしてみてください。
https://laravel.com/docs/6.x/responses#json-responses
ありがとうございます!