Files
Laravel/app/Repositories/BaseRepository.php
David Melendez e25d53d054 init commit
2026-01-14 22:38:44 +01:00

346 lines
7.5 KiB
PHP

<?php
namespace App\Repositories;
use App\Interfaces\BaseRepositoryInterface;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\ModelNotFoundException;
/**
* Base Repository Implementation
*
* Provides common repository functionality for all models.
* Implements the BaseRepositoryInterface with reusable methods.
*
* @author David Valera Melendez <david@valera-melendez.de>
* @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();
}
}