4

I am new to Laravel/PHP, and I am doing my personal "toy project" and I met an issue that I have been Googling for a long time. However, I cannot figure out a perfect solution.

The problem is that, I have two collections $questions and $answers, and I would like to merge them to a big one collection. Here are the structure/example for these two collections

$questions:

questions: [
{
    id: 1,
    title: "Why do PHP developers love Laravel? What are the things that distinguish Laravel from other PHP frameworks?",
    desc: null,
    user_id: 2,
    created_at: "2018-07-15 06:45:57",
    updated_at: "2018-07-15 06:45:57",
    status: "ok"
}
]

$answers:

answers: [
{
    id: 2,
    content: "Laravel is usually considered as PHP on rails! It is amazing!",
    user_id: 2,
    question_id: 1,
    created_at: "2018-07-15 07:11:39",
    updated_at: "2018-07-15 07:11:39"
},
{
    id: 1,
    content: "PHP is the best programming language in the world! [smile]",
    user_id: 1,
    question_id: 1,
    created_at: "2018-07-15 07:02:21",
    updated_at: "2018-07-15 07:05:12"
}
]

I have tried merge command and I got something like this:

$data = $questions->merge($answers);
$data = $data->sortByDesc(function($item) {
    return $item->created_at;
});




data: [
{
    id: 2,
    content: "Laravel is usually considered as PHP on rails! It is amazing!",
    user_id: 2,
    question_id: 1,
    created_at: "2018-07-15 07:11:39",
    updated_at: "2018-07-15 07:11:39"
},
{
    id: 1,
    content: "PHP is the best programming language in the world! [smile]",
    user_id: 1,
    question_id: 1,
    created_at: "2018-07-15 07:02:21",
    updated_at: "2018-07-15 07:05:12"
}
]

Noticed that, in $data, I cannot find the question anymore, but I do wanna it in the $data collection. Besides, I have tried commands like union, push, put, none of them gives a satisfying solution.

Is there something wrong with my code or I cannot do this in PHP at all? In case there are bugs in my codes, I have pasted here.

public function timeline()
{
    list($limit, $skip) = paginate(rq('page'), rq('limit'));

    /* Retrieve questions, $questions is like I pasted above*/
    $questions = question_init()
        ->limit($limit)
        ->skip($skip)
        ->orderBy('created_at', 'desc')
        ->get();

    /* Retrieve answers, $answers is like I pasted above */
    $answers = answer_init()
        ->limit($limit)
        ->skip($skip)
        ->orderBy('created_at', 'desc')
        ->get();        

    /* Merge questions and answers */
    $data = $questions->merge($answers);

    /* Sort by Created time */
    $data = $data->sortByDesc(function($item) {
        return $item->created_at;
    });

    $data = $data->values()->all();

    return succ(['questions' => $questions, 'answers' => $answers, 'data' => $data]);
}
3
  • 2
    Have you tried concat()? Commented Jul 26, 2018 at 10:12
  • Yes, I have tried concat() and any function with a meaning like adding something together Commented Jul 26, 2018 at 21:25
  • concat() is working for me. Commented Nov 7, 2020 at 9:48

2 Answers 2

17

This is because Eloquent Collections which extend Support Collections use a dictionary that is keyed by the key of the Model instances contained when merging. They have special functionality specifically for working with a collection of models. Usually you don't merge Eloquent Collections like this because of that.

You can get a Support Collection from one of the Eloquent Collections and merge the other collection into it.

$collection->toBase() will give you a Illuminate\Support\Collection from your Illuminate\Database\Eloquent\Collection.

You can try:

$data = $questions->toBase()->merge($answers);
Sign up to request clarification or add additional context in comments.

1 Comment

This is a super important difference. I was using keyBy() on two different Eloquent Collections and then using merge() on them, and it absolutely did not care about my use of keyBy(). Could not figure it out until I read this answer.
1

Use can use:

Edit

$merged = array_merge(['questions' => $questions], ['answers' => $answers])

it will return array merged with correct key for each collection.

1 Comment

Thanks! In the next step, I would like to sort by created time, however, this statement gives an error. Anyway, thanks, now I have another way to do something like merge()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.