PHP

Laravel Eloquent Collectionまとめるぜ!

Laravel

 

 

 

ORMさんとのお付き合い

  • 利用するメソッドの戻り値をすべて把握して処理
  • パラメータ配列の添字が空やNULLを考慮
  • get()やfind()でオブジェクトが存在しない時の考慮

 

first()やget()でオブジェクトが存在しない時の考慮

大事なことです🐱

PHP 判定チェック isset empty if is_null

 first()の場合

 

よくないパターン

$user_instance = new User();
$user = $user_instance->find($user_id)->first();
$user_name = $user->name;

$userのオブジェクトがnullの場合にエラーになる

 

職人

$user_instance = new User();
$user = $user_instance->find($user_id)->first();
if (!is_null($user)) {
    $user_name = $user->name;
}
もしくは三項演算子で判定する
$user_name = (is_null($user)) ? "" : $user->name;

 

get()の場合

toArray()で配列に変換にしてからコレクションが空かを判定してからプロパティを参照しよう

職人

 

$user_instance = new User();
$users = $user_instance->where('year', =, 20)->get();
if (!$users->isEmpty()) {
    $user_names = [];
    foreach ($users as $user) {
        $user_names[] = $user->name;
    }
}

// 例で示す為にくどくなっています。Collectionが空の場合はforeach()の中が実行されないので本来はif (!$users->isEmpty()) は省略できる…🐱

または

$user_instance = new User();
$users = $user_instance->where('year', =, 20)->get();
if (!empty($users->toArray())) {
    $user_names = [];
    foreach ($users as $user) {
        $user_names[] = $user->name;
    }
}

ここです🐱

if (!empty($users->toArray())) {

Collectionクラスはforeachで取得できるよ

コレクションを集計処理で使う場合は注意

  • コレクションで集計などで計算する場合もtoArray()で配列化してから、集計処理をすると良い。
  • コレクションのデータ量は大きいのです。配列化すると軽量になります🐱

 

よく使うやつまとめていく

value()

カラムを指定して値だけ取り出したい場合 value()

$user_score = self::where('user_id', $user_id)
             ->where('year', $setYear)
             ->where('period', $setPeriod)
             ->value('score');

return $user_score;

scoreの点数だけ取り出す

 

first()

先頭の1件をCollectionで取得

$user_score = self::where('user_id', $user_id)
             ->where('year', $setYear)
             ->where('period', $setPeriod)
             ->first();

return $user_score;
  • first()やget()では値やレコードがないとエラー吐くので注意

 

where()

$section_kpi = new SectionKpi();
$section_kpi = $section_kpi->where('section_kpi_id', $id)->first();
if (is_null($section_kpi)) {
    abort(404, "部署の目標id:{$id}のデータが存在しません");
}
  • find()を使わず、where() +主キーを指定する形でこっちをよく使う。
    find()は空ぶった時の処理を考慮する必要があるので、findOrFail()かwhere() + 主キーが良い
  • nullだった場合の処理を忘れずに行うこと。
  • is_nullでオブジェクトがあるか判定できる

 

whereIn()

SQLだとこういう形で利用するあれです。

SELECT
  *
FROM
  テーブルA
WHERE tableA.id IN (
  SELECT
    tableA.id
  FROM
    テーブル名B
  WHERE tableB.cost > 1000
)

whereIn()を使う

$company_ids = [1, 3, 4, 6];
$staff_instance = new Staff();
$staffs = $staff_instance->whereIn('company_id', $company_ids)->where('type', 'engineer');

例) $sectionNames配列でのwhereIn()

return $query->select(
                        'tb_member.member_id',
                        'tb_member.fullname',
                        'tb_member.skill',
                        'tb_section.section_name'
                     )
                     ->leftjoin('tb_section', function ($join) {
                         $join->on('tb_section.section_id', '=', 'ud.section_id')
                             ->where('tb_section.deleted', '=', '0');
                     })
                     ->when(isset($sectionNames), function($query) use ($sectionNames) {
                         return $query->whereIn('section_name', $sectionNames); // ←●ここ
                     })
                     ->get();

when()と組み合わせ。whenの場合はreturnが必要になるので忘れずに🐱

 

whereHas()

リレーション先のテーブルに条件をつけて抽出したい時に利用します。

例) departments.department_id = 99に所属するusersテーブルのデータを取得する

    $users = \App\Models\User::whereHas('Department', function($query){
                        $query->where('department_id', 99);
                    })->get();

 

is_nullでのオブジェクト判定

        $sectionKpi = new SectionKpi();

        // 予算を取得
        $date = Carbon::now();
        $now_year = $date->year;
        $now_period = ($date->month < 7) ? 'first' : 'second';
        $my_section = $user->find($user_id)->departs()->first();
        $my_sectionId = $my_section->section_id;
        $my_section_now_kpi = $section_kpi->where('section_id', $my_section_id)
                        ->where('year', $now_year)
                        ->where('period', $now_period)
                        ->first();

        $my_section_now_kpi_buffer = is_null($my_section_now_kpi) ? 0 : $my_section_now_kpi->budget; ←●
$mySectionNowKpi->budget

のようなプロパティを表示するものは、is_null()などでオブジェクトの有無を判定してから利用します。

 

戻り値

  • オブジェクトが存在する場合
    Builderクラスを返却する
  • オブジェクトが存在しない場合
    null

 

複数指定もできる

$sectionKpi->where('section_id', "=", $requestParams['section_id'])
                              ->where('user_id', "=", $requestParams['user_id'])
                              ->where('year', "=", $requestParams['year'])
                              ->get();

 

WHEREで一気に更新をかける場合の考慮

  • 西暦2000年生まれのグループのユーザにかける場合
    ->where(‘year’, “=”, $requestParams[‘year’])
  • 西暦2000年生まれのグループのユーザの名前をそれぞれを一気に更新をかける場合
    ループをかけて
    ->where(‘user_id’, “=”, $requestParams[‘user_id’])
    ->where(‘year’, “=”, $requestParams[‘year’])

誤った更新が起きないように更新先テーブルのidを指定する

 

find() idで抽出

$depart = new Depart();
$department = $depart->find($request_params['department_id']);
  • 最後に->first()や->get()はいらない
  • SELECTする場合は使いやすい
  • UPDATEやDELETEでは使いにくい
    ・where()を使う
    のがベター

戻り値

  • ある場合
    Modelオブジェクト
  • ない場合
    null

 

nullの場合のケア

        $mySection = $user->find($userId)->sections()
                        ->where('year', $nowYear)
                        ->where('period', $nowPeriod)
                        ->where('tb_section.deleted', '=', 0)
                        ->whereNotNull('section_parent_id')
                        ->orderBy('created', 'desc')
                        ->first();

        if (isset($mySection)) {
            $mySectionId = $myDepart->section_id;
            $mySectionNowKpi = $sectionKpi->where('section_id', $mySectionId)
                                ->where('year', $nowYear)
                                ->where('period', $nowPeriod)
                                ->first();
        }

 

ポイント

        if (isset($mySection)) {
            $mySectionId = $myDepart->section_id;

$mySectionがnullではないことを確認してから、プロパティを参照すること

 

findOrFail() idで抽出、見つからない場合は例外を投げる

idを指定することで抽出し、idが見つからない場合は例外を投げる

class UserScoreController extends Controller
{
    public function deleteUserkpiById(Request $request)
    {
        $user_score_id = $request->user_score_id;
        $userScore = new UserScore();

        try {
            $result = $userScore->findOrFail($user_score_id)->delete();
        } catch (ModelNotFoundException $e) {
            $result = 'user_score.id not found';
            return response()->json(
                $result,
                404,[],
                JSON_UNESCAPED_UNICODE
            );
        }
    }
}

 

 

例)

        try {
            if (!isset($request['userId'])) {
                return 'ユーザIDが見つかりません。<br/>
                  <a href="/">ホームに戻る</a>';
            }
            $userId = (int) $request['userId'];

            $user = Users::findOrFail($userId);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
          return 'ユーザIDが見つかりません。<br/>
                  <a href="/home">ホームに戻る</a>';
        }
  • Request $requestにuserIdがあるかチェックする(バリデーションで対応がベター)
  • findOrFailで例外判定する

 

戻り値

  • findOrFail()で該当するレコードが見つからない場合、ModelNotFoundExceptionに例外を投げてくれる。

 

get()

  • 戻り値はCollectionクラス。foreachでそれぞれのModelオブジェクトを取得できる
  • オブジェクトがあるかの判定は$collection->isEmpty()
    empty($collection->toArray())
    toArray()からempty()でも判定できる

 

戻り値

  • Collectionクラス

 

all()

すべて取得する

戻り値

  • Collectionクラス

 

論理削除の扱い

Laravel 論理削除を戻す、物理削除

with()

リレーション先のデータを取得する時はこれ!

 

<?php

namespace App\Http\Models;

use Illuminate\Database\Eloquent\Model;
use App\Http\Models\Users;
use Carbon\Carbon;

class UserScore extends Model
{
・・・

    public function users()
    {
        return $this->belongsTo(Users::class, 'user_id', 'user_id');
    }

}

users()メソッドを定義しておいて

 

    $user = new User();
    $userSections = $user::with('userSections') ←●これ
        ->where('section_id', '=', $user->section_id)
        ->get();
  • UserScoreモデルのリレーション先のUserモデルのデータを取得していく!
  • リレーション先から取得する場合はこれでOK!

 

ビューでリレーション先を出力する例

<?php isset($user->userSections) ? print $user->userSections->section_name : null ?>
  • リレーションが取れているオブジェクトかどうか確認してから、プロパティを参照する。
  • オブジェクトがなければnullを返す配慮が必要

 

 

 

with()で複数のリレーションやネスと先も取得できるぞ

@see

 

save() 保存や更新を行う

レコードのInsertやupdateを行います。そのままリクエストを入れていくのでセキュリティリスクがあります。

$fillable, $guardedを指定しましょう。

  • $fillable … ホワイトリスト。指定したカラムのみにCreateによって代入を許可する
  • $guarded … ブラックリスト。指定したカラムにはCreateによって代入させない。

これを指定しましょう

 

フォームで受け取ったリクエストに値を追加する場合

            $request_params = $request->all();

            if (isset($request->day[0]) && is_array($request->day)) {
                $manDay = array_map('intval', $request->day); // int型に配列を変換
                $request_params['child_day'] = array_sum($childDay);
            }
            $project->fill($request_params);
            $project->save();

一旦$request->all()で変数に受け取ってから->fill()を経由して->save()を行います🐱

 

新規登録する

$section = new Section();
$section->fill($request_params);
$section->save();

 

 

更新する

更新はidをfindOrFail()で指定してModelを取ってきて、こちらもsave()で更新する

$section = Section::findOrFail($request_params['section_id']);
$section->fill($request_params)->save();

 

 

delete() 削除する

 

        $userScore = new UserScore();
        $deleteUserScoreCount = $userScore->where('id', $request->user_score_id)->delete();

        if ($deleteUserScoreCount > 0) {
            $result = 'true';
            return response()->json(
                $result,
                200,[],
                JSON_UNESCAPED_UNICODE
            );
        }

        $result = 'false';
        return response()->json(
            $result,
            404,[],
            JSON_UNESCAPED_UNICODE
        );

 

戻り値

  • 削除したレコード数を返す

 

orderBy()

  • orderBy(‘カラム名’, ‘desc’)
    降順で取得…値が大きい順に取得
  • orderBy(‘カラム名’, ‘asc’)
    昇順で取得…値が小さい順に取得

例) 部署の作成日が新しい順に取得

$mySection = $user->find($userId)->sections()->orderBy('created', 'desc')->get();
  • ->get()で複数取得
  • ->first()で1つ取得

 

コレクション Collection

 

pluck() 特定のカラムのみ抽出する

$section_id = (int) $request['section_id'];
$section = new Section();

$section_staffs = $section->find($section_id)->users()->pluck('full_name', 'tb_user.user_id');

 

map()による加工

Laravel map() Collectionを加工しよう

 

filter()による抽出

Laravel filter() でCollectionから抽出しよう

 

テスト

  • その関数が取得する値が存在しない場合のチェック
    →nullや0を返しているか?

テストすること

 

 

少しずつ追加していくのだ🐹

 

Amazonおすすめ

iPad 9世代 2021年最新作

iPad 9世代出たから買い替え。安いぞ!🐱 初めてならiPad。Kindleを外で見るならiPad mini。ほとんどの人には通常のiPadをおすすめします><

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)