合并并排序两个Eloquent集合


Merge and Sort two Eloquent Collections?

我有两个Collections,我想把它合并到一个变量中(当然,按一个collomn-created_at排序)。我该怎么做?

我的控制器看起来:

$replies = Ticket::with('replies', 'replies.user')->find($id);
$logs = DB::table('logs_ticket')
        ->join('users', 'users.id', '=', 'mod_id')
        ->where('ticket_id', '=', $id)
        ->select('users.username', 'logs_ticket.created_at', 'action')
        ->get();

我的输出例如:

回复:

ID | ticket_id | username | message | created_at
1  | 1         | somebody | asdfghj | 2014-04-12 12:12:12
2  | 1         | somebody | qwertyi | 2014-04-14 12:11:10

日志:

ID | ticket_id | username | action | created_at
1  | 1         | somebody | close  | 2014-04-13 12:12:14
2  | 1         | somebody |  open  | 2014-04-14 14:15:10

我想要这样的东西:

ticket_id | table | username | message | created_at
1         |replies| somebody | asdfghj | 2014-04-12 12:12:12
1         | logs  | somebody |  close  | 2014-04-13 12:12:14
1         | logs  | somebody |  open   | 2014-04-14 11:15:10
1         |replies| somebody | qwertyi | 2014-04-14 12:11:10

编辑:

我的票证模型看起来是:

<?php
class Ticket extends Eloquent {
    protected $table = 'tickets';
    public function replies() {
        return $this->hasMany('TicketReply')->orderBy('ticketreplies.created_at', 'desc');
    }
    public function user()
    {
        return $this->belongsTo('User');
    }
}
?>

一个解决问题的小方法。

$posts = collect(Post::onlyTrashed()->get());
$comments = collect(Comment::onlyTrashed()->get());
$trash = $posts->merge($comments)->sortByDesc('deleted_at');

这样,即使有重复的ID,也可以将它们合并。

你不可能轻易得到你想要的东西。

通常情况下,使用$collection->merge($otherCollection);合并应该很容易,而使用$collection->sort();排序应该很容易。但是,由于没有唯一的ID,合并无法按您希望的方式进行,并且您需要的"表"列必须手动进行。

此外,它们实际上都将是不同类型的集合我认为(一个基于Eloquent'Model的集合将是Eloquent'Collection,另一个是标准Collection),这可能会导致其自身的问题。因此,我建议两者都使用DB::table(),并使用可以控制的列来增强结果。

至于实现这一点的代码,我不确定,因为我在Laravel中没有做很多底层DB工作,所以不知道创建查询的最佳方式。不管怎样,因为用两个查询和一些PHP合并来管理这件事看起来很痛苦,所以我建议在一个DB查询中完成所有操作。它实际上看起来更整洁,可以说更易于维护:

您需要的SQL是这样的:

SELECT * FROM
(
    SELECT
        `r`.`ticket_id`,
        'replies' AS `table`,
        `u`.`username`,
        `r`.`message`,
        `r`.`created_at`
    FROM `replies` AS `r`
    LEFT JOIN `users` AS `u`
        ON `r`.`user_id` = `u`.`id`
    WHERE `r`.`ticket_id` = ?
) UNION (
    SELECT
        `l`.`ticket_id`,
        'logs' AS `table`,
        `u`.`username`,
        `l`.`action` AS `message`,
        `l`.`created_at`
    FROM `logs` AS `l`
    LEFT JOIN `users` AS `u`
        ON `l`.`user_id` = `u`.`id`
    WHERE `l`.ticket_id` = ?
)
ORDER BY `created_at` DESC

这是非常不言自明的:执行两个查询,返回相同的列,UNION它们,然后在MySQL中对结果集进行排序。希望它(或者类似的东西,因为我不得不猜测你的数据库结构)能为你工作。

至于将其转换为Laravel DB::风格的查询,我想这取决于您。