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.
Related
I have some problems with Eloquent Eager Loading. I have added whereHas to remove the blog don't meet the comment criteria but the comment stills return empty array. My intention is to completely remove it from the json record.
How can I completely remove the json data chain that does not meet my condition?
My current code:
User::select("id", "name", "email")
->with(['blog', 'blog.author', 'blog.comments' => function ($query) {
$query->where('comment', 'John is here');
}, 'blog.comments.owner'])
->whereHas('blog.comments', function ($query) {
$query->where('comment', 'John is Here');
})
->get();
My current json output is:
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"blog": [
{
"id": 1,
"created_at": "2021-04-09T18:08:06.000000Z",
"updated_at": "2021-04-09T10:33:03.000000Z",
"title": "First Blog",
"description": "Awesome",
"users_id": 1,
"cover": null,
"author": {
"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
},
"comments": [
{
"id": 1,
"comment": "John is here",
"blog_id": 1,
"user_id": 1,
"created_at": null,
"updated_at": null,
"owner": {
"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
}
}
]
},
{
"id": 6,
"created_at": "2021-04-12T07:41:43.000000Z",
"updated_at": "2021-04-12T08:01:18.000000Z",
"title": "Second Blog",
"description": "Awesome",
"users_id": 1,
"cover": "images/json_1618213303.png",
"author": {
"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
},
"comments": []
}
]
}
My expected output would be:
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"blog": [
{
"id": 1,
"created_at": "2021-04-09T18:08:06.000000Z",
"updated_at": "2021-04-09T10:33:03.000000Z",
"title": "First Blog",
"description": "Awesome",
"users_id": 1,
"cover": null,
"author": {
"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
},
"comments": [
{
"id": 1,
"comment": "John is here",
"blog_id": 1,
"user_id": 1,
"created_at": null,
"updated_at": null,
"owner": {
"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
}
}
]
}
]
}
Try this,
User::select("id", "name", "email")
->with([
'blog' => function ($query) {
$query->whereHas('comments', function ($query) {
$query->where('comment', 'John is Here');
});
},
'blog.comments' => function ($query) {
$query->where('comment', 'John is here');
},
'blog.author',
'blog.comments.owner'])
->get();
You should be applying the constraint on blog eager loading as well. Your query only filters comments of a blog
I have a collection that looks like this,
[
{
"id": 1,
"title": "Cooking",
"deleted_at": null,
"created_at": null,
"updated_at": null,
"listings": [
{
"id": 6,
"title": "Listing Number 1",
"slug": "listing-number-1",
"description": "Description",
"booking_details": "Booking Details",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:35:56.000000Z",
"updated_at": "2020-06-03T22:35:56.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 6
},
"assets": [],
"primary_image": []
},
{
"id": 7,
"title": "Listing Number 1",
"slug": "listing-number-1",
"description": "Description",
"booking_details": "Booking Details",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:36:10.000000Z",
"updated_at": "2020-06-03T22:36:10.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 7
},
"assets": [],
"primary_image": []
},
{
"id": 8,
"title": "Listing Number 1",
"slug": "listing-number-1",
"description": "Description",
"booking_details": "Booking Details",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:36:26.000000Z",
"updated_at": "2020-06-03T22:36:26.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 8
},
"assets": [],
"primary_image": []
},
{
"id": 9,
"title": "Listing Number 1",
"slug": "listing-number-1",
"description": "Description",
"booking_details": "Booking Details",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:36:42.000000Z",
"updated_at": "2020-06-03T22:36:42.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 9
},
"assets": [],
"primary_image": []
},
{
"id": 10,
"title": "Listing Number 1",
"slug": "listing-number-1",
"description": "Description",
"booking_details": "Booking Details",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:37:40.000000Z",
"updated_at": "2020-06-03T22:37:40.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 10
},
"assets": [],
"primary_image": []
},
{
"id": 11,
"title": "Listing Number 2",
"slug": "listing-number-2",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:46:31.000000Z",
"updated_at": "2020-06-03T22:46:31.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 11
},
"assets": [
{
"id": 3,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-2/primary-image-lg.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 11,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:46:33.000000Z",
"updated_at": "2020-06-03T22:46:33.000000Z"
},
{
"id": 4,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-2/primary-image-sm.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 11,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:46:33.000000Z",
"updated_at": "2020-06-03T22:46:33.000000Z"
}
],
"primary_image": [
{
"id": 3,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-2/primary-image-lg.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 11,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:46:33.000000Z",
"updated_at": "2020-06-03T22:46:33.000000Z"
},
{
"id": 4,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-2/primary-image-sm.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 11,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:46:33.000000Z",
"updated_at": "2020-06-03T22:46:33.000000Z"
}
]
},
{
"id": 12,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:50:31.000000Z",
"updated_at": "2020-06-03T22:50:31.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 12
},
"assets": [],
"primary_image": []
},
{
"id": 13,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T22:57:12.000000Z",
"updated_at": "2020-06-03T22:57:12.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 13
},
"assets": [],
"primary_image": []
},
{
"id": 15,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:00:49.000000Z",
"updated_at": "2020-06-03T23:00:49.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 15
},
"assets": [],
"primary_image": []
},
{
"id": 16,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:01:21.000000Z",
"updated_at": "2020-06-03T23:01:21.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 16
},
"assets": [],
"primary_image": []
},
{
"id": 17,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:01:26.000000Z",
"updated_at": "2020-06-03T23:01:26.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 17
},
"assets": [],
"primary_image": []
},
{
"id": 18,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:01:49.000000Z",
"updated_at": "2020-06-03T23:01:49.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 18
},
"assets": [],
"primary_image": []
},
{
"id": 19,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:02:19.000000Z",
"updated_at": "2020-06-03T23:02:19.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 19
},
"assets": [],
"primary_image": []
},
{
"id": 20,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:03:31.000000Z",
"updated_at": "2020-06-03T23:03:31.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 20
},
"assets": [],
"primary_image": []
},
{
"id": 21,
"title": "Listing Number 3",
"slug": "listing-number-3",
"description": "Description 1",
"booking_details": "Booking Details 1",
"cost": "25.00",
"active": 0,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:06:25.000000Z",
"updated_at": "2020-06-03T23:06:25.000000Z",
"pivot": {
"category_id": 1,
"listing_id": 21
},
"assets": [
{
"id": 5,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-3/primary-image-lg.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 21,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:06:26.000000Z",
"updated_at": "2020-06-03T23:06:26.000000Z"
},
{
"id": 6,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-3/primary-image-sm.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 21,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:06:27.000000Z",
"updated_at": "2020-06-03T23:06:27.000000Z"
}
],
"primary_image": [
{
"id": 5,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-3/primary-image-lg.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 21,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:06:26.000000Z",
"updated_at": "2020-06-03T23:06:26.000000Z"
},
{
"id": 6,
"type": "image",
"path": "https://xx-xxxx-xxxx-1.s3.eu-west-2.amazonaws.com/listing-number-3/primary-image-sm.jpg",
"is_primary": 1,
"assetable_type": "App\\Listing",
"assetable_id": 21,
"user_id": 2,
"deleted_at": null,
"created_at": "2020-06-03T23:06:27.000000Z",
"updated_at": "2020-06-03T23:06:27.000000Z"
}
]
}
]
}
]
I only want to see a collection that contains items that don't have empty assets array,
I have tried this,
$category = Category::whereHas('listings.assets')->with(['listings.assets', 'listings.primaryImage' => function($query){
$query->where('assets.is_primary', '=', 1);
}])->get();
return $category->filter(function($item){
foreach($item->listings as $i) {
return !empty($i->assets);
}
});
But this just returns an empty [] what am I doing wrong?
You are returning in your loop, so as soon as it finds listings that does not have assets it will break the loop and be false. Instead use contains(), that check if any of the elements, passes the given condition. If one does, it will return true. Therefor not breaking the loop on empty collections, as you do now.
return $category->filter(function($item){
return $item->listings->contains(function ($listing) {
return $listing->assets->isNotEmpty();
});
});
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 have an api ready that returns the following json response.
Response:
{
"success": true,
"conversation": [{
"id": 37,
"type": "1",
"name": "Sonali",
"created_at": "2019-02-18 13:26:10",
"updated_at": "2019-02-18 20:32:54",
"unread_count": 2,
"chat": {
"id": 357,
"conversation_id": "23",
"type": "text",
"sender_id": "37",
"receiver_id": "39",
"data": "{\"text\":\"hello....\"}",
"delivered_at": "2019-02-20 13:25:27",
"seen_at": null,
"created_at": "2019-02-20 13:25:10",
"updated_at": "2019-02-20 13:25:27",
"sender_name": "Sonali"
}
},
{
"id": 38,
"type": "1",
"name": "Raviraj",
"created_at": "2019-02-18 20:23:55",
"updated_at": "2019-02-18 20:32:47",
"unread_count": 0,
"chat": {
"id": 354,
"conversation_id": "22",
"type": "text",
"sender_id": "39",
"receiver_id": "38",
"data": "{\"text\":\"hey....\"}",
"delivered_at": null,
"seen_at": null,
"created_at": "2019-02-20 13:24:35",
"updated_at": "2019-02-20 13:24:35",
"sender_name": "Nitesh Kesarkar"
}
},
{
"id": 27,
"type": "1",
"name": "Rakesh",
"created_at": "2019-02-01 10:48:19",
"updated_at": "2019-02-07 11:35:10",
"unread_count": 1,
"chat": {
"id": 358,
"conversation_id": "21",
"type": "text",
"sender_id": "27",
"receiver_id": "39",
"data": "{\"text\":\"hello\"}",
"delivered_at": "2019-02-20 13:25:27",
"seen_at": null,
"created_at": "2019-02-20 13:25:24",
"updated_at": "2019-02-20 13:25:27",
"sender_name": "Rakesh Patil"
}
}
]
}
This response consists of list of users and their associated last chat message for currently logged in user. I want to sort this collection according to the latest message first. How can I do that?
Sorting should be based on the chat.created_at field.
Expected Result:
{
"success": true,
"conversation": [
{
"id": 27,
"type": "1",
"name": "Rakesh",
"created_at": "2019-02-01 10:48:19",
"updated_at": "2019-02-07 11:35:10",
"unread_count": 1,
"chat": {
"id": 358,
"conversation_id": "21",
"type": "text",
"sender_id": "27",
"receiver_id": "39",
"data": "{\"text\":\"hello\"}",
"delivered_at": "2019-02-20 13:25:27",
"seen_at": null,
"created_at": "2019-02-20 13:25:24",
"updated_at": "2019-02-20 13:25:27",
"sender_name": "Rakesh Patil"
}
},
{
"id": 37,
"type": "1",
"name": "Sonali",
"created_at": "2019-02-18 13:26:10",
"updated_at": "2019-02-18 20:32:54",
"unread_count": 2,
"chat": {
"id": 357,
"conversation_id": "23",
"type": "text",
"sender_id": "37",
"receiver_id": "39",
"data": "{\"text\":\"hello....\"}",
"delivered_at": "2019-02-20 13:25:27",
"seen_at": null,
"created_at": "2019-02-20 13:25:10",
"updated_at": "2019-02-20 13:25:27",
"sender_name": "Sonali"
}
},
{
"id": 38,
"type": "1",
"name": "Raviraj",
"created_at": "2019-02-18 20:23:55",
"updated_at": "2019-02-18 20:32:47",
"unread_count": 0,
"chat": {
"id": 354,
"conversation_id": "22",
"type": "text",
"sender_id": "39",
"receiver_id": "38",
"data": "{\"text\":\"hey....\"}",
"delivered_at": null,
"seen_at": null,
"created_at": "2019-02-20 13:24:35",
"updated_at": "2019-02-20 13:24:35",
"sender_name": "Nitesh Kesarkar"
}
}
]
}
UPDATE :
Adding these lines worked as expected. Thanks #JCode
$sorted = $chats->sortByDesc('chat.created_at');
$chats = $sorted->values()->all();
You are looking for the sortBy() method.
This will of course work if your JSON output can be turned into a collection via collect()—in a perfect scenario, your chat messages would be a model in Laravel.
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