mafortis
mafortis

Reputation: 7138

Laravel merge arrays into one

I have 2 tables and I want to make 1 array of both tables data.

Logic

  1. User has bids
  2. Either user is bidder which results come from bids table based on user_id column
  3. Or user is owner and received bids which comes from projects table based on user_id column
  4. I want to merge this 2 arrays into 1 (regardless of user being bidder or receiving bids, I want get all bids at once)

Code

This is what I have currently, but it's not good solution in case user is both bidder and owner, with current code user will only receive data of his/her bids as bidder only.

$bids = Bid::where('user_id', '=', $user->id)->with(['project', 'project.user', 'user'])->get();
if(count($bids) > 0) {
    return response()->json([
        'data' => BidsResource::collection($bids),
        'message' => 'Your data is ready.'
    ], 200);
} else {
    $projects = Project::where('user_id', $user->id)->pluck('id');
    $bids = Bid::whereIn('project_id', $projects)->with(['project', 'project.user', 'user'])->get();
    return response()->json([
        'data' => BidsResource::collection($bids),
        'message' => 'Your data is ready.'
    ], 200);
}

I have already tried array_merge but it return errors (details below).

// as bidder
$bids1 = Bid::where('user_id', '=', $user->id)->with(['project', 'project.user', 'user'])->get();
// as project owner
$projects = Project::where('user_id', $user->id)->pluck('id');
$bids2 = Bid::whereIn('project_id', $projects)->with(['project', 'project.user', 'user'])->get();
// merge results
$bids = array_merge($bids1, $bids2);

return response()->json([
  'data' => BidsResource::collection($bids),
  'message' => 'Data is ready.'
], 200);

array_merge Errors

  1. Code above return array_merge(): Expected parameter 1 to be an array, object given
  2. If I add ->get()->toArray(); then it would return Trying to get property 'id' of non-object

Any suggestions?

Update

BidsResource file

public function toArray($request)
{
    $arrayData = [
        'id' => $this->id,
        'amount' => $this->amount ?  "$ " .number_format($this->amount, 0) : "$0",
        'note' => $this->note,
        'attachment' => $this->attachment ? url('images', $this->attachment) : null,
        'accepted' => $this->accepted,
        'results' => $this->results,
        'user' => new UserResource($this->whenLoaded('user')),
        'project' => new ProjectsResource($this->whenLoaded('project')),
        'chats' => BidChatsResource::collection($this->whenLoaded('chats')),
        'created_at' => $this->created_at ? $this->created_at->diffForHumans() : null,
        'updated_at' => $this->updated_at ? $this->updated_at->diffForHumans() : null,
    ];
    return $arrayData;
}

Upvotes: 1

Views: 607

Answers (2)

Ajith Gopi
Ajith Gopi

Reputation: 1846

In your specific case, the proper and efficient way would be using an OR clause to get the records where either of the conditions is satisfied.

The code would be

$projects = Project::where('user_id', $user->id)->pluck('id');
$bids = Bid::where(function($query) use ($projects, $user){
    $query->where('user_id', '=', $user->id)->orWhereIn('project_id', $projects);
})->with(['project', 'project.user', 'user'])->get();

Upvotes: 1

SEYED BABAK ASHRAFI
SEYED BABAK ASHRAFI

Reputation: 4271

As the results of $bids1 and $bids2 are objects of laravel collection, you can use merge() method of collections#method-merge

$bids = $bids1->merge($bids2);

Upvotes: 0

Related Questions