Zhenye Na
Zhenye Na

Reputation: 433

How to merge two collections without dropping (losing) keys in Laravel PHP framework?

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]);
}

Upvotes: 4

Views: 4468

Answers (2)

Mako
Mako

Reputation: 242

Use can use:

Edit

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

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

Upvotes: 1

lagbox
lagbox

Reputation: 50561

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

Upvotes: 17

Related Questions