Files
jobifygarden/app/Repositories/JobRepository.php
T

223 lines
6.5 KiB
PHP
Raw Normal View History

2026-04-03 00:39:57 +03:00
<?php
namespace App\Repositories;
use App\Models\Job;
2026-04-03 20:55:51 +03:00
use App\Services\CacheService;
2026-04-03 00:39:57 +03:00
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
class JobRepository
{
2026-04-03 20:55:51 +03:00
public function __construct(
private CacheService $cacheService
) {}
2026-04-03 00:39:57 +03:00
/**
* Get all active jobs with pagination
*/
public function getActiveJobs(int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->latest('posted_at')
->paginate($perPage);
}
/**
* Find a job by ID
*/
public function find(int $id): ?Job
{
return Job::with(['source', 'category', 'jobLocation'])->find($id);
}
/**
* Get jobs by category
*/
public function getByCategory(int $categoryId, int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->where('job_category_id', $categoryId)
->latest('posted_at')
->paginate($perPage);
}
/**
* Get jobs by location
*/
public function getByLocation(int $locationId, int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->where('job_location_id', $locationId)
->latest('posted_at')
->paginate($perPage);
}
/**
* Get remote jobs
*/
public function getRemoteJobs(int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->remote()
->latest('posted_at')
->paginate($perPage);
}
/**
* Get recent jobs (last N days)
*/
public function getRecentJobs(int $days = 7, int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->where(function ($query) use ($days) {
$query->where('posted_at', '>=', now()->subDays($days))
->orWhere(function ($q) use ($days) {
$q->whereNull('posted_at')
->where('created_at', '>=', now()->subDays($days));
});
})
->latest('posted_at')
->paginate($perPage);
}
/**
* Get jobs by experience level
*/
public function getByExperienceLevel(string $level, int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->experienceLevel($level)
->latest('posted_at')
->paginate($perPage);
}
/**
* Get jobs by type
*/
public function getByJobType(string $type, int $perPage = 15): LengthAwarePaginator
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->ofType($type)
->latest('posted_at')
->paginate($perPage);
}
/**
* Get similar jobs (same category, exclude current)
*/
public function getSimilarJobs(Job $job, int $limit = 5): Collection
{
return Job::with(['source', 'category', 'jobLocation'])
->active()
->where('id', '!=', $job->id)
->where('job_category_id', $job->job_category_id)
->latest('posted_at')
->limit($limit)
->get();
}
/**
* Get featured jobs (most recent from diverse sources)
*/
public function getFeaturedJobs(int $limit = 10): Collection
{
2026-04-03 20:55:51 +03:00
$cacheKey = $this->cacheService->featuredJobsKey($limit);
2026-04-03 20:33:24 +03:00
2026-04-03 20:55:51 +03:00
return $this->cacheService->rememberWithTags(['jobs'], $cacheKey, CacheService::CACHE_FEATURED_JOBS, function () use ($limit) {
// First, build a subquery with window function
$subQuery = \DB::table('jobs')
->selectRaw('jobs.*, ROW_NUMBER() OVER (PARTITION BY job_source_id ORDER BY posted_at DESC) as rn')
->whereNull('deleted_at')
->where(function ($query) {
$query->whereNull('expires_at')
->orWhere('expires_at', '>', now());
});
// Then query from that subquery filtering by rn
// Use withoutGlobalScopes to prevent SoftDeletes from adding WHERE clause
return Job::withoutGlobalScopes()
->with(['source', 'category', 'jobLocation'])
->fromSub($subQuery, 'ranked_jobs')
->whereRaw('ranked_jobs.rn <= 2')
->orderBy('posted_at', 'desc')
->limit($limit)
->get();
});
2026-04-03 00:39:57 +03:00
}
/**
* Get job statistics
*/
public function getStatistics(): array
{
2026-04-03 20:55:51 +03:00
$cacheKey = $this->cacheService->statisticsKey();
2026-04-03 00:39:57 +03:00
2026-04-03 20:55:51 +03:00
return $this->cacheService->remember($cacheKey, CacheService::CACHE_STATISTICS, function () {
$total = Job::count();
$active = Job::active()->count();
$remote = Job::active()->remote()->count();
$recentlyAdded = Job::where('created_at', '>=', now()->subDays(7))->count();
2026-04-03 00:39:57 +03:00
2026-04-03 20:55:51 +03:00
$topCategories = Job::active()
->select('job_category_id', \DB::raw('COUNT(*) as count'))
->whereNotNull('job_category_id')
->groupBy('job_category_id')
->orderBy('count', 'desc')
->limit(5)
->with('category')
->get();
return [
'total_jobs' => $total,
'active_jobs' => $active,
'remote_jobs' => $remote,
'recently_added' => $recentlyAdded,
'top_categories' => $topCategories,
];
});
2026-04-03 00:39:57 +03:00
}
/**
* Create a new job
*/
public function create(array $data): Job
{
return Job::create($data);
}
/**
* Update a job
*/
public function update(Job $job, array $data): bool
{
return $job->update($data);
}
/**
* Delete a job
*/
public function delete(Job $job): bool
{
return $job->delete();
}
/**
* Get jobs count by source
*/
public function getCountBySource(): Collection
{
return Job::with('source')
->select('job_source_id', \DB::raw('COUNT(*) as count'))
->groupBy('job_source_id')
->orderBy('count', 'desc')
->get();
}
}