How to join 2 collection in query laravel - laravel

I have StudentEducation model and in this model i got
public function student_education_countries()
{
return $this->hasMany(StudentEducationCountry::class, 'education_id');
}
and
public function student_education_education_types()
{
return $this->hasMany(StudentEducationEducationType::class, 'education_id');
}
in StudentEducationCountry model i got
public function student_education()
{
return $this->belongsTo(StudentEducation::class, 'education_id');
}
public function student_country()
{
return $this->belongsTo(StudentCountry::class, 'country_id');
}
and in StudentEducationEducationType model i got
public function student_education()
{
return $this->belongsTo(StudentEducation::class, 'education_id');
}
public function student_educationcategory()
{
return $this->belongsTo(StudentEducationcategory::class, 'educationcategory_id');
}
The question is how should i join for to take all educations where country_id is 2 and type is secondary

Simple with whereHas()
$educations = StudentEducation::query()->whereHas('student_education_countries', function (Builder $query) {
$query->where('id', 2);
})->whereHas('student_education_education_types', function (Builder $query) {
//maybe here you need another columns
$query->where('type', 'secondary');
})->get();

Related

Eloquent query on tables with relationships and a condition in a pivot table

I've various tables with these relationships, described as models
Customers
class Customers extends Model
{
public function claims()
{
return $this->hasMany(Claims::class);
}
}
Claims
class Claims extends Model
{
public function refunds()
{
return $this->hasMany(Refunds::class);
}
public function customers()
{
return $this->belongsTo(Customers::class,'customers_id');
}
}
Refunds
class Refunds extends Model
{
public function services()
{
return $this->belongsToMany(Services::class)
->withPivot(['services_id','services_amount','services_status']);
}
public function claims()
{
return $this->belongsTo(Claims::class,'claims_id');
}
}
Services
class Services extends Model
{
public function refunds()
{
return $this->belongsToMany(Refunds::class);
}
}
I need to do a query that return all rows from Customers with a row count on the pivot table refunds_services where services_id = 1 for each Customers row.
How can I do this? Is it possible? or better i use query builder and sql with several joins
Thx
you can try :
Customers::select('cliente')
->addSelect([
'countRefundService' => Customers::withCount('claims.refunds.services', function($query) {
$query->where('id', 1);
})->get();
])
->whereHas('claims.refunds.services', function ($query) {
$query->where('id', 1);
} )
->get();

Relationships in Laravel Models

How can I write this without a join for a scope in a Laravel model as the 'id' field becomes ambiguous
/**
* Return events that social category name
*/
public function scopeWithSocialEvents($query)
{
return $query->join('categories', 'events.event_type_id', '=', 'categories.id')
->where('categories.name', 'social');
}
Use this:
public function eventType()
{
return $this->belongsTo(Category::class);
}
public function scopeWithSocialEvents($query)
{
return $query->whereHas('eventType', function($query) {
$query->where('name', 'social');
});
}

Laravel: Combining multiple query scopes on nested relationships without overriding the previous ones

I've got the following database structure for an online learning platform: A course consists of modules. A module consists of lessons and tasks. There are user specific information for each of these elements with the respective relationships defined on each model:
class Course extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('start_at', 'end_at');
}
public function modules() {
return $this->hasMany(Module::class);
}
// ...
}
class Module extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('start_at', 'end_at');
}
public function lessons() {
return $this->hasMany(Lesson::class);
}
public function tasks() {
return $this->hasMany(Lesson::class);
}
}
class Lesson extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('favourite', 'completed_at');
}
}
class Task extends Model {
public function user() {
return $this->belongsToMany(User::class)->withPivot('completed_at');
}
}
My goal is to load a complete course with the following scopes on the course model:
class Course extends Model {
// ...
public function scopeWithModules($query) {
return $query->with(['modules' => function ($q) {
$q->with(['user' => function ($q) { $q->where('user_id', auth()->user()->id); }])
->whereHas('user', function ($q) { $q->where('user_id', auth()->user()->id); });
}]);
}
public function scopeWithLessons($query) {
return $query->with(['modules.lessons' => function ($q) {
$q->with(['user' => function ($q) { $q->where('user_id', auth()->user()->id); }])
->whereHas('user', function ($q) { $q->where('user_id', auth()->user()->id); });
}]);
}
public function scopeWithTasks($query) {
return $query->with(['modules.tasks' => function ($q) {
$q->with(['user' => function ($q) { $q->where('user_id', auth()->user()->id); }])
->whereHas('user', function ($q) { $q->where('user_id', auth()->user()->id); });
}]);
}
// ...
}
Each of these scopes alone is working fine. But combining them will override the previous ones, so only the last of these scopes will be executed.
Executing this
$course = Course::whereSlug('learning-abc')
->withModules()
->withLessons()
->withTasks()
->firstOrFail();
will give me the course with modules and tasks (but no lessons and user information for the modules).
Of course I can write one single bulky scope like withModulesLessonsTasks() but I hope there is a more elegant solution to this. Any ideas?
Before I had:
$course = Course::whereSlug('learning-abc')
->with([
'modules.user',
'modules.lessons.user',
'modules.tasks.user'
])
->firstOrFail();
which was working fine except for filtering the auth()->user().

Records where value is not equal to current value

I have 7 Departments and an Employee that is assigned to 2 of them through a polymorphic join model called DepartmentItem. When I run the following I expect to get 5 records that the employee does not belong to, but instead I get all 7.
$employee = \App\Employee::find(1);
$departments = \App\Department::join('department_items', 'department_items.department_id', '=', 'departments.id')
->select('departments.*')
->groupBy('departments.id')
->where('company_id', $employee->company_id)
->where('department_items.item_id', '!=', $employee->id)
->where('department_items.item_type', 'employee')
->get();
dd($departments);
This returns 7 departments when it should only return 5. When I change '!=' to '=' it returns the 2 departments that the employee is assigned to.
Here are the model relations:
// Company
public function departments() {
return $this->hasMany(Department::class);
}
public function employees() {
return $this->hasMany(Employee::class);
}
// Department
public function company() {
return $this->belongsTo(Company::class);
}
public function employees() {
return $this->morphedByMany(Employee::class, 'item', 'department_items');
}
// DepartmentItem
public function department() {
return $this->belongsTo(Department::class);
}
public function item() {
return $this->morphTo();
}
// Employee
public function company() {
return $this->belongsTo(Company::class);
}
You should use <> instead of != as where clause method takes mysql operators.
So your code should be like this:
$departments = \App\Department::join('department_items', 'department_items.department_id', '=', 'departments.id')
->select('departments.*')
->groupBy('departments.id')
->where('company_id', $employee->company_id)
->where('department_items.item_id', '<>', $employee->id)
->where('department_items.item_type', 'employee')
->get();
Hope this helps!

How to use wherePivot method in a scope?

I have two models with a pivot.
Domain
{
public function projects()
{
return $this->belongsToMany('Project')->withPivot('is_live');
}
}
Project
{
public function domains()
{
return $this->belongsToMany('Domain')->withPivot('is_live');
}
}
Then I try to create the scope "Domains which have Projects and is_live = true" like that Laravel Scope by pivot data values
public function scopeHasLiveProjects($query)
{
$pivotTable = $this->projects()->getTable();
return $query->whereHas('projects', function ($q) use ($pivotTable) {
$q->where($pivotTable . '.is_live', true);
});
}
But how I can use eloquent method wherePivot('is_live', '=', true) in the scope? Is it possible?!
public function scopeHasLiveProjects($query)
{
return $query->whereHas('projects', function ($q) {
$q->where('is_live', true);
});
}
should do the needed

Resources