【发布时间】:2020-11-14 14:31:54
【问题描述】:
我有 3 个模型:用户、付款和日志。一个用户有很多付款,用户和付款都有很多日志。
用户模型
class User
{
public function payments()
{
return $this->hasMany('Payment', 'user_id');
}
public function logs()
{
return $this->morphMany(Log::class, 'loggable');
}
}
用户表
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`email_verified_at` timestamp NULL DEFAULT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
支付模式
class Payment
{
public function user()
{
return $this->belongsTo('User', 'user_id');
}
public function logs()
{
return $this->morphMany(Log::class, 'loggable');
}
}
付款表
CREATE TABLE `payments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`status` varchar(50),
`amount` int(11) NOT NULL,
`collection_date` date NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`user_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_payments_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
日志模型
class Log
{
public function loggable()
{
return $this->morphTo();
}
}
日志表
CREATE TABLE `logs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`loggable_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`loggable_id` bigint(20) unsigned NOT NULL,
`old_values` text COLLATE utf8mb4_unicode_ci,
`new_values` text COLLATE utf8mb4_unicode_ci,
`user_id` bigint(20) unsigned DEFAULT NULL, /* the user that made the change, if any */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Log 模型存储对任何其他模型所做的所有更改(这是一种多态关系),因此如果用户更改其名称,Log 模型将存储旧名称和新名称。这同样适用于支付:如果支付状态发生变化,Log 模型将有一条新记录,其中包含旧状态和新状态。
我需要显示按日期排序的特定用户的所有日志记录的分页列表。所以我的代码是:
$user = App\User::find($id);
$allLogs = $user->logs();
// Now I need to join (I'm using union) both sets of logs
$allLogs->union($user->payments->logs());
但是,由于一个用户可以有多个付款,$user->payments 返回一个集合,因此不再是一个查询构建器/雄辩对象,当我尝试调用 ->logs() 时它失败了。
$user->payments()->logs() 也不起作用,因为$user->payments() 返回一个HasMany 对象,而->logs() 方法不存在。
我试图避免单独获取Log 的每个集合,然后使用 php 处理它们(最好将该任务委托给 MySql)。
我相信可以做到,因为我可以在MySql上写查询:
select l.*
from payments p
join logs l on p.id = l.loggable_id and l.loggable_type = 'App\\Payments'
where p.user_id = SOMEUSERID
提前致谢
【问题讨论】:
-
您能否添加这些表的结构,以便我们可以看到键以及关系是如何设置的
-
@lagbox,感谢您的回复。我刚刚添加了 sql 代码和模型