LARAVEL hasManyThrough still using the ID as foreign key - laravel

Hi trying to get the rest day of a country. But I am getting error.
Basically here is the structure
Employee
has SITE,
Site
has REGION,
Region
has REST DAY
I have declared this on my Employee Model
public function restdays()
{
return $this->hasManyThrough('App\ref_restdays', 'App\ref_gacomsit', 'region', 'region');
}
But I get this error
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Conversion failed when converting the varchar value 'RUAE' to data type int. (SQL: select [ref_restdays].*, [ref_gacomsit].[region] from [ref_restdays] inner join [ref_gacomsit] on [ref_gacomsit].[id] = [ref_restdays].[region] where [ref_gacomsit].[region] in (855))
Apparently it using still the ID of my site masterfile where as I have declared to use the REGION foreign key.
Can anyone explain where is my mistake is? Appreciate for your help.

Turns out I don't need to use hasManyThrough. I've just declared hasMany on my site masterfile like so:
public function restdays()
{
return $this->hasMany( 'App\ref_restdays', 'region', 'region');
}
then I just use the nested eager loading on my query using dot syntax.
here is my final query, on the last line I just reference site.restdays to get the list of restdays.
$employees = hr_employee::select(
'hr_employee.id',
'empno',
'first_name',
'family_name',
'empstatus',
'empstatus_eff_date',
'contcatg_code',
'post_title_code',
'cs',
'group_initial_joined',
'returned_date',
'mcat2',
'othours1',
'othours2',
'othours3'
)
->where([
['empno','=',$empno]
])
->with(['catg', 'post', 'site.restdays'])
->get();

Related

Get data on relation 'B' where relation 'A' does not exits in same id in laravel eloquent

I have two tables named "Student" and "Subscription". If there is at least one active plan in the subscription database, I check by date. I need to get the data if no plan is active. Below is the code I used to get the data. But this is wrong because in this query I am getting all the expired data and I should get the data only if there is not even one plan active in the student id.
$expired_student = Student::wherehas('getSubscription', function ($query) use ($current_date){
$query->where('expired_at','<',$current_date);
})->where('status',1)->count();
anyone can please help me to solve this problem
In you Student model, you can define a relationship method called activeSubscriptions, like this:
public function activeSubscriptions() {
return $this->hasMany(Subscription::class)->where(function($query) {
$query->whereNull('expired_at')->orWhere('expired_at', '>', now());
});
}
And you can use this function like this:
$expiredStudents = Student::doesntHave('activeSubscriptions')->get();

Wrong ID returned from local Eloquent scope

In my Laravel project I've got a model (and an underlying table) for lessons. Now I'm trying to write a local scope for returning all lessons that have been finished by a particular user. The definition of "finished" is that there exists a row in a table named "lesson_results" with this lesson's ID and the users ID.
My scope currently looks like this:
public function scopeFinished($query, User $user)
{
return $query->join('lesson_results', function($join) use($user)
{
$join->on('lesson_results.lesson_id', '=', 'lessons.id')
->where("user_id", $user->id);
});
}
This kinda works. When I do a Lesson::finished($user)->get() I get out the correct lessons for that user. However the lessons in the collection returned all have the wrong ID's! The ID's I see are the ID's from the lesson_results table. So when I check $lesson->id from one of the returned items I don't get the ID from that lesson, but the ID from the corresponding row in the lesson_results table.
I've checked in mysql and the full query sent from Laravel is the following
select * from `lessons` inner join `lesson_results` on `lesson_results`.`lesson_id` = `lessons`.`id` and `user_id` = 53
This query DO return two columns named id (the one from the lessons table and the one from the lesson_results table) and it seems Laravel is using the wrong one for the result returned.
I don't know if I'm going about this the wrong way or if it's a bug somewhere?
This is on Laravel 7.6.1.
edit: Ok, I think I actually solved it now. Not really sure though if it's a real solution or just a workaround. I added a select() call so the return row now is
return $query->select('lessons.*')->join('lesson_results', function($join) use($user)
...which makes it only return the stuff from the lessons table. But should that really be needed?
One of the same column names will be covered by the other.
Solution 1:
Specify the table with the column, and alias the other table's column if it has same column name.
Lesson::finished($user)->select('lessons.*', 'lesson_results.id AS lesson_result_id', 'lesson_results.column1', 'lesson_results.column2',...)->get();
Solution 2:
Or you can use Eloquent-Builder eager-loading whereHas,(Assuming you have build the relationship between model Lesson and model LessonResult)
public function scopeFinished($query, User $user)
{
return $query->whereHas('lessonResults', function($query) use($user)
{
$query->where("user_id", $user->id);
});
}
So you can get lesson like this:
Lesson::finished($user)->get();

Retrieve custom fields from child of a child model in Laravel eloquent

I'm trying to retrieve custom fields from a model using the with() statement in Laravel. When I just get all fields the child object comes ok, but when I try to retrieve just some fields of this child abject it returns to me the following error:
Integrity constraint violation: 1052 Column 'id' in field list is ambiguous
below I'll show how I'm doing these queries.
When I execute the following query it works:
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:id,title,description',
'speech.speakers'
])->get();
But when I execute the code below it returns the error which I have mentioned above.
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:id,title,description',
'speech.speakers:id,name,email'
])->get();
Note: than only modification in this code is the line: 'speech.speakers:id,name,email'
in my model Speech, the speakers relationship is the following:
public function speakers()
{
return $this->belongsToMany(Speaker::class, 'speech_speaker');
}
You will need to define the table_name for the id's your are selecting:
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:TABLE_NAME.id,title,description',
'speech.speakers:TABLE_NAME.id,name,email'
])->get();
you can also do the following, ie. rename the id:
$cfps = CallForPaper::select('id', 'speech_id')->with([
'speech:TABLE_NAME.id as speechID,title,description',
'speech.speakers:TABLE_NAME.id as speakerID,name,email'
])->get();

Query builder - pivot table laravel

How do I get only users from database where they have no role assigned?
User belongs to many roles, the exact relation is:
public function roles() {
return $this->belongsToMany(Role::class, 'user_has_roles', 'user_id', 'role_id');
}
My problem is, that I do only work with Query builder, not with the model so I do not want to use relation.
EDIT:
I am working with migrations, so please no solutions when using model.
You can use doesntHave, I believe this uses QueryBuilder only.
User::doesntHave('roles')->get();
Reference: https://laravel.com/docs/5.6/eloquent-relationships
UPDATE
Using raw SQL query, you can do this.
Basically what this tries to do is to get all users where its id is not found in the user_has_roles table (meaning it doesn't have any relations)
SELECT *
FROM users
WHERE id NOT IN (SELECT user_id FROM user_has_roles)
I think you can convert this into a JOIN or something. I'm not that expert in raw SQL though.
UPDATE Trying Query Builder
$usersWithoutRoles = DB::table('users')
->whereNotIn(function ($query) {
$query->select(DB::raw('user_id'))
->from('user_has_roles')
->whereRaw('user_has_roles.user_id = users.id');
})
->get();
Reference: SQL - find records from one table which don't exist in another
You can try other alternatives there.

Laravel 5 eager loading, select column from eloquent relationship

I am trying to
1. select `DOS`,`name`,`fin`,`ins_type` from events table.
2. site_name from sites table
3. client_name from clients table
but unable to access site_name, client_name column in select statement
->select('DOS','name','fin','ins_type')
How to add these columns site.site_name, client.client_name in above select statement.
Eloquent query is
$events = Event::with([
'site'=>function($q){
$q->select('site_id','site_name','client_id');
},
'site.client'=>function($q2){
$q2->select('client_id','client_name');
}])
->select('DOS','name','fin','ins_type')
->get();
How about this?
$events = Event::with([
'site'=>function($q){
$q->with(['client'=>function($qq){
$qq->select('client_id','client_name');
}])->select('site_id','site_name','client_id');
}])
->select('DOS','name','fin','ins_type')
->get();
I found a simple solution from the comment section in here. It is possible to put the column selection in the model. So in your case, your Event model could be something like this.
public function site()
{
return $this->belongsTo('App\Site')->select('id', 'name', 'client_id');
}
Then, in your controller you simply call the function.
$events = Event::with('site')->get();
I haven't tried how this goes with the nested eager loading though.
I myself got a little problem with these also until i discover that you need to add the foreign key to the select statement inside the "with" closure.
the column that relates "client" to "site" and "site" to "Event"

Resources