laravel join three tables - laravel

I have three tables that are as follows:
invent_accessory
id,code,detail,is_length
invent_price_accessory
id,invent_accessory_id_fk,price,color
invent_price_accessory_length
id,invent_accessory_id_fk,price,color
how do i combine these three tables so that i can get id,code,detal,is_length,price,color
i have done following but it doesnt not return any data:
public function getAccessoryInventPrice(){
$accessory=DB::table('invent_accessory')
->select('invent_accessory.id as accessory_id')
->join('invent_price_accessory','invent_price_accessory.invent_accessory_id_fk','=','invent_accessory.id')
->join('invent_price_accessory_length','invent_price_accessory_length.invent_accessory_id_fk','=','invent_accessory.id')
->get();
return $accessory;
}
I am guessing that I have to do Union between invent_price_accessory and invent_price_accessory_length first then join with invent_accessory? How do i do this? pls help.

My guess was right!! i was able to solve this by:
public function getAccessoryInventPrice(){
$data1=\DB::table('invent_price_accessory')->select('accessory_code_id','color_id','rate');
$data2=\DB::table('invent_price_acc_length')->select('accessory_code_id','color_id','rate')
->union($data1);
$query= \DB::table(\DB::raw("({$data2->toSql()}) as invent_price"))
->join('invent_accessory','invent_price.accessory_code_id','=','invent_accessory.id')
->join('invent_color','invent_price.color_id','=','invent_color.id')
->select('invent_accessory.id','code','sl_detail','is_length','rate','invent_color.name')
->orderBy('invent_accessory.id','asc')
->get();
return $query;
}

Related

Does "where" works with mutattors in eloquent?

I have a mutattor in an eloquent model that generates a "status" atribute.
public function getStatusAttribute(){
if(){
return "enabled";
}
else
{
return "disabled";
}
}
Can I use?
$query = Anuncio::query();
$query->where('status', "enabled" );
return $query->get();
I seems that I cannot. I getting "status" column not defined. How can I get around this problem?
No doesn't works it works on model level
you can use after query from database in collection result
No, when you are doing a query you are asking the database, therefor there needs to be a column status.
There is a way, retrieve x elements from the database and use the Laravel Collection method where(). This is not optimal if you have many elements in teh database, it will retrieve all of them.
Anuncio::all()->where('status', 'enabled')->all();

Laravel 5 hasMany relation returning incorrect relations

I have a Yard model and Treatment model, I am using the following hasMany relationship to return treatments that are currently active:
public function activeTreatments() {
return $this->hasMany('App\Models\Treatment')
->where(function ($q) {
$q->where('expires_at','>=', Carbon::now('Pacific/Auckland'))
->where('completed_at','>', Carbon::now('Pacific/Auckland'));
})
->orWhere('completed',false);
}
For some reason when I add the ->orWhere('completed',false) the query returns all treatments not just the treatments associated with the specific yard. What am I doing wrong here?
It's hard to say exactly what is going on without inspecting the SQL being generated.
Wherever you are using this code, you could chain a toSql() on the end to see what the query looks like (use this where you would use a get()). Or you could enable the query log to see what is being queried.
Given the symptoms, it is likely that the orWhere() is negating a condition used to filter the models.
Try nest the orWhere() inside the current where() statement:
public function activeTreatments() {
return $this->hasMany('App\Models\Treatment')
->where(function ($q) {
$q->where(function($q), {
$q->where('expires_at','>=', Carbon::now('Pacific/Auckland'))
->where('completed_at','>', Carbon::now('Pacific/Auckland'));
})->orWhere('completed',false);
});
}

Laravel return eloquent result where it matches all ids not just a couple

I can't wrap my head around this for some reason even though it seems the answer is right in front of me.
I have 3 tables, rentals, amenitiesand amenities_rentals
Amenities are things like air conditioning, staff ect.
The amenities_rentals has rentail_id, amenities_id. This table is basically a reference table that connects rentals to amenities.
In a search a user can narrow down rentals by checking off certain amenities. As of now its giving me all the rentals that have at leas one of the checked off options. I need it to narrow down to only rentals that have ALL of the chosen amenities. This is what I have, this is not only not pulling the info correct but I know there is a better way to do it.
if($request->has('amenities'))
{
$rental_ids = AmenitiesRentals::select('rental_id')
->whereIn('amenities_id',$request->amenities)
->distinct()
->get();
$builder->whereIn('rentals.id', $rental_ids->toArray());
}
The rest of the builder works fine.
As Kamal Paliwal suggested, define a BelongsToMany relationship in your Rental model:
public function amenities() {
return $this->belongsToMany(Amenity::class, 'amenities_rentals', 'rental_id', 'amenities_id');
}
Then use whereHas():
$amenities = $request->amenities;
$rentals = Rental::whereHas('amenities', function ($query) use ($amenities) {
$query->whereIn('amenities.id', $amenities);
}, '=', count($amenities))->get();
You should create a many relationship between rentals and amenities like below:
public function amenities()
{
return $this->belongsToMany(\AmenityModel::class, 'amenities_rentals', 'rental_id', 'amenities_id');
}
Then while applying filter you can add it in this way:
$amenitiesIds = $request->amenities;
RentalsModel::with('amenities')->whereHas('amenities', function ($q) use ($amenitiesIds) {
$q->whereIn('amenities_id', $amenitiesIds);
})
Hope this might help you.
You should select rentals that has the count of amenities ids same as the size of amenities array from your request by grouping rentals by amenities count.
Here is an example:
$amenities_ids = $request->amenities;
$amenities_ids_count = count($amenities_ids);
$rental_ids = AmenitiesRentals::selectRaw("COUNT(amenities_id) as amenities_count, rentail_id")
->whereIn('amenities_id', $amenities_ids)
->groupBy('rentail_id')
->having('amenities_count', $amenities_ids_count)
->get();

whereBetween() Eloquent returning wrong results

I have a Eloquent query and I am using query scope. I have a km column in my table and I am passing kmFrom and KmTo values as post data. Now I am doing a eloquent whereBetween and its returning wrong results when I search for km.
For example if I pass kmFrom = 1000 and kmTo = 2000. Its giving me results which are not in between these two values.
Eloquent:
Product::categoriesCategoryId($categoryId)
->km($kmFrom, $kmTo)->get();
Query Scope for the km:
public function scopeKm($query, $kmFrom, $kmTo)
{
if(($kmFrom) && ($kmTo)){
return $query->whereBetween('km', ["$kmFrom", "$kmTo"]);
}
return $query;
}
Please assist what wrong I am doing.
It's different approach to doing same thing
public function scopeKm($query, $kmFrom, $kmTo)
{
if(($kmFrom) && ($kmTo)){
return $query->where('km','>' ,$kmFrom])->where('km','<',$kmTo);
}
return $query;
}
this will work same
hope this will help you!

How to fetch two related objects in Laravel (Eloquent) with one SQL query

I am trying to get two related objects in Laravel using eager loading as per documentation.
https://laravel.com/docs/5.4/eloquent-relationships#eager-loading
My models are:
class Lead extends Model {
public function session() {
return $this->hasOne('App\LeadSession');
}
}
class LeadSession extends Model {
public function lead() {
return $this->belongsTo('App\Lead');
}
}
I want to get both objects with one SQL query. Basically I want to execute:
select * from lead_sessions as s
inner join lead as l
on l.id = s.lead_id
where s.token = '$token';
and then be able to access both the LeadSession and Lead objects. Here is the php code I am trying:
$lead = Lead::with(['session' => function ($q) use ($token) {
$q->where('token','=',$token);
}])->firstOrFail();
print($lead->session->id);
I have also tried:
$lead = Lead::whereHas('session', function($q) use ($token) {
$q->where('token','=',$token);
})->firstOrFail();
print($lead->session->id);
and
$session = LeadSession::with('lead')->where('token',$token)->firstOrFail();
print($session->lead->id);
In all three cases I get two queries executed, one for the leads table, and another for the lead_sessions table.
Is such a thing possible in Eloquent? In my view it should be a standard ORM operation, but for some reason I am struggling a whole day with it.
I don't want to use the Query Builder because I want to use the Eloquent objects and their functions afterwards.
I am coming from Python and Django and I want to replicate the behavior of select_related function in Django.
Try this and see if it makes more than one query
$session = LeadSession::join('leads', 'leads.id', '=', 'lead_sessions.lead_id')
->where('token',$token)
->firstOrFail();
I hope it only runs a single query. I didnt test this. Not sure if you have to add a select() to pick the columns. But yeah, try this first.
Updates
Just adding how to use both session and lead data. Try a select and specify the data you need. The reason being that if both tables have similar columns like 'id', one of them will be overwritten. So you have to alias your select like
$session = LeadSession::join('leads', 'leads.id', '=', 'lead_sessions.lead_id')
->where('token',$token)
->select(
'lead_sessions.*',
'leads.id as lead_id',
'leads.name',
'leads.more_stuff'
)
->firstOrFail();
Now all this data belongs to $session variable. For testing you were doing
print($lead->session->id);
//becomes
print($session->lead_id); //we aliased this in the query

Resources