首發,laravel最優雅的分表、關聯、分頁查詢,手冊方法的熟練運用。

前幾天寫了一遍關於laravel分表關聯的查詢,可是我我的以爲還不算完美,因而今天從新看了一下laravel模型的底層代碼,終於寫出我暫時以爲最滿意的代碼-laravel風格,簡潔、優雅是核心。php

下面直接上demo代碼,主要是3個表,一個用戶表,一個是用戶送禮表,送禮表按月分表laravel

user表
id用戶ID
nickname暱稱sql

<?php

namespace App\Models;

use Eloquent;

class User extends Eloquent
{
  
}

send_gift_2017_07,send_gift_2017_08 送禮表
id自增主鍵
user_id用戶ID
worth禮物價值
uper_id主播ID(也是用戶表的)
created_at送禮時間數據庫

<?php

namespace App\Models;

use Eloquent;

class SendGift extends Eloquent
{
    //關聯用戶表,外鍵是user_id
    public function user()
    {
        return $this->belongsTo(User::class);
    }
    
    關聯用戶表 外鍵是uper_id
    public function uper()
    {
        return $this->belongsTo(User::class);
    }
}

如今作一個輸入開始日期和結束日期查看用戶的送禮記錄而且分頁。性能

<?php

namespace App\Http\Controllers;

use App\Models\SendGift;
use DB;
use Carbon\Carbon;

class IndexController extends Controller
{
    public function index()
    {

        // 開始日期,和日期有關的,都建議用內置的carbon處理,很是好用,並且簡潔
        $start = Carbon::parse(request('start'));
        // 結束日期
        $end = Carbon::parse(request('end'));
        // 查詢集合
        $queries = collect();
        
        // 循環比較年月,添加每一張表的查詢
        for ($i = $start->copy(); $i->format('Y-m') <= $end->format('Y-m'); $i->addMonth()) {
            $queries->push(
                DB::table("send_gift_{$i->format('Y_m')}")
                    // 建議都用select查詢字段,SQL儘量的優化性能
                    ->select('user_id', 'worth', 'uper_id', 'created_at')
                    ->whereBetween('created_at', [$start, $end->tomorrow()])
            );
        }

        // 出列一張表做爲union的開始
        $unionQuery = $queries->shift();
        // 循環剩下的表添加union
        $queries->each(function ($item, $key) use ($unionQuery) {
            $unionQuery->unionAll($item);
        });

        // 設置臨時表的名稱,添加臨時表,順序不能反過來,不然用關聯約束會找不到表
        $lists = with(new SendGift)->setTable('union_send_gift')
            // 添加臨時表
            ->from(DB::raw("({$unionQuery->toSql()}) as union_send_gift"))
            // 合併查詢條件
            ->mergeBindings($unionQuery)
            // 關聯約束,不在用戶表的不用查出來
            ->has('user')
            // 按時間倒序
            ->orderBy('created_at', 'desc')
            // 分頁
            ->paginate();

        // 加載關聯關係
        $lists->load([
            'user' => function ($query) {
                // 關聯查詢也要優化sql
                $query->select('id', 'nickname');
            },
            'uper' => function ($query) {
                $query->select('id', 'nickname');
            }
        ]);

        // 測試結果
        $lists->each(function ($item, $key) {
            echo "用戶:{$item->user_id}-{$item->user->nickname}在{$item->created_at->toDateTimeString()}送出了價值{$item->worth}元的禮物給主播:{$item->uper_id}-{$item->uper->nickname}<br>";
        });
        
    }
}

而後咱們看看SQL。測試

clipboard.png

關聯查詢用了渴求式加載,就能有效減小SQL的條數,保證數據庫的性能。優化

相關文章
相關標籤/搜索