Building an array in nested foreach loops in Laravel controller - php

I am trying to build an array of user ids from a long eloquent relationship, using nested foreach loops in a Laravel controller, but can't get it to work.
Users can have publishers, those publishers can have teams and each team has members. Users can be in multiple teams so I also need to remove duplicate IDs.
I want to end up with a count to see how many team members are associated with a user.
In my user model
public function publishers()
{
return $this->belongsToMany('App\Publisher')->withTimestamps();
}
In my publisher model
public function teams()
{
return $this->belongsToMany('App\Team')->withTimestamps();
}
and in my team model
public function members()
{
return $this->belongsToMany('App\User')->withPivot('status', 'title', 'team_role_ids')->withTimestamps();
}
and in my profile controller
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds[] = $publisherTeam->members->pluck('id')->toarray();
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);
But I'm getting multiple arrays and not just one compiled array and the count isn't working. Any idea what I'm doing wrong?

You are assigning a new array into $teamUserIds each iteration. That's why you are getting multiple arrays.
$teamUserIds = [];
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds = array_merge($teamUserIds, $publisherTeam->members->pluck('id')->toarray());
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);

you are adding arrays of id $publisherTeam->members->pluck('id')->toarray(); as a new index in $teamUserIds . but what you want to do is to merge the array of ids
so your code would be like this :
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds = array_merge($teamUserIds , $publisherTeam->members->pluck('id')->toarray());
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);

Related

Multilayer relational data retrieval Laravel

So i have 3 models: User, Team, Project
User ManyToMany Team.
Team ManyToMany Project.
I need to Retrieve the data from all project, based on the current user and his corresponding teams.
i tried writing it as a oneLiner:
$user->teams->projects
Error: Property [projects] does not exist on this collection instance.
but that didn't work. Is it possible as a oneliner or does it need to be used in a foreach loop
Solved By using this nested Foreach Loop:
$user = auth()->guard('api')->user();
if (!$user->hasRole(['directie', 'administrator'])) {
$collection = collect();
foreach ($user->teams as $team) {
foreach ($team->projects()->with('customer')->get() as $project) {
$collection->push($project);
}
}
$unique = $collection->unique('id');
return new ProjectCollection($unique);
}
return new ProjectCollection(Project::with("customer")->paginate(13));

How to find and merge two rows into one

I am new to Laravel so I am confused how to do this
I have a table called groups where I forget to use unique in validation . After Long time I found out there are multiple datas with same name for ex :
I have two datas with same name called Feminism but with different id
The group table have only name and description columns , but it has relation with products many to many I have other datas too which has same name I want to merge those datas into one . along with the relation to the product . Is is possible ?
Shall I have to check all the names manually like
Item::where('name','Feminism')->get();
and then merge those datas or we have some other relavant methods
You can refactor this code for your models and relations
foreach ($groups as $group) {
$duplicates = Group::where('name', $group->name)->where('id', '<>', $group->id)->get();
foreach ($duplicates as $duplicate) {
$mustBeUpdatedRelation = $duplicate->products;
$anotherRelation = $duplicate->anotherRelation;
foreach ($mustBeUpdatedRelation as $product) {
$product->categories()->detach($duplicate->id); // if product has pivot data you must get these and assign to new relation
//new relation
$product->categories()->attach($group->id);
}
$anotherRelation = $duplicate->anotherRelation;
foreach ($anotherRelation as $item) {
// like above
// detach duplicated
// attach unique
}
//finally you can delete or .... duplicated group
$duplicate->update([
'name' => "duplicated_$duplicate->name"
]);
}
}
You may use the following
$items = App\Item::with('products')->get();
$tempArr = [];
foreach ($items as $key => $item) {
if(isset($tempArr[$item->name])) {
$merged = $tempArr[$item->name]['products']->merge($item->products);
unset($tempArr[$item->name]['products']);
$tempArr[$item->name]['products'] = $merged;
} else {
$tempArr[$item->name] = $item;
}
}
foreach ($tempArr as $item) {
$item->products()->sync($item->products->pluck('id'));
}
$idsToKeep = array_column($tempArr, 'id');
App\Item::whereNotIn('id', $idsToKeep )->delete();
Use onDelete cascade when defining your pivot table migration.
This takes care of deleting the model’s relations for you:
e.g.
$table->foreign(’item_id’)
->references(’id’)->on(’items’)
->onDelete(’cascade’);

Laravel Pagination with array_merge

I have 2 table which name incomes and expenses and I want to show all the data in one view with laravel pagination. For this, I Merged two array with array_merge().
$incomes = Income::where('user_id', Auth::User()->id)->get()->toArray();
$expenses = Expense::where('user_id', Auth::User()->id)->get()->toArray();
foreach ($incomes as $key => $value) {
$incomes[$key]['type'] = 'income';
}
foreach ($expenses as $key => $value) {
$expenses[$key]['type'] = 'expense';
}
$results = array_merge($incomes, $expenses);
How can I paginate this $results?
You can do this in two ways:
Laravel's built in manually creating a paginator functionality.
Get the results from tables using UNION.
Using UNION
$incomes = Income::where('user_id', Auth::User()->id);
$data = Expense::where('user_id', Auth::User()->id)->union($incomes)->paginate(10);
For manually creating a paginator, please see https://laravel.com/docs/6.x/pagination#manually-creating-a-paginator
Add the following to Income Model
protected $appends = ['type'];
public function getTypeAttribute()
{
return 'Income';
}
Add the following to Expense Model
protected $appends = ['type'];
public function getTypeAttribute()
{
return 'Expense';
}
This will add the type key in the query results.

Laravel Eloquent groupBy to return one title of each group

I have a very complex issue, I want to show items under one title if title is the same for every item, Im new to Laravel and dont know how to do this, I hope there is a real soution for this issue, below screen shot of the result, please help me in a very detailed solution to solve this issue, im suffering since a week to solve it but cant do this
screen shot:
https://imgur.com/IOLGpzU
Tables:
https://imgur.com/AbVNDqP
https://imgur.com/kQTzQA2
https://imgur.com/brGYl54
https://imgur.com/oLXjGl9
Controller:
$customizeorders = OrderCustomize::where('userorder_id',$order_number)->with('customizeproduct')->get()->groupBy('customizetitle_id');
OrderCustomize Model:
protected $table = "ordercustomizes";
protected $fillable = [
'customizeproduct_id',
'userorder_id',
'product_id'
];
public function customizeproduct()
{
return $this->belongsTo(CustomizeProduct::class);
}
CustomizeProduct Model:
protected $table = "customizeproducts";
protected $fillable = [
'customizetitle_id',
'product_id',
'selection_type',
'selection_number',
'customize_title',
'customize_price'
];
public function customizetitle()
{
return $this->belongsTo(CustomizeTitle::class);
}
Blade:
#if(count($customizeorders)>0)
#foreach ($customizeorders as $customizetitle => $groupCustomizes)
#foreach($groupCustomizes as $key=>$customize)
#if(($userorder->product_id)==($customize->product_id))
<div>{{$customize->customizeproduct->customizetitle->name}}:</div>
{{$customize->customizeproduct->customize_title}} .
#endif
#endforeach
#break
#endforeach
#endif
//you need to create array to store the array of items having same title.
//i guess the item having same title also have same id.
Then you should use order by id not group by.
//it will provide you the data of same id in the conitnuous queue
//then you can use foreach loop to push the group of items in array and wrap that array with another array.
//so that you can push that in view. then you can loop through the array in view get the desired data.
//here in this method it have check if the items belongs to previous items or not using the $previousItem variable
public function show_device_report(Request $request)
{
//store the overall report.
$wholeData = [];
//stores the individual wrapper.
$wrapper = [];
//getting the id for the first items in the list
$previousItem = $datas[0]->id;
//transforming the values before sending to the view by
foreach ($datas as $data) {
//store the report of every items
$singleItem = [];
if ($data->id == $previousItem) {
$id = $data->id
//get all the item you need and push in the array.
array_push($singleItem, $id, $name, $etc);
array_push($wrapper, $singleItem);
} else {
$previousItem = $data->id;
array_push($wholeData, $wrapper);
//set the wrapper to null so that it can store the another items group in another index.
$wrapper= [];
}
return $wholeData ;
}
You need to modify little code according to your needs. As there is no any table structure provided by you.
store the individual item in singleItem[], then store all the single items in wraper[], and all the wraper[] in wholedata[]. Send wholedata[] to the view.
whole[
[wrapper1[item1,item2,item3]],
[wrapper2[item1,item2,item3,item4]],
[wrapper3[item1,item2]],
]

Laravel relationship query where using array

I'm trying to return all the attributes from my database that have a set foreign key (Attribute groups). I've set up all the relationships in my model but I'm unsure how to query these relationships using a collection or array.
AttributeGroup -
public function attribute()
{
return $this->hasMany('App\Attribute', 'group_id');
}
Attribute -
public function attributeGroup()
{
return $this->belongsTo('App\AttributeGroup');
}
My current query -
$page = Page::where('slug', $slug)->firstOrFail();
$groups = AttributeGroup::where('page_id', $page->id)->get()->toArray();
$atts = Attribute::where('group_id', $groups[0]['id'])->get();
This works because we have set the specific index of the array using $groups[0]
Is there a simple way I can pass an array through to the query using their relationships or is looping through the results and then passing my own array to the query the best approach?
$attributes = array();
foreach ($groups as $group){
array_push($attributes, $group['id']);
}
$atts = Attribute::where('group_id', $attributes)->get();
$groups is a collection. Assume them as arrays on steroids. Therefore you can use the pluck() method to get those ids you need:
$page = Page::where('slug', $slug)->firstOrFail();
$groups = AttributeGroup::where('page_id', $page->id)->get();
$atts = Attribute::where('group_id', $groups->pluck('id'))->get();
Also if you've set your relationships correctly, you should be able to loop through $groups and access the attributes of those $groups. You can test it:
$groups = AttributeGroup::where('page_id', $page->id)->get();
dd($groups->first()->attributes);

Categories