9

I'm currently stuck on how to merge two query results into a single object . Below is my code.

EDITED

Model methods

public static function getTeamStats($competitionId, $teamId) {
    return TeamCompetitionStatistics::where('competitionId', $competitionId)
        ->where('teamid', $teamId)
        ->where('periodNumber', 0)
        ->get();
}

public static function getTeamPosition($competitionId, $teamId){
    return self::where('latest', 1)
        ->where('competitionId',$competitionId)
        ->where('competitorId', $teamId)
        ->get(['position', 'streak'])
        ->map(function($item, $key){
            $item->position = $item->position . date("S", mktime(0, 0, 0, 0, $item->position, 0));
            if(strpos($item->streak, '-') !== FALSE) {
                $item->streak = str_replace('-', 'L', $item->streak);
            }
            else {
                $item->streak = 'W'.$item->streak;
            }
            return $item;
        });
}

Getting values in controller

$teamStanding = Ladder::getTeamPosition($request->competitionId, $request->id);
$teamStatistics = TeamCompetitionStatistics::getTeamStats($request->competitionId, $request->id);

$result = $teamStatistics->merge($teamStanding);

Returned result: [{'teamstanding': 'data'}, {'teamstatictics': 'data'}]

Expected output: [{'teamstanding': 'data', 'teamstatictics': 'data'}]

danronmoon
  • 3,814
  • 5
  • 34
  • 56
PenAndPapers
  • 2,018
  • 9
  • 31
  • 59

4 Answers4

34

You can use all() function.

$teamStanding = Ladder::getTeamPosition($request->competitionId, $request->id)->get();

$teamStatistics = TeamCompetitionStatistics::getTeamStats($request->competitionId, $request->id)->get();

$merged = $teamStatistics->merge($teamStanding);

$result = $merged->all();

// return [{'teamstanding': 'data', 'teamstatictics': 'data'}]
Ramzan Mahmood
  • 1,881
  • 2
  • 21
  • 46
Jakir Hossain
  • 2,457
  • 18
  • 23
7

Try merge()

The merge method merges the given array or collection with the original collection.

$first = ModelName::where('<fieldName>','<searchText>')
        ->get();
$second = Album::where('<fieldName>','<searchText>')
    ->get();

$finalResult = $first->merge($second);

$finalResult->each(function($record)
{
    echo $record-><fieldName>.'<br />';
});
Hiren Makwana
  • 1,976
  • 2
  • 13
  • 28
6

Adding my answer as the above solutions didn't quite work for me, both just added two separate objects to one array: {"Name":"A Name"},{"Surname":"A Surname"}. I had to collect my array and use first.

https://laravel.com/docs/5.4/collections#method-merge

$first  = $modelone->where('Id', '1')->first(['Name']);
$second = $modeltwo->where('Thing', '1')->first(['Surname']);

    $collection = collect($first);
    $merged     = $collection->merge($second);
    $result[]   = $merged->all();
    return $result;
//output: [{"Name":"A Name","Surname":"A Surname"}]
Pat
  • 132
  • 1
  • 10
4

Personally I am not a fan on transforming 2 possible big queries in Collections and merge them, seems like a lot of processing in there.

I normally use union(), maybe this can help others. Laravel documentation for unions

$first = DB::table('users')
        ->whereNull('first_name');

$users = DB::table('users')
        ->whereNull('last_name')
        ->union($first)
        ->get();
NinetyHH
  • 1,494
  • 4
  • 19
  • 32
  • Will merge also work with paginate? For example can we do stuffs like $merged->paginate(10) ?? – Skykid Felix Jun 08 '20 at 13:11
  • In my project, I am using Fractal for my transformers and I managed to do it there by adding the items in a Fractal Collection ```$collection = new Collection($items, $transformer, $type);``` and than add it in the IlluminatePaginatorAdapter from Fractal as ```$collection->setPaginator(new IlluminatePaginatorAdapter($items));``` If you can do it with Fractal, there needs to be a way throught Laravel also. – NinetyHH Jun 08 '20 at 13:20
  • thanks am going to try that. What am trying to achieve is a Facebook type newsfeed where you have multiple models ( posts, videos, status, polls ). Now I want to merge all of them and possibly shuffle them so that each model result is not group. Then finally paginate. – Skykid Felix Jun 08 '20 at 13:22
  • This is more on personal preference but from my point of view, this sounds quite costly. What I will do is having a type Post (posts in db) that has default columns but can have relations to video entity, pools entity etc and than its mostly going to be just the correct relations such as hasMany etc. So instead of making a huge query and merge all data together, ill just return a standardised transformer of Posts which includes relations based on the foreign keys that are available. In this way, you will not need to merge any query. – NinetyHH Jun 08 '20 at 13:27
  • Since am paginating per 10 results, I think I might not have to worry about processing time isn't that so? I am new to eloquent relationships on Laravel and my database already contain user generated content so I can't go with that approach right now. Could you show me a code snippet where you used the paginator adapter?? Thanks a lot – Skykid Felix Jun 08 '20 at 14:54