2014-04-15 2 views
14

나는 2 개의 콜렉션을 가지고 있는데, 하나의 변수로 병합하고 싶다. (물론, 하나의 콜럼으로 주문하기 - created_at). 어떻게해야합니까?두 개의 숭배 컬렉션을 병합하고 정렬 하시겠습니까?

답글 : :

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 

그리고 나는 이런 식으로 뭔가를 원하는

$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(); 

내 출력 예를 찾습니다

내 컨트롤러

는 것을 보인다 :

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

DB :: table은 stdObjects 배열을 반환하므로 결과가 일치하지 않거나 Eloquent Collection/Model로 변환해야합니다.더 나은 방법으로 답을 얻으려면 릴레이션을 사용하여 모델을 붙여 넣으십시오. –

+0

@deczo 티켓 모델을 추가했습니다. – Siper

+0

로그는 어떻게됩니까? –

답변

19

:

내 티켓 모델 것으로 보인다.

일반적으로 $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:: -style 쿼리로 번역 할 때, 나는 당신에게 달려 있다고 생각합니다.

18

문제의 해결 방법은 조금 있습니다.

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

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

중복 된 ID가 있어도이 방법으로 병합 할 수 있습니다.

+2

비효율적이지만 핀치로 일합니다! – alexw

+0

왜 작동합니까? 모든 collect() 메소드는 새로운 Collection을 생성합니까? – Robert

+3

Eloquent는'Eloquent Collection'을 반환하고 collect는 정상적인'Collection'을 반환합니다. '정상적인'컬렉션에는 'Eloquent Collection'과 다른 메소드가 있습니다. –

관련 문제