Currently I’m making a function that displays news
public function getAllNews($listBranches, $listGrade, $userId, $limit, $search, $language, $excludeId = null, $tagIds = null, $listBrandCode): LengthAwarePaginator
{
$models = $this->model->with([
'newsBrands', 'newsGrades', 'newsBranches',
'userNewsLikeShare' => function ($query) use ($userId) {
$query->where('user_id', $userId);
},
])->whereIn('status', [NewsStatus::POSTED->value, NewsStatus::OUTSTANDING->value])
->where('date_post', '<=', now());
$brandCode = $search['brand_code'] ?? BrandEnum::TDS->value;
if (count($listBranches) > 0) {
$models->whereHas('newsBrands', function ($query) use ($listBranches, $brandCode, $listBrandCode) {
$query->where('abbreviation_name', $brandCode);
if (!empty($listBranches) && in_array(strtolower($brandCode), $listBrandCode)) {
$query->whereIn('branch_id', array_values($listBranches));
}
});
if (!empty($listBranches)) {
$models->whereHas('newsBranches', function ($query) use ($listBranches) {
$query->whereIn('branch_id', $listBranches);
})->orWhereDoesntHave('newsBranches');
}
}
if (count($models->get()) == 0 || count($listBranches) == 0) {
$models = $this->model->with([
'newsBranches', 'newsGrades',
'userNewsLikeShare' => function ($query) use ($userId) {
$query->where('user_id', $userId);
},
])->where('status', NewsStatus::POSTED->value);
$models = $models->whereHas('newsBrands', function ($query) use ($brandCode) {
$query->where('abbreviation_name', $brandCode);
});
$models = $models->whereHas('newsTypes', function ($q) {
$q->where('news_types_id', NewTypeEvents::EVENTS->value);
});
}
if (!empty($search['search'])) {
$text_search = $search['search'];
$models->where(function ($q) use ($text_search, $language) {
$q->whereRaw("LOWER(json_extract(title, '$.$language')) COLLATE utf8mb4_unicode_520_ci like (?)", '%' . strtolower($text_search) . '%')
->orWhereRaw("LOWER(json_extract(description, '$.$language')) COLLATE utf8mb4_unicode_520_ci like (?)", '%' . strtolower($text_search) . '%');
});
}
$models = $models->select([
"id", "image", "title", "description", "likes", "views", "date_post", "is_pin",
"link_share", "is_outstanding", "created_at", "updated_at", "status",
])->when($excludeId, function ($q) use ($excludeId) {
$q->whereNot('id', $excludeId);
})->when($tagIds, function ($q) use ($tagIds) {
$q->whereHas('newsTags', function ($subQ) use ($tagIds) {
$subQ->whereIn('tags_id', $tagIds);
});
})
->when(count($listGrade) > 0, function ($subQ) use ($listGrade) {
$subQ->where(function ($subQ) use ($listGrade) {
$subQ->whereDoesntHave('newsGrades')->orWhereHas('newsGrades', function ($subQ) use ($listGrade) {
$subQ->whereIn('grade_id', $listGrade);
});
});
})->whereHas('newsBrands', function ($query) use ($brandCode) {
$query->where('abbreviation_name', $brandCode);
});
$orderBy = !empty($search['order_by']) ? $search['order_by'] : ['updated_at'];
$sortedBy = !empty($search['sort_by']) ? $search['sort_by'] : 'desc';
foreach ($orderBy as $value) {
$models = $models->orderBy($value, $sortedBy);
}
$models->orderBy('status', 'desc');
Log::channel('deferment_application')->info(
$models->toSql().' - grade: '. implode(',', $listGrade)
.' - branchID: '. implode(',', $listBranches)
);
$categoryNews = $search['category_news'] ?? [];
if (count($categoryNews)) {
$models->where(function ($query) use ($categoryNews) {
foreach ($categoryNews as $category) {
switch ($category) {
case NewsCategories::School->value:
$query->orWhere(function ($query) {
$query->whereHas('newsBranches')
->whereDoesntHave('newsStudyPrograms')
->whereDoesntHave('newsSchoolShips')
->whereDoesntHave('newsGrades')
->whereHas('newsTypes', function ($query) {
$query->where('name->en', '!=', 'Events');
});
});
break;
case NewsCategories::GradeCategory->value:
$query->orWhere(function ($query) {
$query->whereHas('newsGrades')
->whereHas('newsTypes', function ($query) {
$query->where('name->en', '!=', 'Events');
});
});
break;
case NewsCategories::Event->value:
$query->orWhereHas('newsTypes', function ($query) {
$query->where('name->en', 'Events');
});
break;
case NewsCategories::SubjectCombinationCategory->value:
$query->orWhere(function ($query) {
$query->whereHas('newsSchoolShips')
->whereDoesntHave('newsGrades')
->whereHas('newsTypes', function ($query) {
$query->where('name->en', '!=', 'Events');
});
});
break;
case NewsCategories::StudyProgram->value:
$query->orWhere(function ($query) {
$query->whereHas('newsStudyPrograms')
->whereDoesntHave('newsSchoolShips')
->whereDoesntHave('newsGrades')
->whereHas('newsTypes', function ($query) {
$query->where('name->en', '!=', 'Events');
});
});
break;
}
}
});
}
return $models->paginate($limit);
}
But when filtering by $categoryNews
, it still always returns the news that I filtered out with whereDoesntHave()
Here is my relationship:
public function newsStudyPrograms(): BelongsToMany
{
return $this->belongsToMany(ProgramBase::class, 'news_config_study_program', 'news_id', 'study_program_id');
}
public function newsGrades(): BelongsToMany
{
return $this->belongsToMany(GradeBase::class, 'news_config_grade', 'news_id', 'grade_id');
}
public function newsSchoolShips(): BelongsToMany
{
return $this->belongsToMany(SchoolShipBase::class, 'news_config_school_ship', 'news_id', 'school_ship_id');
}
public function newsTypes(): BelongsToMany
{
return $this->belongsToMany(NewsTypesBase::class, 'news_has_news_types', 'news_id', 'news_types_id');
}
Does anyone have any solution?
My logic is that when filtering any news, I will only display that exact type of news. I can filter many categories at the same time. For example, if I filter NewsCategories::School
and NewsCategories::GradeCategory
, I will only display exactly the news of this two categories.