0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LaravelのEloquentで取得できるコレクションからキーを除外する

Posted at

概要

LaravelのEloquentでデータを取得した際、getメソッドを使用する際、コレクション形式でデータが取得できます。
getメソッドで取得したデータには、キーととコレクション値が含まれます。
しかし、whereInwhereNotIn節を使用する場合などで、コレクション値のみを取得したい場合、pluckメソッドを使用することで、直接コレクション値を取得できるようになります。

Laravelで通知の未読数を取得する際、既読の通知レコードを取得し、通知一覧から既読ではない通知を取得することで、通知の未読数を取得しています。

例で使用しているDB定義

通知テーブル(trn_notice)

No 論理名 物理名 データ型
1 ID id uuid
2 作成日時 created_at timestanp
3 更新日時 updated_at timestanp
4 削除日時 deleted_at timestanp
5 利用者マスタID user_id uuid
6 配信日時 stream_date timestanp
7 通知タイトル notice_title varchar(256)
8 通知内容 notice_contents text

通知既読テーブル(trn_notice_read)

No 論理名 物理名 データ型
1 ID id uuid
2 作成日時 created_at timestanp
3 更新日時 updated_at timestanp
4 削除日時 deleted_at timestanp
5 利用者マスタID user_id uuid
6 既読通知ID read_notice_id uuid

pluckメソッドを使用せずに、処理を記載すると以下のようになります。

NoticeController.php
/** 
 * 通知の未読数を取得する
 * @return int $unread 未読件数
 */
public function getUnread() {
    // JWTからログインしている利用者IDを取得
    $userId = Auth::id();
    // 既読済みの通知ID
    $readNoticeId = [];

    try {
        // 既読済みの通知を取得
        $reads = TrnNoticeRead::where('user_id', '=', $userId)
        ->get();

        // 既読の通知IDが存在する場合ループし、通知IDを配列に保持
        if (!$reads->isEmpty()) {
            foreach($reads as $read) {
                $readNoticeId[] = $read->read_notice_id;
            }
        }

        // 未読の通知数を取得
        $unread = TrnNotice::where('user_id', '=', $userId)
        // 既読ではない通知
        ->whereNotIn('id', $readNoticeId)
        ->orderBy('stream_date', 'desc')
        ->count();

        return $unread;
    } catch (Exception $exception) {
        \Log::error($exception);

        throw $exception;
    }
}

既読済みの通知をgetメソッドで取得した場合、以下のようにデータが取得できます。

[
    {
        "id": 85f4736b-a909-a63a-9428-79805804f248,
        "created_at": "2023-01-20 12:00:00.000",
        "updated_at": "2023-01-20 12:00:00.000",
        "deleted_at": null,
        "user_id": c56328f6-be77-9dd5-2f72-a5b8a136e654,
        "read_notice_id": ffeb35c4-311f-c52e-86ba-e79225e2811a,
    }, {
        "id": bc65cc1b-91dc-7fde-5afc-9d1450d63407,
        "created_at": "2023-01-20 12:00:00.000",
        "updated_at": "2023-01-20 12:00:00.000",
        "deleted_at": null,
        "user_id": b796948d-3a3e-8d89-f2a9-31845b15e1ff,
        "read_notice_id": 674ad489-10a6-e6fd-9c8f-6b738f744934,
    }
]

しかし、whereNotIn節を使用するには、[ffeb35c4-311f-c52e-86ba-e79225e2811a, 674ad489-10a6-e6fd-9c8f-6b738f744934]形式にする必要があるため、foreachで配列に挿入する処理を行う必要があります。
foreachで取得したコレクションをループさせ、別配列にプッシュするとなると、通知件数が多くなるにつれてどんどん処理時間が増えていってしまいます。

そこで、pluckメソッドを使用することで、配列に既読した通知のIDが入った状態で取得できるようになります。

NoticeController.php
/** 
 * 通知の未読数を取得する
 * @return int $unread 未読件数
 */
public function getUnread() {
    // JWTからログインしている利用者IDを取得
    $userId = Auth::id();

    try {
        // 既読済みの通知を取得
        $reads = TrnNoticeRead::where('user_id', '=', $userId)
        // コレクション値のみを返す
        ->pluck('read_notice_id');

        // 未読の通知数を取得
        $unread = TrnNotice::where('user_id', '=', $userId)
        // 既読ではない通知
        ->whereNotIn('id', $readNoticeId)
        ->orderBy('stream_date', 'desc')
        ->count();

        return $unread;
    } catch (Exception $exception) {
        \Log::error($exception);

        throw $exception;
    }
}

pluckメソッドを使用することで、クエリで処理するため、通知件数が増えても高速で未読数を取得することができるようになります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?