How to select not null datas using whereHas in LARAVEL - laravel

Let me make it simple, In my models, I have countries and cities. My goal is, I want to select and display only the cities that has shops and it should also have datas and the employees should not be NULL
In the below given array, my city has two shops where id - 13 that doesn't have any datas and id - 19 which is having data.
[
{
"id": 1,
"created_at": "2022-06-02T06:07:31.000000Z",
"updated_at": "2022-06-02T06:07:31.000000Z",
"name": "Niue",
"cities": [
{
"id": 13,
"created_at": "2022-06-02T06:07:44.000000Z",
"updated_at": "2022-06-02T06:07:44.000000Z",
"country_id": 1,
"name": "North Michealbury",
"shops": [] //empty
},
{
"id": 19,
"created_at": "2022-06-02T06:07:44.000000Z",
"updated_at": "2022-06-02T06:07:44.000000Z",
"country_id": 1,
"name": "Millsmouth",
"shops": [
{
"id": 1,
"created_at": "2022-06-02T06:14:37.000000Z",
"updated_at": "2022-06-02T06:14:37.000000Z",
"city_id": 19,
"name": "Roberts-Okuneva",
"employees_count": 146
}
]
}
]
}
]
This is the code that, I have written in my controller. The goal is, I want to select and show only those cities that has shops with employees.
return Country::with(['cities','cities.shops'=>function($employee){
$employee->withCount('employees')->where('city_id',19);
}])->whereHas('cities',function($city){
$city->where('cities.id',19);
})->get();
These are my models, each of them has a hasMany relationship
Country model
public function Cities(){
return $this->hasMany(City::class);
}
City model
public function shops(){
return $this->hasMany(Shop::class);
}
Shop model
public function employees(){
return $this->belongsToMany(User::class,'shop_employees','shop_id','employee_id');
}

You can try
//Get all cities which have shops having at least one employee
return Country::with([
'cities',
'cities.shops' => function($query) {
$query->withCount('employees');
}
])
->whereHas('cities', function($query) {
$query->whereHas('shops', function($query) {
$query->has('employees');
});
})
->get();

i found another solution querying with clause.
return Country::whereHas('cities',function($cities){
$cities->where('country_id',1);
})->with(['cities'=>function($shops){
$shops->has('shops')->where('cities.country_id',1);
},'cities.shops'=>function($employee){
$employee->withCount('employees');
}])->get();

Related

Laravel Eloquent with query

I want to pull the invoice detail with the "id" number of 3 in the tools table from the "invoice_details" table. "plate" "invoice_details" relationship "plate_no" in the "trucks" table, but when I pull the data, a different data is coming, where am I making a mistake?
public function getTruck($id)
{
$truck = Truck::find($id)->with(['truckHistory'])->first();
return $truck;
}
Truck extends Model
public function truckHistory(){
return $this->hasMany(InvoiceDetail::class,'plate_no','plate');
}
Normally the incoming data is TRUE when I don't write a with condition
THIS IS TRUE
$truck = Truck::find(3);
{
"id": 3,
"plate": "73AD323",
"created_at": "2021-10-13T08:38:23.000000Z",
"updated_at": "2021-10-13T08:38:23.000000Z"
}
When I type a condition, the id is wrong.
$truck = Truck::find(3)->with(['truckHistory'])->first();
{
"id": 1,
"plate": "33EER36",
"created_at": "2021-10-11T06:01:29.000000Z",
"updated_at": "2021-10-11T06:01:29.000000Z",
"truck_history": [
{
"id": 1,
"plate_no": "33EER36",
"created_at": "2021-10-11T06:03:16.000000Z",
"updated_at": "2021-10-11T06:03:16.000000Z"
},
{
"id": 2,
"plate_no": "33EER36",
"created_at": "2021-10-11T06:06:18.000000Z",
"updated_at": "2021-10-11T06:06:18.000000Z"
}
]
}
Using first will return the first record of the trucks table, to do so you can use
Truck::with(['truckHistory'])->find($id);

Filter Data with Pivot Table Laravel Eloquent

I want to filter users based on their subscription_status which s stored in a pivot table.
I have Three tables users , subscription_packages , subscription_package_user
$user=User::with(['studentDetails','subscriptionsSatus.courses'])
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
this code return the response is
[
{
"id": 44,
"first_name": "Abcd Test",
"last_name": "Test lastname",
"student_details": null,
"subscriptions_satus": [
{
"id": 1,
"name": "Gold",
"price": 3000,
"user_id": "2"
"pivot": {
"user_id": 44,
"subscription_package_id": 1,
"subscription_status": "on_free_trial",
"expires_on": null,
"id": 9
},
"courses": [
{
"id": 18,
"title": "English Grammar for Class 3",
"price": 400,
"strikethrough_price": null,
"status": "draft",
"user_id": 2,
"image": "http://127.0.0.1:8000/courses/1615702915.png",
"description": null,
"pivot": {
"subscription_package_id": 1,
"course_id": 18,
}
}
]
}
]
}]
i want to return only users who having subscription_status =$filter.
$filter='acive'or 'on_free_trail'
my model is
public function subscriptionsSatus()
{
return $this->belongsToMany(SubscriptionPackage::class)->withTimestamps()->withPivot('subscription_status','expires_on','id');
}
I havetried
$filter=$request->input('filter')??"active";
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
But Got error Column not found 'pivot'
You need to use wherePivot along with the orWhere like below:
public function subscriptionsStatus()
{
return $this->belongsToMany(SubscriptionPackage::class)
->withTimestamps()
->withPivot('subscription_status','expires_on','id')
->wherePivot(function($q){
return $q->where('subscription_status','=','active')
->orWhere('subscription_status','=','on_free_trail');
});
}
Update
Or in your controller:
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->withPivot('subscription_status')
->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();

Is it possible to apply condition inside the map function of Laravel?

I wanted to apply some condition in foodOrders. Is it possible to apply condition inside map function that acts as where $foodOrder->foodOrders->where('invoice_id',null)->get();
public function getTableList(Request $request){
$skip =$request->skip;
$limit=$request->limit;
$totaltable = Table::get()->count();
$table = Table::skip($skip)->take($limit)->orderBy('id', 'DESC')->get();
$table->map(function($foodOrder){
$foodOrder->foodOrders;
});
}
Below is the output that this query returns. But I only want the data with null invoice_id
{
"success": true,
"message": "Lists of Table.",
"data": [
{
"id": 2,
"table_number": "TN02",
"food_orders": [
{
"id": 16,
"food_items_id": 1,
"table_id": 2,
"invoice_id": null,
"quantity": 2,
"price": "2000.00"
},
{
"id": 17,
"food_items_id": 2,
"table_id": 2,
"invoice_id": null,
"quantity": 3,
"price": "150.00"
}
]
},
{
"id": 1,
"table_number": "TN01",
"created_at": "2020-10-25 10:44:31",
"updated_at": "2020-10-25 10:44:31",
"food_orders": [
{
"id": 14,
"food_items_id": 1,
"table_id": 1,
"invoice_id": 39,
"quantity": 1,
"price": "2000.00"
}
]
}
]
}
Not the best approach, bu this should do the trick
$table->map(function($foodOrder){
$foodOrder->foodOrders=$foodOrder->foodOrders()->where('invoice_id',null)->get();
});
Note the scopes, you need them to apply where condition. And we say = so the further changes are propagated.
I think what you need to use is a filter and not a map. Or am I wrong ?
You can filter out the whitelisted records for the food_orders.
$table->map(function($record){
$record->food_orders = collect($record->food_orders)
->filter(fn($foodOrder) => is_null($foodOrder->invoice_id));
return $record;
});
From the output data you have shown above it seems that the food_orders is a hasMany relation on the model, so it would be easy to filter out the relation when eager loading
Assuming that Table model has a relation defined for food_orders
class Table extends Model
{
public function food_orders()
{
return $this->hasMany(FoodOrder::class);
}
//... rest of the class code
}
You can constrain the related models when eager loading
$table = Table::with([
'food_orders' => fn($query) => $query->whereNull('invoice_id')
])
->skip($skip)
->take($limit)
->orderBy('id', 'desc')
->get();

Laravel eloquent get related model as column_name => value

I have a Product table related with Image table, one to many relationship.
How do I get Image records not as array? Instead, return only 1 Image record as column_name: value
This code:
$products = $request->user()->products()->orderBy('id', 'desc')->with(['images' => function($query) {
$query->where('featured', 1)->limit(1);
}])->get();
Is returning data like this :
{
"id": 13,
"name": "Shoes",
"price": "3.00",
"stock": 5,
"pivot": {
"user_id": 7,
"product_id": 13
},
"images": [
{
"id": 5,
"file": "5da9d9b493403.png",
"featured" 1,
"pivot": {
"product_id": 13,
"image_id": 5
}
}
]
}
}
How to make it return like this?
{
"id": 13,
"name": "Shoes",
"price": "3.00",
"stock": 5,
"pivot": {
"user_id": 7,
"product_id": 13
},
"images": "5da9d9b493403.png"
}
}
You can append a custom accessor that gets the first image from the relationship
In the Product model
protected $appends = ['images'];
public function getImagesAttribute()
{
return $this->images()->where('featured', 1)->first()->file;
}
public function images()
{
return $this->hasMany('App\Image');
}
Then just return the query without eager loading
$products = $request->user()->products()->orderBy('id', 'desc')->get();
Hope this helps
In the Product model
protected $appends = ['images'];
public function images()
{
return $this->hasMany('App\Image')->select(['name'])->first();
}
select the name only and return first relation

Laravel get only one column from relation

I have a table user_childrens whose contains id_parent and id_user.
I'm trying to list all childrens of the parent with this:
code:
//relation in model via belongsTo
$idparent = auth('api')->user()->id;
$list = UserChildren::where('id_parent',$idparent)
->with('child:id,name,email')
->get();
return $list->toJson();
The return is:
[
{
"id": 1,
"id_parent": 1,
"id_user": 1,
"created_at": null,
"updated_at": null,
"child": {
"id": 1,
"name": "Mr. Davin Conroy Sr.",
"email": "prempel#example.com"
}
},
{
"id": 4,
"id_parent": 1,
"id_user": 2,
"created_at": null,
"updated_at": null,
"child": {
"id": 2,
"name": "Krystel Lehner",
"email": "cernser#example.net"
}
}
]
But it's API so I want only the child column like:
[
{
"id": 1,
"name": "Mr. Davin Conroy Sr.",
"email": "prempel#example.com"
},
{..}
]
UserChildren Model:
public function child() {
return $this->belongsTo('App\User','id_user','id');
}
I know that I could do this via .map() on collection but maybe there is other solution already on this query
You can use this code
$idparent = auth('api')->user()->id;
$childs = User::whereHas('user_childrens', function ($query) use ($idparent) {
$query->where('id_parent', $idparent);
})->get(['id', 'name', 'email']);
dd($childs->toJson());
And User model define user_childrens relation.
public function user_childrens()
{
return $this->hasMany('App\UserChildren','id_user','id');
}
See also docs https://laravel.com/docs/5.5/eloquent-relationships#querying-relationship-existence

Resources