How to re-format laravel relationship collections - php

I have the following models and their relationships:
Product - (name, price, qty)
Product Attribute (qty, price - when there is a combination, the qty and price here is the one getting)
Attribute - (size, color)
Attribute Values - (small, medium, large, red, blue, green etc)
// One to Many Relationship
$product->productAttributes (returns a collection)
// Many to Many Relationship
$productAttribute->attributeValues (returns a collection)
// One to Many Relationship
$attribute->attributeValues
I need to format it in such a way like:
array:2 [
"color" => array:2 [
0 => "red"
1 => "blue"
]
"size" => array:3 [
0 => "small"
1 => "medium"
2 => "large"
]
]
This is what I get when I iterate on the collections:
$attributes = $productAttributes->map(function (ProductAttribute $pa){
return $pa->attributesValues->map(function (AttributeValue $av) {
return [$av->attribute->name => $av->value];
});
})->all();
it obviously returns:
array:6 [▼
0 => Collection {#508 ▼
#items: array:2 [▼
0 => array:1 [▼
"Color" => "red"
]
1 => array:1 [▼
"Size" => "small"
]
]
}
1 => Collection {#525 ▼
#items: array:2 [▼
0 => array:1 [▼
"Color" => "red"
]
1 => array:1 [▼
"Size" => "medium"
]
]
}
2 => Collection {#535 ▼
#items: array:2 [▼
0 => array:1 [▼
"Color" => "red"
]
1 => array:1 [▼
"Size" => "large"
]
]
}
3 => Collection {#545 ▼
#items: array:2 [▼
0 => array:1 [▼
"Color" => "red"
]
1 => array:1 [▼
"Size" => "small"
]
]
}
]
Again, my intent is to format it like this:
array:2 [
"color" => array:2 [
0 => "red"
1 => "blue"
]
"size" => array:3 [
0 => "small"
1 => "medium"
2 => "large"
]
]
TIA!
Edit:
$product->productAttributes
Collection {#513 ▼
#items: array:6 [▼
0 => ProductAttribute {#514 ▼
#fillable: array:2 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:6 [▶]
#original: array:6 [▼
"id" => 7
"quantity" => 3
"price" => "100.00"
"product_id" => 25
"created_at" => "2018-03-11 16:56:36"
"updated_at" => "2018-03-11 16:56:36"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
1 => ProductAttribute {#515 ▶}
2 => ProductAttribute {#516 ▶}
3 => ProductAttribute {#517 ▶}
4 => ProductAttribute {#518 ▶}
5 => ProductAttribute {#519 ▶}
]
}
$productAttribute->attributeValues
array:6 [▼
0 => Collection {#507 ▼
#items: array:2 [▼
0 => AttributeValue {#521 ▼
#fillable: array:1 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:5 [▶]
#original: array:7 [▼
"id" => 1
"value" => "red"
"attribute_id" => 1
"created_at" => "2018-03-11 16:49:15"
"updated_at" => "2018-03-11 16:49:15"
"pivot_product_attribute_id" => 7
"pivot_attribute_value_id" => 1
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▶]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
1 => AttributeValue {#506 ▼
#fillable: array:1 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:5 [▶]
#original: array:7 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▶]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
]
}
1 => Collection {#523 ▶}
2 => Collection {#530 ▶}
3 => Collection {#537 ▶}
4 => Collection {#544 ▶}
5 => Collection {#547 ▶}
]

I think, what you're looking for is something like the following;
$attributes = $productAttributes->pluck('attributesValue')
->flatten()
->unique()
->groupBy(function (AttributeValue $av) {
return $av->attribute->name;
})
->each(function (Collection $avs) {
$avs->map(function (AttributeValue $av) {
return $av->value;
});
});
Here's what the above code does;
Pull the relationship attributesValue for all results.
Flatten it out so we have one collection containing all attributesValue
Make sure we don't have any duplicates
We group everything so that we have something like colour => (collection of colour attributesValue)
Now we cycle through our multi level collection, and map the instances of AttributeValue so that each is replaced with their value
I've not ran this code myself, but I believe this will work.

Related

Get particular values multidimensional array Laravel

I want to get the values of some fields form the #attributes field (like "title" and "location") so I can fill a calendar.
dd($events); Outputs:
Illuminate\Database\Eloquent\Collection {#948 ▼
#items: array:3 [▼
"26-01-2021" => Illuminate\Database\Eloquent\Collection {#972 ▶}
"01-02-2021" => Illuminate\Database\Eloquent\Collection {#962 ▶}
"03-11-2021" => Illuminate\Database\Eloquent\Collection {#965 ▼
#items: array:1 [▼
0 => App\Models\DaysEvent {#994 ▼
#table: "days_events"
#casts: array:11 [▶]
#dates: array:2 [▶]
#fillable: array:25 [▶]
#dispatchesEvents: array:1 [▶]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#escapeWhenCastingToString: false
#attributes: array:29 [▼
"id" => 166
"title" => "Individual Interview"
"slug" => "individual-interview"
"functionality_type" => "selection"
"days_event_type_id" => 1
"event_start" => "2021-11-03 09:00:00"
"event_end" => "2021-11-03 19:00:00"
"location" => "Online"
"excerpt" => "Suit up and sit down with a recruiter to get in touch with the company on an individual level."
"content" => "<div>Suit up and sit down with a recruiter to get in touch with the company on an individual level. The Individual Interview will last 30 or 50 minutes and is e ▶"
"event_link" => "https://zoom.us/j/1234"
"parent_event_id" => null
"requires_motivation" => 1
"requires_cv" => 1
"requires_followup" => 1
"requires_student_company_preference" => 0
"company_id" => 34
"force_in_calendar" => 0
"spots" => 9
"has_timeslots" => 1
"has_algorithm_priority" => 1
"timeslot_slots" => "["9:00-9:30","9:30-10:00","10:00-10:30","11:00-11:30","11:30-12:00","12:00-12:30","13:00-13:30","13:30-14:00","14:00-14:30"]"
"timeslot_people" => 1
"can_unsubscribe_late" => 1
"company_can_see_cvs" => 1
"sf_id" => null
"deleted_at" => null
"created_at" => "2021-01-04 10:33:38"
"updated_at" => "2021-11-16 12:33:00"
]
#original: array:29 [▶]
#changes: []
#classCastCache: []
#dateFormat: null
#appends: []
#observables: []
#relations: array:1 [▶]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
#forceDeleting: false
}
]
#escapeWhenCastingToString: false
}
]
#escapeWhenCastingToString: false
}
I think I can get the values using the collect function form Laravel. (read this on this very similar question)
But when I try do do: $event_items = collect($events->items);
It gives the error: Property [items] does not exist on this collection instance.
What am I doing wrong here?
you are not get direct use of item,
you use $event_items = collect($events['03-11-2021']['0']->title);
This result you have is basically a collection of collections of models. Collections implement array access so you can user $collection['index'] or you can use $collection->get('index'). If you want all the values in the collection you can call the $collection->all() method. I don't really understand what data you want to get from here or why you have a collection of collections in the first place but the $collection->map() or $collection->transform() method is usually used to extract specific data from a collection.
I also believe that $collection->items is a private property so if you want all the items it is the same as $collection->all()
You can check Collections documentation for how they work.

How to Foreach loop through Laravel collection.?

i m a beginner at laravel. using 5.5 . i have this collection return by my controller :
$products = Product::with('bazar.resellers')->take(2)->get();
dd($products);
//return view('shop.index')->with('products', $products);
which basically is three tables with nested relations. Note the relations lists in the code below. i want to access data(all columns in red colour) from every model i have in the collection i.e. Product, bazar and reseller.
Relationships are quite fine. but how to retrieve it from a collection? i dunno how foreach loops play with a collection.
Collection {#578 ▼
#items: array:2 [▼
0 => Product {#487 ▼
#fillable: array:7 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:10 [▼
"id" => 1
"created_at" => "2018-04-27 12:54:41"
"updated_at" => "2018-04-27 12:54:41"
"imgp" => "shirt.jpg"
"title" => "shirt1"
"Prod_descript" => "shirt1 is a good shirt"
"price" => 10
"reseller_id" => 1
"City_id" => 1
"bazar_id" => 1
]
#original: array:10 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"bazar" => Bazar {#523 ▼
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:7 [▼
"id" => 1
"Bazarname" => "Saddar"
"Bazarlat" => null
"Bazarlong" => null
"created_at" => null
"updated_at" => null
"City_id" => 1
]
#original: array:7 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"resellers" => Collection {#574 ▼
#items: array:1 [▼
0 => Reseller {#564 ▼
#guard: "reseller"
#fillable: array:12 [▶]
#hidden: array:2 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:15 [▼
"id" => 1
"Fname" => "talha"
"Lname" => "ali"
"email" => "p#g.com"
"password" => "$2y$10$M7wOmSouxSAYADN7NeFdSObT8fGwkEOFxVmOgcNSWvrixWCDtA/1S"
"mobile_no" => "03169880008"
"landline_no" => "0987654"
"shop_name" => "MyTestSHop"
"NIC_no" => "170178359437589754"
"shop_address" => "University Town, Peshawar, Pakistan"
"remember_token" => "wrb3nOwOWQcTuoF0P9KnaknwpOxfpTHt4gkShUmTzkR2Df9A7pPY5shBq6pQ"
"created_at" => "2018-04-27 12:42:25"
"updated_at" => "2018-04-27 12:42:25"
"City_id" => 1
"bazar_id" => 1
]
#original: array:15 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#visible: []
#guarded: array:1 [▶]
#rememberTokenName: "remember_token"
}
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▼
0 => "*"
]
}
1 => Product {#488 ▶}
]
}
the code i have tried is not working!
#foreach($products as $product)
<h1>{{ $product->title }}</h1>
#foreach($product->bazar as $bazar)
<h3>{{ $bazar->Bazarname }}</h3>
#foreach($bazar->resellers as $reseller)
<p>{{ $reseller->Fname }}</p>
#endforeach
#endforeach
#endforeach
If product has single bazar,then you don't need to use foreach on $product->bazar. You just need to use bazar property directly. and if product has many bazars, then update your product model bazar() method like:
public function bazars()
{
return $this->hasMany(Bazar::class);
}
It returns collection of bazars and then you can run loop on that.

Checking if a value exists in two or more arrays in php

Hi there I have this problem here:
I have this on my controller:
$questions = Question::select('text','question_image','question_type_id','id')
->whereIn('id', $question_ids)
->where('deleted', 0)
->orderBy('created_at','ASC')
->paginate(20);
which ouputs this:
LengthAwarePaginator {#1635 ▼
#total: 4
#lastPage: 1
#items: Collection {#1627 ▼
#items: array:4 [▼
0 => Question {#1622 ▼
#hidden: array:1 [▶]
#fillable: array:10 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:4 [▼
"text" => "asd"
"question_image" => null
"question_type_id" => 5
"id" => 1213
]
#original: array:4 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#visible: []
#guarded: array:1 [▶]
}
1 => Question {#1623 ▶}
2 => Question {#1624 ▶}
3 => Question {#1625 ▶}
And then I have this one:
$owner_questions = BankQuestion::select('question_id')->where('bank_id', $bank_id)->where('user_id', $auth)->where('deleted', 0)->get()->toArray();
Which outputs this:
array:2 [▼
0 => array:1 [▼
"question_id" => 1217
]
1 => array:1 [▼
"question_id" => 1218
]
]
And here I have my loop of questions:
foreach ($questions as $question) {
if(in_array($question->id, $owner_questions )){
$question->authorQuestion = 1;
}else{
$question->authorQuestion = 0;
}
}
Here I need to find the $question->id that exists on $owner_questions arrays which there the numbers that I am looking for are 1217 and 1218. Can someone please help me what I am doing wrong here please..?
You are comparing numeric value($question->id) with an array, which has a property question_id. Here is what you can do:
$owner_questions_ids = array();
foreach($owner_questions as $owner_question){
$owner_questions_ids[] = $owner_question['question_id'];
}
// now you can compare them
in_array($question->id, $owner_questions_ids )

Getting list of discounted products in laravel

I try to get all of my discounted products in one page, but it doesn't return results
while the exact same query return results in homepage.
function
public function promotions() {
$promotions = Discount::with('products')->orderby('id', 'desc')->paginate(12);
return view('front.promotions', compact('promotions'));
}
route
Route::get('/promotions', 'frontend\FrontendController#promotions')->name('promotions');
blade
#foreach($promotions as $product)
{{$product->title}} // return nothing!
#endforeach
here is dd of my $product
dd code
Discount {#686 ▼
#table: "discounts"
#dates: array:2 [▶]
#fillable: array:4 [▶]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:8 [▶]
#original: array:8 [▼
"id" => 4
"value_from" => "2018-02-18"
"value_to" => "2018-02-19"
"amount" => "10000"
"product_id" => 16
"stock" => 25
"created_at" => "2018-02-19 09:05:48"
"updated_at" => "2018-02-19 09:47:10"
]
#changes: []
#casts: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"products" => Product {#697 ▼
#fillable: array:16 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:23 [▶]
#original: array:23 [▼
"id" => 16
"title" => "new product"
"slug" => "new-product"
"imageOne" => "productone-1519001703.png"
"imageTwo" => "producttwo-1519001703.jpg"
"short_description" => """
<!DOCTYPE html>\r\n
<html>\r\n
<head>\r\n
</head>\r\n
<body>\r\n
<p>eagtheyh</p>\r\n
</body>\r\n
</html>
"""
"description" => """
<!DOCTYPE html>\r\n
<html>\r\n
<head>\r\n
</head>\r\n
<body>\r\n
<p>shw4 bw 6r uwrurjw ryt jyhkiuggk</p>\r\n
</body>\r\n
</html>
"""
"price" => "100000"
"meta_description" => "gjyrj"
"meta_tags" => "yrujr,ujrtsdjr,jrjurysj,"
"arrivalDays" => "1"
"height" => "546"
"weight" => "56"
"lenght" => "56"
"width" => "56"
"sku" => "47ghg"
"stock" => "24"
"status_id" => 1
"brand_id" => 1
"category_id" => 1
"subcategory_id" => 1
"created_at" => "2018-02-19 07:55:03"
"updated_at" => "2018-02-21 09:58:04"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
#slugOptions: null
#configSettings: array:4 [▶]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
You need to iterate over discounts and products:
#foreach($promotions as $discount)
{{ $discount->products->title }}
#endforeach

Sort or order items with multiple relationships in laravel 5.1

I'm using multiple relationship and uses eager loading. What I have now are three tables (quizzes, multiple_choice, question_numbers), and I want to sort the multiple_choice using the question_numbers table with the field question_number. How can I do that? Please see my code below:
$undeleted = function($query){
return $query->where('deleted', 0);
};
$quiz = Quiz::with([
'multiple_choices.question_numbers' => $undeleted
])->find($id);
$quiz_items = collect($quiz->multiple_choices);
//$quiz_items = $quiz_items->sortBy('question_number');
I tried the commented part, but nothings happen.
Update with dd()
After I used dd(), the result is:
Collection {#478 ▼
#items: array:13 [▼
0 => MultipleChoice {#427 ▼
#table: "multiple_choice"
#fillable: array:6 [▶]
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:9 [▼
"id" => 1
"name" => "My name"
"question" => "the question body"
"created_at" => "2017-06-06 00:00:00"
"updated_at" => "2017-10-07 18:34:36"
]
#original: array:13 [▶]
#relations: array:2 [▶]
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
]
}
Update2
#relations: array:2 [▼
"pivot" => Pivot {#426 ▶}
"question_numbers" => Collection {#452 ▼
#items: array:1 [▼
0 => Quiz {#449 ▶}
]
}
]
Update 3
databases
quizzes — id, name, body
multiple_choice — id, name, question
multiple_choice_quiz — id, multiple_choice_id, quiz_id
question_numbers — id, quiz_id, question_id, question_number
The question_number field in the question_numbers table is the field that I want to sort or order.

Categories