Show only the latest record using laravel query builder - laravel

I have two tables a payments table and a tenants table. Each payments table can have many payments for a single tenant (one to many relationship)
Payments
id tenant_id amount
1 1 5000
2 1 6000
3 2 7000
4 2 8000
tenants
id name email
1 peter peter#info.com
2 grace grace#info.com
When i run the following in my controller
public function getPaymentsList(Request $request)
{
$payments = DB::table("payments")
->join('tenants','tenants.id','=','tenant_id')
->select('payments.id','payments.tenant_id','tenants.name','payments.rent_to')
->groupBy('tenant_id')->get()
;
return response()->json($payments);
}
}
I get json content of the oldest record in the payments table not the latest record.
[
{
"id": 1,
"tenant_id": 1,
"name": "peter",
"amount": "5000"
},
{
"id": 3,
"tenant_id": 2,
"name": "grace",
"amount": "7000"
},
]
The output i want is
[
{
"id": 2,
"tenant_id": 1,
"name": "peter",
"amount": "6000"
},
{
"id": 4,
"tenant_id": 2,
"name": "grace",
"amount": "8000"
},
]
How to improve the above query so that it can display the desired output?

you can use something like:
public function getPaymentsList(Request $request)
{
$payments = DB::table("payments")
->join('tenants','tenants.id','=','tenant_id')
->select('payments.id','payments.tenant_id','tenants.name','payments.rent_to')
->groupBy('tenant_id')->latest()->first()
;
return response()->json($payments);
}
}
check the larvel documents for useing latest()->first()

Related

How to select not null datas using whereHas in 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();

Laravel How to orderby()->first() in eager loading

I have this query which is working just fine except when i call ->first() function on it, the data from certain relations disappear.
What I am trying to achieve:
I am trying to get the sp_services where price is lowest. The first object (id: 1) in data array has two sp_services, the second object inside data array (id: 13) has only one sp_services. When i do $query->orderBy('sp_services.price', 'DESC')->first(); The object from first one is there but the second one where (id: 6, name: car wash) disappears and there is only empty array.
In the below mentioned JSON I'm only showing the relevant data here. Can anyone please tell me what am i doing wrong here ? and why is it not working. Also is there a better way to achieve desired result.
Query:
$branchesQuery = SpBranch::query();
$branchesQuery->where('status', true);
$branchesQuery->when($request->filled('price'), function($query) use($request) {
return $query->with(['service_provider' => function($query) use($request) {
$query->whereHas('sp_services')
->with(['sp_services' => function($query) use($request) {
$query->orderBy('sp_services.price', 'DESC'); //->first();
}]);
}]);
});
$branches = $branchesQuery->paginate($perPageLimit);
return $branches;
Models:
class SpBranch extends Model
{
public function service_provider()
{
return $this->belongsTo(ServiceProvider::class, 'sp_id');
}
}
class ServiceProvider extends Model
{
public function sp_services()
{
return $this->hasMany(SpService::class, 'sp_id', 'id');
}
}
JSON:
{
"data": [
{
"id": 1,
"sp_id": 1,
"name": "Branch 01",
"status": 1,
"service_provider": {
"id": 1,
"name": "Service Provider 01",
"sp_services": [
{
"id": 3,
"sp_id": 1,
"branch_id": null,
"name": "Service 03",
"price": 50
},
{
"id": 4,
"sp_id": 1,
"branch_id": null,
"name": "Service 04",
"price": 70
}
]
}
},
{
"id": 13,
"sp_id": 5,
"name": "Branch 13",
"status": 1,
"service_provider": {
"id": 5,
"name": "Service Provider 05",
"sp_services": [
{
"id": 6,
"sp_id": 5,
"branch_id": null,
"name": "car wash",
"price": 300
}
]
}
}
]
}
You cannot order or group by a eager loaded table on database, because what WITH method does is that it fires a new query meaning that is not connected to the first one at all, what you can do is you can order or group them in collections meaning after the data is fetch from db you can order them, I think function is called ->sortBy() which will order by the field you want, but it will cost you on performance. If performance is important in your case, you can always use joins to join both tables which will enable you order results directly from database.
class ServiceProvider extends Model
{
public function sp_services()
{
return $this->hasMany(SpService::class, 'sp_id', 'id')->orderBy('price', 'asc');
}
}

ReferenceManyFields (One to Many Relationship)

I am working on a project where I have to create one to many relationships which will get all the list of records referenced by id in another table and I have to display all the selected data in the multi-select field (selectArrayInput). Please help me out in this, if you help with an example that would be great.
Thanks in advance.
Example:
district
id name
1 A
2 B
3 C
block
id district_id name
1 1 ABC
2 1 XYZ
3 2 DEF
I am using https://github.com/Steams/ra-data-hasura-graphql hasura-graphql dataprovider for my application.
You're likely looking for "nested object queries" (see: https://hasura.io/docs/1.0/graphql/manual/queries/nested-object-queries.html#nested-object-queries)
An example...
query MyQuery {
district(where: {id: {_eq: 1}}) {
id
name
blocks {
id
name
}
}
}
result:
{
"data": {
"district": [
{
"id": 1,
"name": "A",
"blocks": [
{
"id": 1,
"name": "ABC"
},
{
"id": 2,
"name": "XYZ"
}
]
}
]
}
}
Or...
query MyQuery2 {
block(where: {district: {name: {_eq: "A"}}}) {
id
name
district {
id
name
}
}
}
result:
{
"data": {
"block": [
{
"id": 1,
"name": "ABC",
"district": {
"id": 1,
"name": "A"
}
},
{
"id": 2,
"name": "XYZ",
"district": {
"id": 1,
"name": "A"
}
}
]
}
}
Setting up the tables this way...
blocks:
districts:
Aside: I recommend using plural table names as they are more standard, "districts" and "blocks"

hasManyThrough is returning only one result instead of all

The platform has a many to many relationship, where the table assigned_users holds all Users assigned to CalendarEvents.
I need to fetch, through CalendarEvents, the assigned users as an object, showing each user's information. So, I want to access the User through AssignedUsers, because I wanna fetch all the users related to that event.
public function assignedUsers()
{
return $this->hasManyThrough(Users::class, AssignedUsers::class, 'user_id', 'id');
}
It works, but it shows only the first user in the table. I want to show all of them. Currently there are 3.
"assigned_users": [
{ id: 1, ... }
]
If I do the following:
public function assignedUsers()
{
return $this->belongsToMany(Users::class, "assigned_users", "event_id", "event_id");
}
It will fetch 3 results, but all the information will be from the same user. It will repeat the same user 3 times. Changing both the event_id to user_id and id, and id and user_id will have the same result.
"assigned_users": [
{ id: 1, ... },
{ id: 1, ... },
{ id: 1, ... },
...
]
What I am trying to accomplish is the following result:
{
"status": "200",
"success": true,
"data": [
{
"event_id": 1,
"event_key": "EB1M7OGJRPW0",
"calendar_id": 4,
"start_at": "2018-01-01 00:00:00",
"end_at": "2018-01-31 00:00:00",
"location": "123 Lorem, Ipsum",
"event_name": "Event #1",
"description": "Lorem ipsum dolor sit amet",
"added_at": "2018-02-07 09:07:31",
"created_by": {
"id": 4,
"name": "Foo Bar",
"email": "foobar92#gmail.com",
"first_name": "Foo",
"last_name": "Bar",
"status": "active",
"is_activated": 0,
"created_at": "2018-02-07 09:06:49",
"updated_at": "2018-02-07 09:06:49"
},
"assigned_users": [
{
"id": 1,
...
},
{
"id": 2,
...
},
{
"id": 3,
...
},
...
]
}
]
}
This is not the case of hasManyThrough relationship. Here assigned_users is a pivot table so you just need a belongsToMany relationship defined
public function assignedUsers()
{
return $this->belongsToMany(Users::class, 'assigned_users', 'event_id', 'user_id');
}
and for this to work, you may have to change the calendar_events table's primary key to id (instead of event_id)

Laravel eager loading with field limit

I have three tables:
users
id
name
role_id
password
...
role_user
id
role_id
user_id
roles
id
name
slug
...
Now I want to get a user list with users.id,users.name,
roles.id. That's my code:
$query = User::with(['roles'=>function($q){
$q->lists('role_id');
}])->get(['id','name']);
the response like that
{
"id": "1",
"name": "aaaa",
"roles": []
},
{
"id": "2",
"name": "bbbb",
"roles": []
},
when i don't pass the array to get method,the response like that:
{
"id": 1,
"name": "aaaa",
"password": "xxxxxxx",
"created_at": "2015-05-07 14:15:00",
"roles": [
{
"role_id": 2,
"pivot": {
"user_id": 1,
"role_id": 2
}
}
]
},
{
"id": 2,
"name": "bbbb",
"password": "xxxxxxx",
"created_at": "2015-05-05 14:15:00",
"roles": [
{
"role_id": 2,
"pivot": {
"user_id": 2,
"role_id": 2
}
}
]
},
But i do not want the password,created_at and pivot field. How to filter these?
To get relations you need to get the foreign keys. Try this
$query = User::with(['roles'=>function($q){
$q->get(['id', 'name', 'slug']);
}])->get(['id','name', 'role_id']);
As for the pivot table, can you post you roles relation in the user model?
Edit
Add this to your user model to hide the pivot properties
protected $hidden = ['pivot'];
You can add more fields to that property to remove them from all queries.

Resources