How to map using Laravel BelongsTo Relationship - php

I have a relationship between your_electricity_yesterday_category and building as building_id is present in your_electricity_yesterday_category table.
I am trying to get details out of the building table using the relationship.
I have this in my Electricity model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Electricity extends Model
{
use HasFactory;
protected $connection = 'mysql2';
protected $table = 'your_electricity_yesterday_category';
public function buildings()
{
return $this->belongsTo(Building::class, 'building_id');
}
}
I have this in my Repository
public function getAllBuilding()
{
// $buildings = Building::where('module_electricity', 1)->orderBy('description')->get();
$buildings = Electricity::with('buildings')->get();
return $buildings;
}
I have this in my controller
public function electBuilding()
{
$getBuilding = $this->electricityRepository->getAllBuilding();
return response()->json($getBuilding);
}
On the building table i have a column where module_electricity is either 0 or 1
How can i use this relationship to return building where module_electricity is 1 in json?

use whereHas query builder to filter parent Electricity details based on condition
$buildings = Electricity::with(['buildings'=>function($query){
$query->where('module_electricity',1);
}])
->whereHas('buildings',function($query){
$query->where('module_electricity',1);
})->get();
Also you can write scope for where condition in buildings model like below
public function scopeModuleElectricity($query,$module){
return $query->where('module_electricity',$module);
}
so your query will be
$buildings = Electricity::with(['buildings'=>function($query){
$query->moduleElectricity(1);
}])
->whereHas('buildings',function($query){
$query->moduleElectricity(1);
})->get();

Here is what I came up with:
public function getAllBuilding()
{
return Electricity::query()
->with('buildings', fn ($query) => $query->where('module_electricity', 1))
->get()
->pluck('buildings')
->collapse();
}
Walking through this step by step so you can better understand what's happening:
Initiating a query (completely optional, just for better code formatting)
Eager loading buildings with a condition (module_electricity = 1)
Retrieving data from the database
Extracting buildings only
Flat-mapping results
This will return a single collection with buildings that met a condition.
Let me know if the result turned out to be exactly what you expected.
P.S. Note that the above solution might not work if you're using older versions of PHP. If the above returns syntax error:
replace:
fn ($query) => $query->where('module_electricity', 1)
with:
function ($query) {
$query->where('module_electricity', 1)
}

Related

Laravel querying multiple related models

For example: I have these models in my application.
User, Profile, Interest.
I linked the users table with the profiles table by adding the user_id column in the profiles table. And I linked profiles and interests by using a pivot table (interest_profile), Which is (as obvious) will have two columns (profile_id, interest_id).
However, I want to query the users who are associated with a profile, too see who is associated with a particular interest, In other words: "select all users who are having (in their profiles) that particular interest".
I know that I can do this with raw SQL by joining the four tables and then use (where clause).. But I want to do it the Laravel way.
Thanks in advance.
First make sure you have your relationships setup correctly on your models like:
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function interests()
{
return $this->belongsToMany(Interest::class, 'interest_profile');
}
}
class Interest extends Model
{
public function profiles()
{
return $this->belongsToMany(Profile::class, 'interest_profile');
}
}
Then you can use whereHas() to constrain a query by a related model and dot notation for nested relations. So your query would be:
User::whereHas('profile.interests', function($query) use ($interestName) {
return $query->where('name', $interestName);
})->get();
That would just return a collection of users. If you wanted to return their profiles and interests as well you would use with():
User::whereHas('profile.interests', function($query) use ($interestName) {
return $query->where('name', $interestName);
})
->with('profile.interests')
->get();
Assuming the User model has a relationship profile and the Profile model has a relationship interests, you can do this.
$interest_id = 1;
$users = User::whereHas('profile', function ($query) use ($interest_id) {
$query->whereHas('interests', function ($query) use ($interest_id) {
$query->where('id', $interest_id);
});
})->get();

Laravel Eloquent Eager loading confusion

In Laravel I have a model that looks like this:
class Recipient extends Model
{
public $table = 'recipients';
public function location()
{
return $this->belongsTo('App\Location');
}
public function teams()
{
return $this->belongsToMany('App\Team');
}
public function company()
{
return $this->belongsTo('App\Company');
}
}
To query that model I do this:
$recipients = Recipient::with('location')
->with('teams')
->where('company_id',Auth::user()->company_id)
->where('teams.id', 10)
->get();
On doing so, I get an error saying that laravel can't find teams.id, as it is only querying the parent recipient table. Wondering what I'm doing wrong, I thought the with method was to eager load / inner join records? Do I need to use a DB: inner join instead? Or am I missing something?
Use the whereHas method for this:
Recipient::with('location')
->where('company_id', auth()->user()->company_id)
->whereHas('teams', function($q){
return $q->where('id', 10);
})
->get();
try being explicit and add a select statement. Sometimes a relationship does not show up when not selected. Include the IDs else it won't work

php/laravel - select other table's column using the belongsToMany of laravel

This is my code on patient model:
class Patient extends Model
{
protected $primaryKey = 'PatientID';
public function users()
{
return $this->belongsToMany('App\Vaccine', 'immunizations', 'patient_id', 'vaccine_id');
}
}
and this is my query
$patients = Patient::whereDoesntHave('users', function ($q) use ($vaccine_id) {
$q->where('vaccine_id', '=', $vaccine_id);
})->get();
In my current situation I can only get the Patient model column data but not the other tables. Where should I put the select() method to select the rows and columns of the immunizations table because i want to set a chain where()or condition which is where('immunizations_id', 1) but it doesn't work because the immunizations table is not selected.
or does anyone here knows how to convert it without using a closure like make it
Patient::wheredoesnthave(join('table')); so i can freely manipulate it
We will get other relationship table using 'with()'
$patients = Patient::whereDoesntHave('users', function ($q) use ($vaccine_id) {
$q->where('vaccine_id', '=', $vaccine_id);
$q->with('Vaccine', 'immunizations');
})->get();
Try this.

Laravel 5: Eloquent - order by relation when returning single record

im trying build query in eloquent with data sorted by relation. Imagine this DB structure:
TABLE: Station
id
name
...
TABLE: station_status:
id
station_id
status_type_id
date
...
TABLE: status_type:
id
description
...
MODELS
class Station extends \Eloquent
{
public function stationStatus() {
return $this->hasMany('App\StationStatus', 'station_id', 'id');
}
}
class StationStatus extends \Eloquent
{
public function statusType() {
return $this->hasOne('App\StatusType', 'id', 'status_type_id');
}
}
class StatusType extends \Eloquent
{
...
}
Now the question. How can i query Station model by station ID, but sort by related status types description?
So far i have:
// This just do not work
$query = Station::join('station_status', 'station.id', '=', 'station_status.station_id')
->join('status_type', 'station_status.status_type_id', '=', 'status_type.id')
->orderBy('status_type.description', 'ASC')
->select(['stations.*'])
->with(['stationStatus.statusType']
->find(110);
I think the problem is that i'm not returning collection but only one item using find() method, how can i overcome this problem?
Many thanks for any help !
Try this:
$query = Station::with(['stationStatus' => function($q){
$q->join('status_type', 'station_status.status_type_id', '=', 'status_type.id')
->orderBy('status_type.description', 'ASC');
}])->find(110);
With is a convienent way of getting the related objects, but it doesn't perform a join. It performs a new query and attaches all the elements to your collection. You can add your own logic to the query, like I did with $q->orderBy(...).

Laravel Multiple Models Eloquent Relationships Setup?

I have 3 models
User
Pick
Schedule
I'm trying to do something like the following
$picksWhereGameStarted = User::find($user->id)
->picks()
->where('week', $currentWeek)
->first()
->schedule()
->where('gameTime', '<', Carbon::now())
->get();
This code only returns one array inside a collection. I want it to return more than 1 array if there is more than 1 result.
Can I substitute ->first() with something else that will allow me to to return more than 1 results.
If not how can I set up my models relationship to allow this to work.
My models are currently set up as follow.
User model
public function picks()
{
return $this->hasMany('App\Pick');
}
Schedule model
public function picks()
{
return $this->hasMany('App\Pick');
}
Pick model
public function user()
{
return $this->belongsTo('App\User');
}
public function schedule()
{
return $this->belongsTo('App\Schedule');
}
Since you already have a User model (you used it inside you find method as $user->id), you can just load its Pick relationship and load those Picks' Schedule as follows:
EDIT:
Assuming you have a schedules table and your picks table has a schedule_id column. Try this.
$user->load(['picks' => function ($q) use ($currentWeek) {
$q->join('schedules', 'picks.schedule_id', '=', 'schedules.id')
->where('schedules.gameTime', '<', Carbon::now()) // or Carbon::now()->format('Y-m-d'). See what works.
->where('picks.week', $currentWeek);
}])->load('picks.schedule');
EDIT: The code above should return the user's picks which have a schedules.gameTime < Carbon::now()
Try it and do a dump of the $user object to see the loaded relationships. That's the Eloquent way you want.
Tip: you may want to do $user->toArray() before you dump $user to see the data better.
EDIT:
The loaded picks will be in a form of Collections so you'll have to access it using a loop. Try the following:
foreach ($user->picks as $pick) {
echo $pick->schedule->gameTime;
}
If you only want the first pick from the user you can do: $user->picks->first()->schedule->gameTime
I think a foreach loop may be what you're looking for:
$picks = User::find($user->id)->picks()->where('week', $currentWeek);
foreach ($picks as $pick){
$pickWhereGameStarted = $pick->schedule()->where('gameTime', '<', Carbon::now())->get();
}
Try this and see if it's working for you

Categories