* @since February 2025 */ abstract class BaseRepository implements BaseRepositoryInterface { /** * The model instance * * @var Model */ protected Model $model; /** * The query builder instance * * @var Builder */ protected Builder $query; /** * Create a new repository instance * * @param Model $model */ public function __construct(Model $model) { $this->model = $model; $this->resetQuery(); } /** * Get all records * * @param array $columns * @return Collection */ public function all(array $columns = ['*']): Collection { $result = $this->query->get($columns); $this->resetQuery(); return $result; } /** * Get records with pagination * * @param int $perPage * @param array $columns * @return LengthAwarePaginator */ public function paginate(int $perPage = 15, array $columns = ['*']): LengthAwarePaginator { $result = $this->query->paginate($perPage, $columns); $this->resetQuery(); return $result; } /** * Find a record by ID * * @param int $id * @param array $columns * @return Model|null */ public function find(int $id, array $columns = ['*']): ?Model { $result = $this->query->find($id, $columns); $this->resetQuery(); return $result; } /** * Find a record by ID or throw an exception * * @param int $id * @param array $columns * @return Model * @throws ModelNotFoundException */ public function findOrFail(int $id, array $columns = ['*']): Model { $result = $this->query->findOrFail($id, $columns); $this->resetQuery(); return $result; } /** * Find records by criteria * * @param array $criteria * @param array $columns * @return Collection */ public function findBy(array $criteria, array $columns = ['*']): Collection { $this->applyCriteria($criteria); $result = $this->query->get($columns); $this->resetQuery(); return $result; } /** * Find a single record by criteria * * @param array $criteria * @param array $columns * @return Model|null */ public function findOneBy(array $criteria, array $columns = ['*']): ?Model { $this->applyCriteria($criteria); $result = $this->query->first($columns); $this->resetQuery(); return $result; } /** * Create a new record * * @param array $data * @return Model */ public function create(array $data): Model { return $this->model->create($data); } /** * Update an existing record * * @param int $id * @param array $data * @return bool */ public function update(int $id, array $data): bool { $model = $this->findOrFail($id); return $model->update($data); } /** * Update or create a record * * @param array $attributes * @param array $values * @return Model */ public function updateOrCreate(array $attributes, array $values = []): Model { return $this->model->updateOrCreate($attributes, $values); } /** * Delete a record by ID * * @param int $id * @return bool */ public function delete(int $id): bool { $model = $this->findOrFail($id); return $model->delete(); } /** * Delete records by criteria * * @param array $criteria * @return int Number of deleted records */ public function deleteBy(array $criteria): int { $this->applyCriteria($criteria); $result = $this->query->delete(); $this->resetQuery(); return $result; } /** * Count records * * @param array $criteria * @return int */ public function count(array $criteria = []): int { if (!empty($criteria)) { $this->applyCriteria($criteria); } $result = $this->query->count(); $this->resetQuery(); return $result; } /** * Check if record exists * * @param array $criteria * @return bool */ public function exists(array $criteria): bool { $this->applyCriteria($criteria); $result = $this->query->exists(); $this->resetQuery(); return $result; } /** * Get records with relationships * * @param array $relations * @return BaseRepositoryInterface */ public function with(array $relations): BaseRepositoryInterface { $this->query = $this->query->with($relations); return $this; } /** * Order records * * @param string $column * @param string $direction * @return BaseRepositoryInterface */ public function orderBy(string $column, string $direction = 'asc'): BaseRepositoryInterface { $this->query = $this->query->orderBy($column, $direction); return $this; } /** * Limit records * * @param int $limit * @return BaseRepositoryInterface */ public function limit(int $limit): BaseRepositoryInterface { $this->query = $this->query->limit($limit); return $this; } /** * Apply criteria to the query * * @param array $criteria * @return void */ protected function applyCriteria(array $criteria): void { foreach ($criteria as $field => $value) { if (is_array($value)) { $this->query = $this->query->whereIn($field, $value); } elseif (is_null($value)) { $this->query = $this->query->whereNull($field); } else { $this->query = $this->query->where($field, $value); } } } /** * Reset the query builder * * @return void */ protected function resetQuery(): void { $this->query = $this->model->newQuery(); } /** * Get the model instance * * @return Model */ public function getModel(): Model { return $this->model; } /** * Set the model instance * * @param Model $model * @return void */ public function setModel(Model $model): void { $this->model = $model; $this->resetQuery(); } /** * Execute a callback within a database transaction * * @param callable $callback * @return mixed * @throws \Throwable */ protected function transaction(callable $callback) { return $this->model->getConnection()->transaction($callback); } /** * Get fresh timestamp for the model * * @return \Carbon\Carbon */ protected function freshTimestamp(): \Carbon\Carbon { return $this->model->freshTimestamp(); } }