Files
jobifygarden/app/Models/Job.php
T
2026-04-03 00:39:57 +03:00

191 lines
4.9 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class Job extends Model
{
use SoftDeletes;
protected $fillable = [
'external_id',
'title',
'company',
'description',
'location',
'salary_min',
'salary_max',
'salary_currency',
'job_type',
'job_source_id',
'source_url',
'apply_url',
'posted_at',
'expires_at',
'remote_allowed',
'experience_level',
'job_category_id',
'job_location_id',
'fingerprint',
];
protected $casts = [
'posted_at' => 'datetime',
'expires_at' => 'datetime',
'remote_allowed' => 'boolean',
'salary_min' => 'decimal:2',
'salary_max' => 'decimal:2',
];
/**
* Get the source that provides this job.
*/
public function source(): BelongsTo
{
return $this->belongsTo(JobSource::class, 'job_source_id');
}
/**
* Get the category that this job belongs to.
*/
public function category(): BelongsTo
{
return $this->belongsTo(JobCategory::class, 'job_category_id');
}
/**
* Get the location of this job.
*/
public function jobLocation(): BelongsTo
{
return $this->belongsTo(JobLocation::class, 'job_location_id');
}
/**
* Get the users who saved this job.
*/
public function savedByUsers(): BelongsToMany
{
return $this->belongsToMany(User::class, 'user_saved_jobs')
->withTimestamps();
}
/**
* Scope a query to only include active jobs.
*/
public function scopeActive($query)
{
return $query->where(function ($q) {
$q->whereNull('expires_at')
->orWhere('expires_at', '>', now());
});
}
/**
* Scope a query to only include remote jobs.
*/
public function scopeRemote($query)
{
return $query->where('remote_allowed', true);
}
/**
* Scope a query to filter by job type.
*/
public function scopeOfType($query, string $type)
{
return $query->where('job_type', $type);
}
/**
* Scope a query to filter by experience level.
*/
public function scopeExperienceLevel($query, string $level)
{
return $query->where('experience_level', $level);
}
/**
* Scope a query to search by keywords in title, company, and description.
*/
public function scopeSearchKeywords($query, string $keywords)
{
return $query->where(function ($q) use ($keywords) {
$q->where('title', 'LIKE', "%{$keywords}%")
->orWhere('company', 'LIKE', "%{$keywords}%")
->orWhere('description', 'LIKE', "%{$keywords}%");
});
}
/**
* Scope a query to filter by category.
*/
public function scopeInCategory($query, int $categoryId)
{
return $query->where('job_category_id', $categoryId);
}
/**
* Scope a query to filter by location.
*/
public function scopeInLocation($query, string $location)
{
return $query->where(function ($q) use ($location) {
$q->where('location', 'LIKE', "%{$location}%")
->orWhereHas('jobLocation', function ($q2) use ($location) {
$q2->where('city', 'LIKE', "%{$location}%")
->orWhere('state', 'LIKE', "%{$location}%")
->orWhere('country', 'LIKE', "%{$location}%");
});
});
}
/**
* Scope a query to filter by salary range.
*/
public function scopeWithinSalaryRange($query, ?float $minSalary = null, ?float $maxSalary = null)
{
if ($minSalary) {
$query->where(function ($q) use ($minSalary) {
$q->where('salary_max', '>=', $minSalary)
->orWhereNull('salary_max');
});
}
if ($maxSalary) {
$query->where(function ($q) use ($maxSalary) {
$q->where('salary_min', '<=', $maxSalary)
->orWhereNull('salary_min');
});
}
return $query;
}
/**
* Scope a query to filter by posted date.
*/
public function scopePostedWithin($query, int $days)
{
return $query->where(function ($q) use ($days) {
$q->where('posted_at', '>=', now()->subDays($days))
->orWhere(function ($q2) use ($days) {
$q2->whereNull('posted_at')
->where('created_at', '>=', now()->subDays($days));
});
});
}
/**
* Scope a query to filter by company.
*/
public function scopeByCompany($query, string $company)
{
return $query->where('company', 'LIKE', "%{$company}%");
}
}