Scope always get the same relation - laravel

I want to make a relation ship bt condition...
I'm try like this:
Model:
public function page_link()
{
return $this->belongsTo(Link::class, 'page_id', 'user_id')->inRandomOrder()->Select('links.id', 'links.title', 'links.photo', 'links.country', 'links.friendly_url', 'links.clicks', 'links.description', 'links.suggestions', 'links.count_comments', 'links.url', 'links.shares', 'links.page_id', 'links.tag_id', 'links.created_at')->where('sponsored', 0)->where('scheduled', 0)>where('status', 1)->take(3)->orderBy('id','desc');
}
public function user_share()
{
return $this->belongsTo(Share::class, 'user_id', 'user_id')->inRandomOrder()->Select('id', 'link_id', 'user_id', 'shared_in', 'content', 'created_at')->take(3)->orderBy('id', 'desc')->where('type', '=', 0);
}
public function user(){
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function scopeProfile($query)
{
return $query
->when($this->type == 0, function($q)
{
return $q->with('user_share.link.page')->with('user')->with('user_share.link.tag');
})
->when($this->type == 1, function($q)
{
return $q->with('page_link');
})
->when($this->type == 2, function($q)
{
return $q->with('group_link');
});
}
Controller:
$feed = Feed::Profile()->where('follower_id', auth()->user()->id)
->take(10)
->get();
But ALL the results, even the type 1 or 2 returns "user_links" relation. I don't know whats happening.
Someone can help me?

Related

Laravel pass value from query to with() function

Here is my query:
$fix = Fixture::select('fixtures.*')
->whereDate('kickoff', '<', $date)
->with('competition')
->with('teamA')
->with(['teamA.standing' => function ($q) {
$q->whereColumn('standings.competition_id', '=', {{here i want the competition_id from competitions or fixtures table}} );
}])
->with('teamB')
->with(['teamB.standing' => function ($q) {
$q->whereColumn('standings.competition_id', '=', {{here i want the competition_id from competitions table or fixtures table}});
}])->get();
Code from Fixture model:
public function teamA()
{
return $this->belongsTo(Team::class,'team_a','id');;
}
public function teamB()
{
return $this->belongsTo(Team::class,'team_b','id');;
}
Code from Team model:
public function standing()
{
return $this->hasOne(Standing::class);;
}
Code from Standing model:
public function team(){
return $this->belongsTo(Team::class);
}
public function competition()
{
return $this->belongsTo(Competition::class);
}
Can someone help me to get this done or if I am doing it wrong what's the correct way?
->with(['teamA.standing' => function ($q) {
$q->whereColumn('standings.competition_id', '=', {{here i want the competition_id from competition table or fixtures table}} );
}])
Example:
Category::select('id', 'name')->whereHas('statuses', function($query) { $query(); })->with('courses')->get();

How to join 2 collection in query 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();

How to apply condition in relationship methods from controller?

I have three model MainCategory, Subcategory and Menu
Main category Model
protected $table="main_categories";
protected $fillable =['category'];
public function subCategories()
{
return $this->hasMany(SubCategory::class,'maincategory_id');
}
Sub Category Model
protected $table="sub_categories";
protected $fillable =['category','maincategory_id'];
public function foods()
{
return $this->hasMany(Menu::class,'subcategory_id');
}
Menu Model
protected $table="menus";
protected $fillable = [
'resturant_id',
'maincategory_id',
'subcategory_id',
'foodtype_id',
'food_name',
'slug',
'food_price',
'food_image'
];
public function mainCategory()
{
return $this->belongsTo(MainCategory::class,'maincategory_id');
}
public function subCategory()
{
return $this->belongsTo(SubCategory::class,'subcategory_id');
}
Problem is in my Controller
$data['main_category'] = MainCategory::with(['subCategories', 'menus'])
->whereHas('subCategories.foods', function ($q) use ($resturantid) {
return $q->where('resturant_id', $resturantid);
})
->whereHas('menus', function ($q) use ($resturantid) {
return $q->where('resturant_id', $resturantid);
})
->get();
I want to apply condition in subcategories foods() method where resturant_id is resturant.id.
But it is showing all the resturants data.
I have applied subquery with notation as well but did not help
I am not sure if this is want you want, but could you try the following:
$data['main_category'] = MainCategory::with([
'subCategories.foods' => function ($q) use ($resturantid) {
$q->where('resturant_id', $resturantid);
},
'menus'
])
->whereHas('subCategories.foods', function ($q) use ($resturantid) {
return $q->where('resturant_id', $resturantid);
})
->whereHas('menus', function ($q) use ($resturantid) {
return $q->where('resturant_id', $resturantid);
})
->get();
This will only load the foods from the subCategories where the resturant_id matches the $resturantid

Nested "with()" laravel

I'm having issues with some relationships. I have the following situation
Product:
public function catalogues()
{
return $this->belongsToMany('App\Catalogue');
}
public function category()
{
return $this->belongsTo('App\Category');
}
Category:
public function products()
{
return $this->hasMany('App\Product');
}
Catalogue:
public function products()
{
return $this->belongsToMany('App\Product');
}
With a single query, I need to get all the categories that have products belonging to a certain catalogue. How can I achieve it?
Use whereHas():
Category::whereHas('products.catalogues', function($q) use($catalogueId) {
$q->where('catalogues.id', $catalogueId);
})
->get();
Or:
Category::whereHas('products', function($q) use($catalogueId) {
$q->whereHas('catalogues', function($q) use($catalogueId) {
$q->where('id', $catalogueId);
})
})
->get();
You need whereHas and
Category::whereHas('products')
->with(['products' => function($query) use ($id){
$query->with('catalogues' => function($query) use ($id){
$query->where('catalogues.id',$id);
});
}])
->get();
Hope this helps.

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().

Resources