In any job portal , jobs should expire after a certain period . The common problem jobs keep showing up in search results which resulting frustating candidates and recrutiers .
Any way , when we develop this , we purposely not adding any job expired as we need to ensure our job portal look active (YTJT) .
Easy Fix
The fix is easy , dont think to much , just implement this directly .
public function index()
{
$jobs = JobAdvertisement::where('expires_at', '>', now())->get();
return view('jobs.index', compact('jobs'));
}
See easy , but you know , we notice that we have multiple place need to update so we need to update at different place . Till the day that we found out this thing will never ending , we will still getting complaint from recruiter of the company and also from candidate that applied and receive notification from expired job because we miss some place to add the expires_at .
We did something like this also for the context
public function show($id)
{
$job = JobAdvertisement::findOrFail($id);
if ($job->expires_at < now()) {
abort(404);
}
return view('jobs.show', compact('job'));
}
Basically we jut repeating the expiry logic everywhere and in risk missing it . This solve the expiry problem but not easy to maintain and scalable .
A New Hope
At this point , we starting to asking why we keep writing same condition , why not the model itself should know when a job is expired ?
By using global scope , we can make it more clean and easy to maintain as the logic in one place only .
Why global not model scope ? Since global scope will be enforce for each query , we want it automatically applied everywhere since we want to enforce this as one of our business rules in job portal where all job should be display only that are not expired only .
class JobAdvertisement extends Model
{
protected static function booted()
{
static::addGlobalScope('active', function ($builder) {
$builder->where('expires_at', '>', now());
});
}
}
So now everytime you use , it will already use the scope .
JobAdvertisement::all();
With this we can guarantee all thing related to job advertisement will always show non expired by default .
BUT , we still got admin or recruiter that might need to access expired one also right ? No worry we can still handle this using this way
class JobAdvertisement extends Model
{
protected static function booted()
{
static::addGlobalScope('active', function ($builder) {
$builder->where('expires_at', '>', now());
});
}
public function scopeWithExpired($query)
{
return $query->withoutGlobalScope('active');
}
public function scopeOnlyExpired($query)
{
return $query->withoutGlobalScope('active')
->where('expires_at', '<=', now());
}
}
Now for usage admin and recruiter we can just call like this
$expiredJobAdvertisements = JobAdvertisement::onlyExpired()->get();
$jobAdvertisements = JobAdvertisement::withExpired()->get();
Closing
Using global scope is really cool , but like any other thing , we should always know when to use it properly .
For me , if anything related to business rules and it need to be apply to all by default.
Don't use it when you want to get it by filtering based on context dependent and also user specific .
Top comments (0)