Слияние и сортировка двух редких коллекций?

У меня есть две коллекции, и я хочу объединить ее с одной переменной (конечно, с упорядочением на один столбец - 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

EDIT:

Моя модель билета выглядит так:

<?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');
    }
}
?>

Ответы

Ответ 1

Вы не сможете получить то, что хотите.

В общем, слияние должно быть простым с $collection->merge($otherCollection); и сортироваться с $collection->sort();. Однако слияние не будет работать так, как вы хотите, из-за отсутствия уникальных идентификаторов и столбца "Таблица", который вы хотите, вам нужно будет сделать это вручную.

И они на самом деле собираются быть коллекциями разных типов, я думаю (один из основанных на Eloquent\Model будет Eloquent\Collection, а другой будет стандартным Collection), что может вызвать собственные проблемы, Таким образом, я бы предложил использовать DB:: table() для обоих и увеличить результаты с помощью столбцов, которые вы можете контролировать.

Что касается кода для этого, я не уверен, так как я не делаю много работы низкого уровня в Laravel, поэтому не знаю, как лучше всего создавать запросы. В любом случае, только потому, что это похоже на то, что вы начинаете испытывать боль, чтобы справиться с этим двумя запросами и слиянием PHP, я бы предложил сделать все это в одном запросе БД. Он будет выглядеть более аккуратным и, возможно, более удобным:

В 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::, я думаю, что до вас.

Ответ 2

Небольшое обходное решение для вашей проблемы.

$posts = collect(Post::onlyTrashed()->get());
$comments = collect(Comment::onlyTrashed()->get());

$trash = $posts->merge($comments)->sortByDesc('deleted_at');

Таким образом вы можете просто объединить их, даже если есть дубликаты идентификаторов.