Related
I would like to perform the average rating of respective product which stored in the pivot table called "reviews".Below are my existing code.
Product Model:
public function reviews(){
return $this->belongsToMany(User::class,'reviews')->withPivot('comment','rating')->withTimestamps();
}
public function getProductRatingAttribute(){
return $this->reviews()->average('rating');
}
User Model:
public function reviews(){
return $this->belongsToMany(Product::class,'reviews')->withPivot('comment','rating')->withTimestamps();
}
Migration for the reviews
Schema::create('reviews', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->string('comment')->nullable();
$table->integer('rating');
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('product_id')->references('id')->on('products');
});
I have attempted to use the below to code construct the expected output but it leads N+1 issue because it does not take advantage of the eager loading of the Laravel Eloquent.
$s = Product::with('reviews')->append('product_rating');
As I check telescope, it produces 6 query which can lead performance issue when the data is large.
Expected output:
{
"msg": [
{
"id": 4,
"created_at": "2021-04-09T07:32:35.000000Z",
"updated_at": "2021-04-09T07:32:35.000000Z",
"name": "MacDonald",
"nickname": "MCD",
"users_id": 1,
"price": "0.00",
"product_rating": "3.3333",
"reviews": [
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 4,
"user_id": 1,
"comment": "Ouch",
"rating": 3,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
},
{
"id": 2,
"name": "Kelvin Ooi",
"email": "kelvin.ooi#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-13T12:07:11.000000Z",
"role": 1,
"pivot": {
"product_id": 4,
"user_id": 2,
"comment": "Ouch",
"rating": 5,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
},
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 4,
"user_id": 1,
"comment": "Ouch",
"rating": 2,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
}
]
},
{
"id": 10,
"created_at": null,
"updated_at": null,
"name": "Mary Bown",
"nickname": "MB",
"users_id": 1,
"price": "2.88",
"product_rating": "2.0000",
"reviews": [
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 10,
"user_id": 1,
"comment": "Ouch",
"rating": 2,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
}
]
},
{
"id": 11,
"created_at": null,
"updated_at": null,
"name": "Pizza Hut",
"nickname": "pizzahut",
"users_id": 1,
"price": "4.10",
"product_rating": null,
"reviews": [
]
},
{
"id": 12,
"created_at": "2021-04-09T08:00:42.000000Z",
"updated_at": "2021-04-09T08:00:42.000000Z",
"name": "Domino Pizza",
"nickname": "domino",
"users_id": 3,
"price": "0.00",
"product_rating": null,
"reviews": [
]
},
{
"id": 13,
"created_at": "2021-04-26T16:12:53.000000Z",
"updated_at": "2021-04-26T16:12:53.000000Z",
"name": "Chicken Chop",
"nickname": "chickchop",
"users_id": 3,
"price": "0.00",
"product_rating": null,
"reviews": [
]
}
]
}
Appending is performing the query on each record.
Why not perform average on the collection itself?
$s = Product::with('reviews')->get();
$avg = $s->avg('pivot.rating');
Alternatively you can modify the relationship method to include a raw select of the average rating.
I have the following models
Order (id,number)
Detail (id,item_id,count,user_id ...etc)
Item (id,name)
Cat (id,name)
User (id,name) which is not important in my case
Each order has Many details
Each detail belong to item
Each item belong to category
Each detail belong to user
I wrote this line of code
public function show(Order $order)
{
//
$orders= $order->details()->with(['item','user'])->get();
return response()->json(['details'=>$orders],200);
}
to obtains a response like this :
"details": [
{
"id": 3089,
"count": 3,
"item_id": 102,
"order_id": 1,
"user_id": 10,
"created_at": "2019-11-22 22:19:23",
"updated_at": "2019-11-22 22:19:23",
"user": {
"id": 10,
"name": "Ms. Eda Stoltenberg DVM",
"username": "Brandy Murazik",
"verified": "1",
"verification_token": null,
"status": "1",
"dept_id": 5,
"created_at": "2019-11-22 22:15:47",
"updated_at": "2019-11-22 22:15:47"
},
"item": {
"id": 102,
"code": "Lamar Hansen",
"cat_id": 91,
"created_at": "2019-11-22 22:15:54",
"updated_at": "2019-11-22 22:15:54"
}
},
{
"id": 3428,
"count": 1,
"item_id": 15,
"order_id": 1,
"user_id": 10,
"created_at": "2019-11-22 22:19:41",
"updated_at": "2019-11-22 22:19:41",
"user": {
"id": 10,
"name": "Ms. Eda Stoltenberg DVM",
"username": "Brandy Murazik",
"verified": "1",
"verification_token": null,
"status": "1",
"dept_id": 5,
"created_at": "2019-11-22 22:15:47",
"updated_at": "2019-11-22 22:15:47"
},
"item": {
"id": 15,
"code": "Hilario Dicki",
"cat_id": 20,
"created_at": "2019-11-22 22:15:51",
"updated_at": "2019-11-22 22:15:51"
}
},
{
"id": 3493,
"count": 1,
"item_id": 129,
"order_id": 1,
"user_id": 6,
"created_at": "2019-11-22 22:19:45",
"updated_at": "2019-11-22 22:19:45",
"user": {
"id": 6,
"name": "Prof. Marina Kiehn",
"username": "Nickolas Hessel",
"verified": "0",
"verification_token": "mwWkL95jjyi5di9PSH3T3LXXZEE1W2DmegTxAOtN",
"status": "1",
"dept_id": 3,
"created_at": "2019-11-22 22:15:47",
"updated_at": "2019-11-22 22:15:47"
},
"item": {
"id": 129,
"code": "Dr. Donnell Harber",
"cat_id": 54,
"created_at": "2019-11-22 22:15:55",
"updated_at": "2019-11-22 22:15:55"
}
},
{
"id": 4032,
"count": 1,
"item_id": 221,
"order_id": 1,
"user_id": 8,
"created_at": "2019-11-22 22:20:10",
"updated_at": "2019-11-22 22:20:10",
"user": {
"id": 8,
"name": "Prof. Thaddeus Boehm",
"username": "Frederick Kshlerin",
"verified": "1",
"verification_token": null,
"status": "1",
"dept_id": 3,
"created_at": "2019-11-22 22:15:47",
"updated_at": "2019-11-22 22:15:47"
},
"item": {
"id": 221,
"code": "Maia Hettinger V",
"cat_id": 57,
"created_at": "2019-11-22 22:15:58",
"updated_at": "2019-11-22 22:15:58"
}
},
{
"id": 4311,
"count": 1,
"item_id": 139,
"order_id": 1,
"user_id": 3,
"created_at": "2019-11-22 22:20:21",
"updated_at": "2019-11-22 22:20:21",
"user": {
"id": 3,
"name": "Cletus Walter I",
"username": "Johan Kemmer",
"verified": "0",
"verification_token": "M6MWe7mOmzcyM0rrlbMwVCX7q2vyULFKwSAJmQwl",
"status": "0",
"dept_id": 5,
"created_at": "2019-11-22 22:15:46",
"updated_at": "2019-11-22 22:15:46"
},
"item": {
"id": 139,
"code": "Tanner Schimmel",
"cat_id": 80,
"created_at": "2019-11-22 22:15:55",
"updated_at": "2019-11-22 22:15:55"
}
},
{
"id": 4821,
"count": 2,
"item_id": 243,
"order_id": 1,
"user_id": 1,
"created_at": "2019-11-22 22:20:41",
"updated_at": "2019-11-22 22:20:41",
"user": {
"id": 1,
"name": "Mrs. Fay Cassin",
"username": "Ryley Bode",
"verified": "0",
"verification_token": "E93hzJbIp2eCxbBGgtcsYDckRreASTPL6ZEAyyKP",
"status": "1",
"dept_id": 1,
"created_at": "2019-11-22 22:15:46",
"updated_at": "2019-11-22 22:15:46"
},
"item": {
"id": 243,
"code": "Miss Jaida Simonis DVM",
"cat_id": 53,
"created_at": "2019-11-22 22:15:59",
"updated_at": "2019-11-22 22:15:59"
}
}
]
But i also need to get category object inside item object, which is already relationship is Item belong to Category
I know that i can make a join query but i prefer to find a best solution with relation based between models
So how can i do that if it is possible?
thanks
You may try this (Since item belongs to category):
$orders = $order->details()->with(['item.category', 'user'])->get();
I got a some trouble in my Laravel application, in Search function, when I do search the result is
{
"data": [
{
"id": 2,
"user_id": 8,
"identity_number": "213918273",
"name": "Pekerja_2",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "4232343432",
"image": null,
"created_at": "2018-01-11 10:59:54",
"updated_at": "2018-01-11 10:59:54",
"partner_id": null,
"skill": [
{
"id": 3,
"worker_id": 2,
"skill_id": 6,
"sub_skill_id": 18,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"price": null,
"unit": null
}
]
},
{
"id": 3,
"user_id": 16,
"identity_number": "213918273",
"name": "Pekerja_3",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "2345234234",
"image": null,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"partner_id": null,
"skill": []
}
]
}
as you can see that "Skill" with id number 3 is empty, I want all in id number 3 is empty also.
My controller is :
$worker = Worker::with(['skill' => function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
}])->whereHas('skill');
And I want something like this :
{
"data": [
{
"id": 2,
"user_id": 8,
"identity_number": "213918273",
"name": "Pekerja_2",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "2534234234",
"image": null,
"created_at": "2018-01-11 10:59:54",
"updated_at": "2018-01-11 10:59:54",
"partner_id": null,
"skill": [
{
"id": 3,
"worker_id": 2,
"skill_id": 6,
"sub_skill_id": 18,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"price": null,
"unit": null
}
]
},
]
}
The point is, if "skill" variable is empty then data not show and vice versa.
Thankyou any help will appreciate, sorry for bad english
You can add a callback to your whereHas function with the same filter as the with function
$worker = Worker::with(['skill' => function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
}])
->whereHas('skill', function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
})
->get();
You can try this $worker = Worker:has('skill')->get();
Only worker that have at least one skill are contained in the collection
In my forum I'm showing all topics. It looks like this:
So a user can subscribe by clicking on the red hearth.
I'm loading the topics with this json:
{
"forum": {
"id": 1,
"slug": "test",
"name": "test",
"description": "test",
"created_at": null,
"updated_at": null
},
"topics": {
"total": 6,
"per_page": 5,
"current_page": 1,
"last_page": 2,
"next_page_url": "http://forum.dev/api/forum/test?page=2",
"prev_page_url": null,
"from": 1,
"to": 5,
"data": [
{
"id": 1,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 2,
"slug": "2",
"name": "1",
"description": "1\t",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 3,
"slug": "1",
"name": "1",
"description": "1\t",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 4,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 5,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
}
]
}
}
I'm returning that ^ like this:
$forum->topics()->orderBy('created_at', 'DESC')->paginate(5);
So how do I get a subscribe value on every topic object?
So like this:
"data": [
{
"id": 1,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null,
"subscribed": true
},
I already made this on my topic model:
/**
* #return mixed
*/
public function subscriptions()
{
return Topic::subscribedBy(Auth::user())->get();
}
And it's working. But how do I send that ^ with every topic.
You can add an attribute (which is not present in the database) by creating an accessor.
public function getSubscriptionsAttribute()
{
return Topic::subscribedBy(Auth::user())->get();
}
and then adding it to the $append property.
protected $appends = ['subscriptions'];
If you're using the $visible whitelist you might have to add it to that property too.
Source (Its all the way in the bottom.)
I have folowing JSON returned by ORM
[
{
"id": 3,
"name": "Card Department",
"name_burmese": "Card Department",
"is_active": "1",
"created_at": "2014-11-23 07:02:07",
"updated_at": "2014-11-23 07:02:07",
"orm_bank_contact": []
},
{
"id": 1,
"name": "Loan Department",
"name_burmese": "Loan Department",
"is_active": "1",
"created_at": "2014-11-23 07:01:16",
"updated_at": "2015-02-24 09:05:35",
"orm_bank_contact": []
},
{
"id": 4,
"name": "Remittance Department",
"name_burmese": "Remittance Department",
"is_active": "0",
"created_at": "2015-02-24 09:43:25",
"updated_at": "2015-04-17 12:26:07",
"orm_bank_contact": []
},
{
"id": 2,
"name": "Deposit Department",
"name_burmese": "Deposit Department",
"is_active": "1",
"created_at": "2014-11-23 07:01:34",
"updated_at": "2015-04-20 14:04:27",
"orm_bank_contact": [
{
"id": 27,
"bank_department": 2,
"mobile": "9843139168",
"phone": "9843139168",
"email": "shresthabeenu#gmail.com",
"contact_person": "Binu Shrestha",
"address": "No. 416, Mahabandoola Road, Kyauktada Township, Yangon, Myanmar",
"is_active": "1",
"created_at": "2015-04-15 08:50:16",
"updated_at": "2015-04-15 08:50:16",
"bank_id": 13
}
]
}
]
but i just need
[
{
"id": 2,
"name": "Deposit Department",
"name_burmese": "Deposit Department",
"is_active": "1",
"created_at": "2014-11-23 07:01:34",
"updated_at": "2015-04-20 14:04:27",
"orm_bank_contact": [
{
"id": 27,
"bank_department": 2,
"mobile": "9843139168",
"phone": "9843139168",
"email": "shresthabeenu#gmail.com",
"contact_person": "Binu Shrestha",
"address": "No. 416, Mahabandoola Road, Kyauktada Township, Yangon, Myanmar",
"is_active": "1",
"created_at": "2015-04-15 08:50:16",
"updated_at": "2015-04-15 08:50:16",
"bank_id": 13
}
]
}
]
I need to fetch record with child on eager loaded objects
I tried below
$bank_contact = BankDepartment::with(array('OrmBankContact' => function($query) use($bank_id){
$query->where('bank_id', "=", $bank_id)->where('bank_department','>',0);}))
->get();
But no luck.. what is the proper way?
This query should do the job returning only departments with OrmBankContact
BankDepartment::has('OrmBankContact')->get();
See Eloquent docs on querying relations
Model BankDepartment
class BankDepartment extends Eloquent implements UserInterface, RemindableInterface {
public function OrmBankContact(){
return $this->hasMany('OrmBankContact','bank_department','id');
}
}
Model OrmBankContact
class OrmBankContact extends Eloquent implements UserInterface, RemindableInterface {
public function BankDepartment(){
return $this->belongsTo('BankDepartment','bank_department','id');
}
}
In Any controller you can get like this
$OrmBankContact = BankDepartment::with('OrmBankContact')->get();
$OrmBankContact = $OrmBankContact->toArray();
echo '<pre>'; print_r($OrmBankContact); exit;