Hello, I am implementing a Filter class for my Thread model & I am having trouble with working out how to handle the ORDER BY aspect when I chain filters in the query string / request.
This is my ThreadFilters class:
<?php
namespace App\Filters;
use App\Models\User;
class ThreadFilters extends Filters
{
protected array $filters = ['creator', 'best', 'search', 'filter'];
public function creator($value)
{
$user = User::select('id')->where('username', $value)->get()->first();
if ($user) {
return $this->query->where('user_id', $user->id)->orderBy('created_at', 'desc');
} else {
return $this->query->where('user_id', 0)->orderBy('created_at', 'desc');
}
}
public function best($value)
{
$user = User::select('id')->where('username', $value)->get()->first();
if ($user) {
return $this->query->whereHas('replies', function ($q) use ($user) {
$q->where('user_id', $user->id)
->where('best', 1);
})->orderBy('created_at', 'desc');
} else {
return $this->query->whereHas('replies', function ($q) {
$q->where('user_id', 0)
->where('best', 1);
});
}
}
public function search($query, $value)
{
return $query->where(function ($q) use ($value) {
$q->where('title', 'like', '%' . $value . '%')
->orWhere('body', 'like', '%' . $value . '%');
})->orderBy('created_at', 'desc');
}
public function filter($value)
{
switch ($value) {
case 'unsolved':
return $this->query->where('solved', 0)
->orderBy('created_at', 'desc');
case 'popular':
// count the replies and order by the count, then order by views
return $this->query->withCount('replies')
->orderBy('replies_count', 'desc')
->orderBy('views', 'desc');
case 'unanswered':
// get the threads that don't have any replies
return $this->query->whereDoesntHave('replies')
->orderBy('created_at', 'desc');
case 'solved':
// get the threads that have been solved
return $this->query->where('solved', 1)
->orderBy('created_at', 'desc');
case 'trending':
// get the threads that have been created in the last week, and order by the replies count
// and then order by the views, descending order for both of them
return $this->query->withCount(['replies' => function ($subQuery) {
$subQuery->where('created_at', '>=', now()->subWeek());
}])->orderByDesc('replies_count', 'desc')
->orderByDesc('views', 'desc');
case 'participated':
// get the threads that the user has participated in, either by replying to it
return $this->query->whereHas('replies', function ($q) {
$q->where('user_id', auth()->id());
})
// or the user has created the thread (uncomment the line below if you want to include the threads that the user has created)
//->orWhere('user_id', auth()->id())
->orderBy('created_at', 'desc');
case 'following':
// get the threads that the user is following
return $this->query->whereHas('follows', function ($q) {
$q->where('user_id', auth()->id());
})->orderBy('created_at', 'desc');
}
}
}