前几天写了一遍关于laravel分表关联的查询,但是我个人觉得还不算完美,于是今天重新看了一下laravel模型的底层代码,终于写出我暂时觉得最满意的代码-laravel风格,简洁、优雅是核心。
下面直接上demo代码,主要是3个表,一个用户表,一个是用户送礼表,送礼表按月分表
user表
id用户ID
nickname昵称
<?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。
关联查询用了渴求式加载,就能有效减少SQL的条数,保证数据库的性能。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。