how to join 4 tables in php laravel? - php

I Want to extract data from 4 tables .
like sname,cgpa,Group_Cgpa,Room_No and Hostel Name.
Relation of table is as follows.
AllotmentApps has : id,sname,cgpa and grpID (from Group id Table) columns.
Groups has : id,Group_CGPA
Room has : id, HostelID (From Hostel) and ResidentID (From Group id).
Hostels has: id, Name, Total_Rooms.
I'm facing problem in joining the tables. Join with AllotmentApps and Groups works fine, but problem occurs when I joined the Room and Hostel Table.
Join of AllotmentApps and Groups
public function FinalList()
{
$allot_apps = AllotmentApps::join('Groups','Groups.id','AllotmentApps.grpID')->orderBy('Groups.Group_CGPA', 'Desc')->get()->groupBy(
function($item) {
return $item->grpID;
}
) ->take(3);
Join of 4 Tables
public function FinalList()
{
$allot_apps = AllotmentApps::select('sname','cgpa','Group_CGPA','Hostel_Name')->join('Groups','Groups.id','AllotmentApps.grpID')->join('Hostels','Hostels.id','Hostels.HostelID')->join('Rooms','Rooms.id','Hostel.HostelID')->orderBy('Groups.id', 'Asc')->get()->groupBy(
function($item) {
return $item->grpID;
}
) ->take(3);

Try This
$allot_apps=AllotmentApps::select('AllotmentApps .sname','AllotmentApps .cgpa','Groups.Group_CGPA','tablename.Hostel_Name')
->join('Groups','Groups.id','=','AllotmentApps.grpID')
->join('Rooms','Rooms.ResidentID','=','Groups.id')
->join('Hostels','Hostels.id','=','Rooms.HostelID')
->orderBy('Groups.id', 'Asc')
->groupBy()
->get();

public function FinalList()
{ $capasity = Rooms::selectRaw('count(id) as c')->count();
$allot_apps = Rooms::select('Hostel_Name','Rooms.id','Groups.Group_CGPA','AllotmentApps.sname','AllotmentApps.cgpa')->join('Hostels','Hostels.id','Rooms.HostelID')->join('Groups','Groups.id','Rooms.ResidentID')->join('AllotmentApps','Groups.id','AllotmentApps.grpID')->orderBy('Groups.Group_CGPA', 'Desc')->get()->groupBy(
function($item) {
return $item->grpID;
}
) ->take($capasity);
// return $allot_apps;
return view('x', compact('allot_apps'));
}

Related

PHP/Laravel: SELECT and JOIN two tables

I have three tables as shown below and trying to join the expenses and allowance table on customers. I have tried using the code below but it returns null on expenses and allowances. I tried inner JOIN as well but didn't work.
I have tables as below:
customers(id, user_id, full_name)
expenses(id, customer_id, name, amount)
allowances(id, customer_id, name, quantity)
And i tried using the code below but doesn't work.
$logs = Customer::query()
->select([
"customers.id",
"customers.full_name",
"expenses.name as expenses_name",
"expenses.amount as expenses_amount",
"allowances.name as allowance_name",
"allowances.quantity as allowance_quantity"
])
->join('expenses', function (JoinClause $join) {
$join->type = 'left outer';
$join->on('expenses.customer_id', 'customers.id');
})
->join('allowances', function (JoinClause $join) {
$join->type = 'left outer';
$join->on('allowances.customer_id', 'customers.id');
});
return $logs->toJson();
I want output as:
{
id:'',
full_name:'',
expenses:{{expenses_name, expenses_amount},{expenses_name, expenses_amount}},
allowances:{{allowance_name, allowance_quantity},{allowance_name, allowance_quantity}}
}
Use the following Code:
$logs = Customer::select([
"customers.id",
"customers.full_name",
"expenses.name as expenses_name",
"expenses.amount as expenses_amount",
"allowances.name as allowance_name",
"allowances.quantity as allowance_quantity"
])
->leftjoin('expenses', 'customers.id','=','expenses.customer_id')
->leftjoin( 'allowances','customers.id','=','allowances.customer_id')
->get();
You can also use eloquent relationship.
define relations in Customer Model
public function expenses()
{
return $this->hasMany(Expense::class);
}
public function allowances()
{
return $this->hasMany(Allowance::class);
}
get Customers with relationship
$logs = Customer::with(['expenses','allowances'])->get();

Retrieving distinct relationships of relationships using Eloquent in Laravel

Lets assume I have a model for: Race, Participant, Team
And these relations: Race 1-N Participant N-1 Team
See in another way :
races 1 - N participants
teams 1 - N participants
In Laravel terms:
/* Inside Race model */
public function participants()
{
return $this->hasMany(Participant::class);
}
/* Inside Team model */
public function participants()
{
return $this->hasMany(Participant::class);
}
/* Inside Participant model */
public function race()
{
return $this->belongsTo(Race::class);
}
public function team()
{
return $this->belongsTo(Team::class);
}
In the participants table, It looks like this:
id | team_id | race_id | [a lot of other columns...]
------------------------------
1 | 1 | 1 |
2 | 1 | 1 |
3 | 2 | 1 |
4 | 2 | 1 |
In the above example, I know that the race ID 1 has 2 teams.
I can count them by doing this:
$race = Race::find(1);
$number = $race->participants()->distinct()->count('team_id');
The problem
Counting the number of teams is cool, but I want to access to the list of corresponding Team model instances, so that I can use them for further operations (within a foreach loop for example).
I tried a lot of things without success.
Something like this:
$teams = $race->participants()->distinct()->[...] // Don't know what to put here
The working equivalent SQL query is:
SELECT teams.* FROM teams
INNER JOIN participants ON participants.team_id = teams.id
INNER JOIN races ON races.id = participants.race_id
WHERE races.id = 1
GROUP BY teams.id
Resulting in this:
When the participants table contains this:
I want to know if I can do it with Eloquent instead of using Query/Builder DB:: methods directly ?
EDIT 1
My closest result:
$race->participants()->distinct()->get('team_id')
And then using this list of team_id I can access to the teams using Team::find([list of IDs]) but it looks greedy to me.
EDIT 2
I forgot some information:
The participants.team_id column is NULLABLE because:
There are races with teams of participants
There are races with participants (without team)
I don't think you can easily access to it through the $race instance.
But, you can use the whereHas method on the Team model:
$race = Race::find(1);
$teams = Team::whereHas('participants', function ($query) use ($race) {
$query->where('race_id', $race->id);
})->get(); // ->count() also works
See documentation
To get distinct teams from a race model, you could add a many to many relationship between Race and Team with Participant acting as the pivot.
For example,
/* Race */
public function teams()
{
return $this->belongsToMany(Team::class, 'participants', 'race_id', 'team_id');
}
/* Team */
public function races()
{
return $this->belongsToMany(Race::class,'participants', 'team_id', 'race_id');
}
Then, you could just do this
$race = Race::find($id);
$teams = $race->teams()->distinct()->get();
to get a list of distinct teams for the race.
And since we set up the relationship on both models, you can now also get distinct races for each team by doing
$team = Team::find($id);
$teams = $team->races()->distinct()->get();
First, let's improve your eloquent relations.
// Race
public function teams()
{
return $this->hasMany(Team::class);
}
public function withoutTeamParticipants() // change name that suits you
{
return $this->hasMany(Participant::class);
}
// Team
public function participants()
{
return $this->hasMany(Participant::class); // In this case make sure that participant.race_id is null
}
// Participant
public function team()
{
return $this->belongsTo(Team::class); // When no team, then participant.team_id is null
}
public function race()
{
return $this->belongsTo(Race::class);
}
To access list of participants of a given race:
$race = Race::where('id', 1)->with('teams.participants', 'withoutTeamParticipants')->get();
In your blade you can further use this as:
// List of participants without a team
#foreach ($race->withoutTeamParticipants as $participant)
{{ $participant->name }}
#endforeach
// List of participants that are with a team
#foreach ($race->teams as $team)
#foreach ($team->participants as $participant)
{{ $participant->name }}
#endforeach
#endforeach
You can directly use hasManyThrough relationship inside Race model for fetching distinct teams associated with the race.
public function distinctTeams()
{
return $this->hasManyThrough(Team::class, Participant::class, 'race_id', 'id', 'id', 'team_id')->distinct();
}
Now, you can loop over the teams of a race by using $race->distinctTeams
Hopefully this helps.

Laravel Join query is not working for 4 tables

I have 4 tables
Table Name : Clinics
Fields: clinicID , clinicName
Table Name : locations
Fileds: locationID, clinicID,locationname
Table Name : Services
Fields: ServiceId , ServiceName
Table Name: LocationServices
Fields: locationServiceID, locationID , ServiceId
My requiremnt is that when i pass clinicID, i need to retrive Corresponding clinics service name, there may be more than one.
But when i tried join query is not working
Following is my code in controller
public function showClinic($id)
{
$clinic = Clinic::find($id);
$locations = Location::where('clinicID', $id)->get();
$locationsservices=\App\Clinic::with('locations');
var_dump($locationsservices);
die();
return view('clinic.show')->with(['locations' => $locations ,'clinic'=>$clinic]);
}
You can get this details by using relationships.
In the Clinic model,add
public function locations()
{
return $this->belongsTo('App\Models\Locations','clinicID','clinicID');
}
In the Locations model,add,
public function location_services()
{
return $this->hasOne('App\Models\LocationServices','locationID','locationID');
}
On the LocationServices model,
public function services()
{
return $this->hasOne('App\Models\Services','ServiceId','ServiceId');
}
You can get the result by,
$clinic_info = Clinic::find($id);
if(isset($clinic_info->locations))
{
if(isset($clinic_info->locations->location_services))
{
if(isset($clinic_info->locations->location_services->services))
{
echo $clinic_info->locations->location_services->services->ServiceName;
}
}
}
Reference Maybe HelpFull for You
Multi Joins
$data = DB::table('city')
->join('state', 'state.state_id', '=', 'city.state_id')
->join('country', 'country.country_id', '=', 'state.country_id')
->select('country.country_name', 'state.state_name', 'city.city_name')
->get();
return view('join_table', compact('data'));

JOINS with Many to Many Relationship - Laravel

I have two tables in a many to many relationship countries and teams table. In my country table, there is president_id. Now i want to get teams that belong to that president_id using a join query but i am not able to achieve this.
How can i achieve selecting all teams belonging to a particular president?
PS: Newbie with laravel
Country
public function teams()
{
return $this->belongsToMany('App\Team');
->withTimestamps();
}
Team
public function countries()
{
return $this->belongsToMany('App\Country')
->withTimestamps();
}
Controller
$teams = Team::all()->with('countries')->where('president_id,1)->first();
$getTeams = $teams->pluck('id')->toArray();
Your can get all teams that has countries with some president_id like this:
$president_id = 1;
$teams = Team::whereHas('countries',function($q)use($president_id){
$q->where('president_id',$president_id);
})->get();

How define relation hasManyThrough

I have tables:
users
- id
- name
- company_id
companies
- id
- company_name
watched_objects
- id
- user_id
- object_id
- type
Now I want to get all watched companies for a user.
So query should looks:
SELECT
companies.*
FROM companies
JOIN watched_objects ON watched_objects.object_id = companies.id
WHERE watched_objects.user_id = 1
How should I define relations?
I try this:
class User
{
public function watched()
{
return $this->hasManyThrough('App\Company', 'App\WatchedObject', 'user_id', 'id');
}
}
But query is:
SELECT
companies.*,
watched_objects.user_id
FROM companies
INNER JOIN watched_objects ON watched_objects.id = companies.id
WHERE watched_objects.user_id = 1
How I can change watched_objects.id to watched_objects.object_id.
If your treating object_id as company id, then the relation is considered to be many to many. Then table watched_objects will be the third table kept the relation of user and company.
class User {
public function watched() {
return $this->belongsToMany('App\Company', 'watched_objects', 'user_id', 'object_id');
}
}
In order to find the watched companies of user 1, you can use the following code.
$watched_companies = User::find(1)->watched;
To get all watched companies by a user you can do like this:
$watches=WatchedObject::where(['user_id'=>Auth::user()->id])->with('company')->get();
foreach($watches as $watch)
{
print_r($watch->company->company_name);
}
Relation:
Company hasMany watched objects:
public function watches()
{
return $this->hasMany('App\WatchedObject','object_id');
}
and belongsTo in watchedObject Model:
public function company()
{
return $this->belongsTo('App\Company','object_id');
}

Categories