feat: implement repository architecture with smart caching
- Add base repository interfaces and abstract classes - Implement separated read/write repositories for Domain and Username models - Add intelligent query caching with automatic invalidation - Include cache management service and CLI commands - Add comprehensive configuration for cache TTL and monitoring - Enhance performance through optimized data access patterns
This commit is contained in:
335
app/Repositories/BaseRepository.php
Normal file
335
app/Repositories/BaseRepository.php
Normal file
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Repositories\Contracts\ReadRepositoryInterface;
|
||||
use Illuminate\Cache\CacheManager;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
abstract class BaseRepository implements ReadRepositoryInterface
|
||||
{
|
||||
protected Model $model;
|
||||
|
||||
protected CacheManager $cache;
|
||||
|
||||
protected Builder $query;
|
||||
|
||||
protected array $withRelations = [];
|
||||
|
||||
protected array $withCountRelations = [];
|
||||
|
||||
protected string $cacheTag;
|
||||
|
||||
protected int $cacheTtl = 3600; // 1 hour default
|
||||
|
||||
protected bool $cachingEnabled = true;
|
||||
|
||||
public function __construct(Model $model, CacheManager $cache)
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->cache = $cache;
|
||||
$this->query = $model->newQuery();
|
||||
$this->cacheTag = $this->getCacheTag();
|
||||
}
|
||||
|
||||
abstract protected function getCacheTag(): string;
|
||||
|
||||
protected function getCacheKey(string $method, array $parameters = []): string
|
||||
{
|
||||
$key = $this->cacheTag.':'.$method;
|
||||
|
||||
if (! empty($parameters)) {
|
||||
$key .= ':'.md5(serialize($parameters));
|
||||
}
|
||||
|
||||
$key .= ':'.md5(serialize($this->withRelations));
|
||||
$key .= ':'.md5(serialize($this->withCountRelations));
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
protected function executeQuery(callable $callback, ?string $cacheKey = null, ?int $ttl = null)
|
||||
{
|
||||
if (! $this->cachingEnabled || $cacheKey === null) {
|
||||
return $callback();
|
||||
}
|
||||
|
||||
$ttl = $ttl ?? $this->cacheTtl;
|
||||
|
||||
return $this->cache->tags([$this->cacheTag])->remember($cacheKey, $ttl, $callback);
|
||||
}
|
||||
|
||||
protected function resetQuery(): void
|
||||
{
|
||||
$this->query = $this->model->newQuery();
|
||||
$this->withRelations = [];
|
||||
$this->withCountRelations = [];
|
||||
}
|
||||
|
||||
public function findById(int $id, array $columns = ['*']): ?Model
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('find_by_id', ['id' => $id, 'columns' => $columns]);
|
||||
|
||||
return $this->executeQuery(function () use ($id, $columns) {
|
||||
$result = $this->query->find($id, $columns);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function findBy(string $column, mixed $value, array $columns = ['*']): ?Model
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('find_by', [$column => $value, 'columns' => $columns]);
|
||||
|
||||
return $this->executeQuery(function () use ($column, $value, $columns) {
|
||||
$result = $this->query->where($column, $value)->first($columns);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function all(array $columns = ['*']): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('all', ['columns' => $columns]);
|
||||
|
||||
return $this->executeQuery(function () use ($columns) {
|
||||
$result = $this->query->get($columns);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function get(array $columns = ['*']): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('get', ['columns' => $columns]);
|
||||
|
||||
return $this->executeQuery(function () use ($columns) {
|
||||
$result = $this->query->get($columns);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function paginate(int $perPage = 15, array $columns = ['*'], string $pageName = 'page'): LengthAwarePaginator
|
||||
{
|
||||
$page = request()->input($pageName, 1);
|
||||
$cacheKey = $this->getCacheKey('paginate', [
|
||||
'per_page' => $perPage,
|
||||
'columns' => $columns,
|
||||
'page' => $page,
|
||||
]);
|
||||
|
||||
return $this->executeQuery(function () use ($perPage, $columns, $pageName) {
|
||||
$result = $this->query->paginate($perPage, $columns, $pageName);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800); // 30 minutes for pagination
|
||||
}
|
||||
|
||||
public function whereIn(string $column, array $values, array $columns = ['*']): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('where_in', [$column => $values, 'columns' => $columns]);
|
||||
|
||||
return $this->executeQuery(function () use ($column, $values, $columns) {
|
||||
$result = $this->query->whereIn($column, $values)->get($columns);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function where(string $column, mixed $operator, mixed $value = null): static
|
||||
{
|
||||
if (func_num_args() === 2) {
|
||||
$this->query->where($column, $operator);
|
||||
} else {
|
||||
$this->query->where($column, $operator, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereNull(string $column): static
|
||||
{
|
||||
$this->query->whereNull($column);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereNotNull(string $column): static
|
||||
{
|
||||
$this->query->whereNotNull($column);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereBetween(string $column, array $values): static
|
||||
{
|
||||
$this->query->whereBetween($column, $values);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function orderBy(string $column, string $direction = 'asc'): static
|
||||
{
|
||||
$this->query->orderBy($column, $direction);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function limit(int $limit): static
|
||||
{
|
||||
$this->query->limit($limit);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function with(array $relations): static
|
||||
{
|
||||
$this->withRelations = array_merge($this->withRelations, $relations);
|
||||
$this->query->with($relations);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withCount(array $relations): static
|
||||
{
|
||||
$this->withCountRelations = array_merge($this->withCountRelations, $relations);
|
||||
$this->query->withCount($relations);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function exists(): bool
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('exists');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query->exists();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 300); // 5 minutes for exists check
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query->count();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 600); // 10 minutes for count
|
||||
}
|
||||
|
||||
public function first(array $columns = ['*']): ?Model
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('first', ['columns' => $columns]);
|
||||
|
||||
return $this->executeQuery(function () use ($columns) {
|
||||
$result = $this->query->first($columns);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function firstWhere(string $column, mixed $operator, mixed $value = null): ?Model
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('first_where', [$column => $operator, 'value' => $value]);
|
||||
|
||||
return $this->executeQuery(function () use ($column, $operator, $value) {
|
||||
if (func_num_args() === 2) {
|
||||
$result = $this->query->firstWhere($column, $operator);
|
||||
} else {
|
||||
$result = $this->query->firstWhere($column, $operator, $value);
|
||||
}
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function pluck(string $column, ?string $key = null): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('pluck', ['column' => $column, 'key' => $key]);
|
||||
|
||||
return $this->executeQuery(function () use ($column, $key) {
|
||||
$result = $this->query->pluck($column, $key);
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey);
|
||||
}
|
||||
|
||||
public function clearCache(): void
|
||||
{
|
||||
$this->cache->tags([$this->cacheTag])->flush();
|
||||
}
|
||||
|
||||
public function clearCacheForModel(Model $model): void
|
||||
{
|
||||
$this->cache->tags([$this->cacheTag])->flush();
|
||||
}
|
||||
|
||||
public function disableCaching(): static
|
||||
{
|
||||
$this->cachingEnabled = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function enableCaching(): static
|
||||
{
|
||||
$this->cachingEnabled = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCacheTtl(int $ttl): static
|
||||
{
|
||||
$this->cacheTtl = $ttl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function startTransaction(): void
|
||||
{
|
||||
DB::beginTransaction();
|
||||
}
|
||||
|
||||
protected function commitTransaction(): void
|
||||
{
|
||||
DB::commit();
|
||||
}
|
||||
|
||||
protected function rollbackTransaction(): void
|
||||
{
|
||||
DB::rollBack();
|
||||
}
|
||||
|
||||
public function transaction(callable $callback): mixed
|
||||
{
|
||||
try {
|
||||
$this->startTransaction();
|
||||
$result = $callback();
|
||||
$this->commitTransaction();
|
||||
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
$this->rollbackTransaction();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
app/Repositories/Contracts/ReadRepositoryInterface.php
Normal file
52
app/Repositories/Contracts/ReadRepositoryInterface.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Contracts;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
interface ReadRepositoryInterface
|
||||
{
|
||||
public function findById(int $id, array $columns = ['*']): ?Model;
|
||||
|
||||
public function findBy(string $column, mixed $value, array $columns = ['*']): ?Model;
|
||||
|
||||
public function all(array $columns = ['*']): Collection;
|
||||
|
||||
public function get(array $columns = ['*']): Collection;
|
||||
|
||||
public function paginate(int $perPage = 15, array $columns = ['*'], string $pageName = 'page'): LengthAwarePaginator;
|
||||
|
||||
public function whereIn(string $column, array $values, array $columns = ['*']): Collection;
|
||||
|
||||
public function where(string $column, mixed $operator, mixed $value = null): self;
|
||||
|
||||
public function whereNull(string $column): self;
|
||||
|
||||
public function whereNotNull(string $column): self;
|
||||
|
||||
public function whereBetween(string $column, array $values): self;
|
||||
|
||||
public function orderBy(string $column, string $direction = 'asc'): self;
|
||||
|
||||
public function limit(int $limit): self;
|
||||
|
||||
public function with(array $relations): self;
|
||||
|
||||
public function withCount(array $relations): self;
|
||||
|
||||
public function exists(): bool;
|
||||
|
||||
public function count(): int;
|
||||
|
||||
public function first(array $columns = ['*']): ?Model;
|
||||
|
||||
public function firstWhere(string $column, mixed $operator, mixed $value = null): ?Model;
|
||||
|
||||
public function pluck(string $column, ?string $key = null): Collection;
|
||||
|
||||
public function clearCache(): void;
|
||||
|
||||
public function clearCacheForModel(Model $model): void;
|
||||
}
|
||||
16
app/Repositories/Contracts/RepositoryInterface.php
Normal file
16
app/Repositories/Contracts/RepositoryInterface.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Contracts;
|
||||
|
||||
interface RepositoryInterface extends ReadRepositoryInterface, WriteRepositoryInterface
|
||||
{
|
||||
public function getModel(): string;
|
||||
|
||||
public function startTransaction(): void;
|
||||
|
||||
public function commitTransaction(): void;
|
||||
|
||||
public function rollbackTransaction(): void;
|
||||
|
||||
public function transaction(callable $callback): mixed;
|
||||
}
|
||||
45
app/Repositories/Contracts/WriteRepositoryInterface.php
Normal file
45
app/Repositories/Contracts/WriteRepositoryInterface.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Contracts;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
interface WriteRepositoryInterface
|
||||
{
|
||||
public function create(array $data): Model;
|
||||
|
||||
public function createMany(array $data): Collection;
|
||||
|
||||
public function update(Model $model, array $data): bool;
|
||||
|
||||
public function updateById(int $id, array $data): bool;
|
||||
|
||||
public function upsert(array $data, array|string $uniqueBy, ?array $update = null): Collection;
|
||||
|
||||
public function delete(Model $model): bool;
|
||||
|
||||
public function deleteById(int $id): bool;
|
||||
|
||||
public function deleteMultiple(array $ids): int;
|
||||
|
||||
public function restore(Model $model): bool;
|
||||
|
||||
public function restoreById(int $id): bool;
|
||||
|
||||
public function forceDelete(Model $model): bool;
|
||||
|
||||
public function forceDeleteById(int $id): bool;
|
||||
|
||||
public function sync(Model $model, string $relation, array $ids, bool $detaching = true): array;
|
||||
|
||||
public function attach(Model $model, string $relation, array $ids, array $attributes = [], bool $touch = true): void;
|
||||
|
||||
public function detach(Model $model, string $relation, ?array $ids = null, bool $touch = true): int;
|
||||
|
||||
public function clearCache(): void;
|
||||
|
||||
public function clearCacheForModel(Model $model): void;
|
||||
|
||||
public function clearCacheForCollection(Collection $models): void;
|
||||
}
|
||||
224
app/Repositories/Domain/Read/DomainReadRepository.php
Normal file
224
app/Repositories/Domain/Read/DomainReadRepository.php
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Domain\Read;
|
||||
|
||||
use App\enum\DomainType;
|
||||
use App\enum\ProviderType;
|
||||
use App\Models\Domain;
|
||||
use App\Repositories\BaseRepository;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class DomainReadRepository extends BaseRepository
|
||||
{
|
||||
protected function getCacheTag(): string
|
||||
{
|
||||
return 'domains';
|
||||
}
|
||||
|
||||
public function getModel(): string
|
||||
{
|
||||
return Domain::class;
|
||||
}
|
||||
|
||||
public function findActive(): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('active');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800); // 30 minutes
|
||||
}
|
||||
|
||||
public function findActiveByType(?DomainType $domainType = null, ?ProviderType $providerType = null): array
|
||||
{
|
||||
$params = [
|
||||
'domain_type' => $domainType?->value,
|
||||
'provider_type' => $providerType?->value,
|
||||
];
|
||||
$cacheKey = $this->getCacheKey('active_by_type', $params);
|
||||
|
||||
return $this->executeQuery(function () use ($domainType, $providerType) {
|
||||
$query = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
});
|
||||
|
||||
if ($domainType) {
|
||||
$query->where('domain_type', $domainType->value);
|
||||
}
|
||||
|
||||
if ($providerType) {
|
||||
$query->where('provider_type', $providerType->value);
|
||||
}
|
||||
|
||||
$result = $query->pluck('name')->toArray();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800); // 30 minutes
|
||||
}
|
||||
|
||||
public function findActiveByProvider(ProviderType $providerType): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('active_by_provider', ['provider' => $providerType->value]);
|
||||
|
||||
return $this->executeQuery(function () use ($providerType) {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where('provider_type', $providerType->value)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findExpiringSoon(int $days = 7): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('expiring_soon', ['days' => $days]);
|
||||
|
||||
return $this->executeQuery(function () use ($days) {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->whereNotNull('ends_at')
|
||||
->where('ends_at', '<=', now()->addDays($days))
|
||||
->where('ends_at', '>', now())
|
||||
->orderBy('ends_at', 'asc')
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 900); // 15 minutes
|
||||
}
|
||||
|
||||
public function findInactive(): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('inactive');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', false)
|
||||
->orWhere(function ($query) {
|
||||
$query->whereNotNull('starts_at')
|
||||
->where('starts_at', '>', now());
|
||||
})
|
||||
->orWhere(function ($query) {
|
||||
$query->whereNotNull('ends_at')
|
||||
->where('ends_at', '<', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findRecentlyUsed(int $hours = 24): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('recently_used', ['hours' => $hours]);
|
||||
|
||||
return $this->executeQuery(function () use ($hours) {
|
||||
$result = $this->query
|
||||
->whereNotNull('last_used_at')
|
||||
->where('last_used_at', '>=', now()->subHours($hours))
|
||||
->orderBy('last_used_at', 'desc')
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 900); // 15 minutes
|
||||
}
|
||||
|
||||
public function findByName(string $name): ?Domain
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('find_by_name', ['name' => $name]);
|
||||
|
||||
return $this->executeQuery(function () use ($name) {
|
||||
$result = $this->query->where('name', $name)->first();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 3600); // 1 hour
|
||||
}
|
||||
|
||||
public function countActive(): int
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count_active');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->count();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 600); // 10 minutes
|
||||
}
|
||||
|
||||
public function countByProvider(): array
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count_by_provider');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->selectRaw('provider_type, COUNT(*) as count')
|
||||
->groupBy('provider_type')
|
||||
->pluck('count', 'provider_type')
|
||||
->toArray();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function countByType(): array
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count_by_type');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->selectRaw('domain_type, COUNT(*) as count')
|
||||
->groupBy('domain_type')
|
||||
->pluck('count', 'domain_type')
|
||||
->toArray();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
}
|
||||
103
app/Repositories/Domain/Write/DomainWriteRepository.php
Normal file
103
app/Repositories/Domain/Write/DomainWriteRepository.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Domain\Write;
|
||||
|
||||
use App\Models\Domain;
|
||||
use App\Repositories\WriteRepository;
|
||||
|
||||
class DomainWriteRepository extends WriteRepository
|
||||
{
|
||||
protected function getCacheTag(): string
|
||||
{
|
||||
return 'domains';
|
||||
}
|
||||
|
||||
protected function getReadRepositoryClass(): string
|
||||
{
|
||||
return \App\Repositories\Domain\Read\DomainReadRepository::class;
|
||||
}
|
||||
|
||||
public function activateDomain(Domain $domain): bool
|
||||
{
|
||||
$domain->is_active = true;
|
||||
$result = $domain->save();
|
||||
$this->clearRelatedCache($domain);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function deactivateDomain(Domain $domain): bool
|
||||
{
|
||||
$domain->is_active = false;
|
||||
$result = $domain->save();
|
||||
$this->clearRelatedCache($domain);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateUsage(Domain $domain): bool
|
||||
{
|
||||
$domain->last_used_at = now();
|
||||
$domain->checked_at = now();
|
||||
$result = $domain->save();
|
||||
$this->clearRelatedCache($domain);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateCheckedAt(Domain $domain): bool
|
||||
{
|
||||
$domain->checked_at = now();
|
||||
$result = $domain->save();
|
||||
$this->clearRelatedCache($domain);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setExpiration(Domain $domain, ?\DateTime $endsAt = null): bool
|
||||
{
|
||||
$domain->ends_at = $endsAt;
|
||||
$result = $domain->save();
|
||||
$this->clearRelatedCache($domain);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function bulkActivate(array $domainIds): int
|
||||
{
|
||||
$updated = Domain::whereIn('id', $domainIds)->update(['is_active' => true]);
|
||||
$this->clearCache();
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
public function bulkDeactivate(array $domainIds): int
|
||||
{
|
||||
$updated = Domain::whereIn('id', $domainIds)->update(['is_active' => false]);
|
||||
$this->clearCache();
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
public function updateDailyMailboxLimit(Domain $domain, int $limit): bool
|
||||
{
|
||||
$domain->daily_mailbox_limit = $limit;
|
||||
$result = $domain->save();
|
||||
$this->clearRelatedCache($domain);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function createWithDefaults(array $data): Domain
|
||||
{
|
||||
$defaults = [
|
||||
'is_active' => true,
|
||||
'daily_mailbox_limit' => 100,
|
||||
'checked_at' => now(),
|
||||
];
|
||||
|
||||
$domainData = array_merge($defaults, $data);
|
||||
|
||||
return $this->create($domainData);
|
||||
}
|
||||
}
|
||||
317
app/Repositories/Username/Read/UsernameReadRepository.php
Normal file
317
app/Repositories/Username/Read/UsernameReadRepository.php
Normal file
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Username\Read;
|
||||
|
||||
use App\enum\ProviderType;
|
||||
use App\enum\UsernameType;
|
||||
use App\Models\Username;
|
||||
use App\Repositories\BaseRepository;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class UsernameReadRepository extends BaseRepository
|
||||
{
|
||||
protected function getCacheTag(): string
|
||||
{
|
||||
return 'usernames';
|
||||
}
|
||||
|
||||
public function getModel(): string
|
||||
{
|
||||
return Username::class;
|
||||
}
|
||||
|
||||
public function findActive(): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('active');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800); // 30 minutes
|
||||
}
|
||||
|
||||
public function findActiveByType(?UsernameType $usernameType = null, ?ProviderType $providerType = null): array
|
||||
{
|
||||
$params = [
|
||||
'username_type' => $usernameType?->value,
|
||||
'provider_type' => $providerType?->value,
|
||||
];
|
||||
$cacheKey = $this->getCacheKey('active_by_type', $params);
|
||||
|
||||
return $this->executeQuery(function () use ($usernameType, $providerType) {
|
||||
$query = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
});
|
||||
|
||||
if ($usernameType) {
|
||||
$query->where('username_type', $usernameType->value);
|
||||
}
|
||||
|
||||
if ($providerType) {
|
||||
$query->where('provider_type', $providerType->value);
|
||||
}
|
||||
|
||||
$result = $query->pluck('username')->toArray();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800); // 30 minutes
|
||||
}
|
||||
|
||||
public function findActiveByProvider(ProviderType $providerType): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('active_by_provider', ['provider' => $providerType->value]);
|
||||
|
||||
return $this->executeQuery(function () use ($providerType) {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where('provider_type', $providerType->value)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findPublicActive(): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('public_active');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where('username_type', UsernameType::PUBLIC->value)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findPremiumActive(): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('premium_active');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where('username_type', UsernameType::PREMIUM->value)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findExpiringSoon(int $days = 7): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('expiring_soon', ['days' => $days]);
|
||||
|
||||
return $this->executeQuery(function () use ($days) {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->whereNotNull('ends_at')
|
||||
->where('ends_at', '<=', now()->addDays($days))
|
||||
->where('ends_at', '>', now())
|
||||
->orderBy('ends_at', 'asc')
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 900); // 15 minutes
|
||||
}
|
||||
|
||||
public function findInactive(): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('inactive');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', false)
|
||||
->orWhere(function ($query) {
|
||||
$query->whereNotNull('starts_at')
|
||||
->where('starts_at', '>', now());
|
||||
})
|
||||
->orWhere(function ($query) {
|
||||
$query->whereNotNull('ends_at')
|
||||
->where('ends_at', '<', now());
|
||||
})
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findRecentlyUsed(int $hours = 24): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('recently_used', ['hours' => $hours]);
|
||||
|
||||
return $this->executeQuery(function () use ($hours) {
|
||||
$result = $this->query
|
||||
->whereNotNull('last_used_at')
|
||||
->where('last_used_at', '>=', now()->subHours($hours))
|
||||
->orderBy('last_used_at', 'desc')
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 900); // 15 minutes
|
||||
}
|
||||
|
||||
public function findByUsername(string $username): ?Username
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('find_by_username', ['username' => $username]);
|
||||
|
||||
return $this->executeQuery(function () use ($username) {
|
||||
$result = $this->query->where('username', $username)->first();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 3600); // 1 hour
|
||||
}
|
||||
|
||||
public function countActive(): int
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count_active');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->count();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 600); // 10 minutes
|
||||
}
|
||||
|
||||
public function countByProvider(): array
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count_by_provider');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->selectRaw('provider_type, COUNT(*) as count')
|
||||
->groupBy('provider_type')
|
||||
->pluck('count', 'provider_type')
|
||||
->toArray();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function countByType(): array
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('count_by_type');
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->selectRaw('username_type, COUNT(*) as count')
|
||||
->groupBy('username_type')
|
||||
->pluck('count', 'username_type')
|
||||
->toArray();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
|
||||
public function findAvailableForUse(UsernameType $type, int $limit = 10): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('available_for_use', [
|
||||
'type' => $type->value,
|
||||
'limit' => $limit,
|
||||
]);
|
||||
|
||||
return $this->executeQuery(function () use ($type, $limit) {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where('username_type', $type->value)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('starts_at')
|
||||
->orWhere('starts_at', '<=', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ends_at')
|
||||
->orWhere('ends_at', '>=', now());
|
||||
})
|
||||
->orderBy('last_used_at', 'asc')
|
||||
->limit($limit)
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 300); // 5 minutes
|
||||
}
|
||||
|
||||
public function findUnused(int $days = 30): Collection
|
||||
{
|
||||
$cacheKey = $this->getCacheKey('unused', ['days' => $days]);
|
||||
|
||||
return $this->executeQuery(function () {
|
||||
$result = $this->query
|
||||
->where('is_active', true)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('last_used_at')
|
||||
->orWhere('last_used_at', '<', now()->subDays($days));
|
||||
})
|
||||
->orderBy('last_used_at', 'asc')
|
||||
->get();
|
||||
$this->resetQuery();
|
||||
|
||||
return $result;
|
||||
}, $cacheKey, 1800);
|
||||
}
|
||||
}
|
||||
163
app/Repositories/Username/Write/UsernameWriteRepository.php
Normal file
163
app/Repositories/Username/Write/UsernameWriteRepository.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories\Username\Write;
|
||||
|
||||
use App\enum\UsernameType;
|
||||
use App\Models\Username;
|
||||
use App\Repositories\WriteRepository;
|
||||
|
||||
class UsernameWriteRepository extends WriteRepository
|
||||
{
|
||||
protected function getCacheTag(): string
|
||||
{
|
||||
return 'usernames';
|
||||
}
|
||||
|
||||
protected function getReadRepositoryClass(): string
|
||||
{
|
||||
return \App\Repositories\Username\Read\UsernameReadRepository::class;
|
||||
}
|
||||
|
||||
public function activateUsername(Username $username): bool
|
||||
{
|
||||
$username->is_active = true;
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function deactivateUsername(Username $username): bool
|
||||
{
|
||||
$username->is_active = false;
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateUsage(Username $username): bool
|
||||
{
|
||||
$username->last_used_at = now();
|
||||
$username->checked_at = now();
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateCheckedAt(Username $username): bool
|
||||
{
|
||||
$username->checked_at = now();
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setExpiration(Username $username, ?\DateTime $endsAt = null): bool
|
||||
{
|
||||
$username->ends_at = $endsAt;
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setStartDate(Username $username, ?\DateTime $startsAt = null): bool
|
||||
{
|
||||
$username->starts_at = $startsAt;
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function changeType(Username $username, UsernameType $type): bool
|
||||
{
|
||||
$username->username_type = $type->value;
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function bulkActivate(array $usernameIds): int
|
||||
{
|
||||
$updated = Username::whereIn('id', $usernameIds)->update(['is_active' => true]);
|
||||
$this->clearCache();
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
public function bulkDeactivate(array $usernameIds): int
|
||||
{
|
||||
$updated = Username::whereIn('id', $usernameIds)->update(['is_active' => false]);
|
||||
$this->clearCache();
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
public function updateDailyMailboxLimit(Username $username, int $limit): bool
|
||||
{
|
||||
$username->daily_mailbox_limit = $limit;
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function createWithDefaults(array $data): Username
|
||||
{
|
||||
$defaults = [
|
||||
'is_active' => true,
|
||||
'daily_mailbox_limit' => 100,
|
||||
'checked_at' => now(),
|
||||
];
|
||||
|
||||
$usernameData = array_merge($defaults, $data);
|
||||
|
||||
return $this->create($usernameData);
|
||||
}
|
||||
|
||||
public function markAsUsed(Username $username): bool
|
||||
{
|
||||
$username->last_used_at = now();
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function resetUsage(Username $username): bool
|
||||
{
|
||||
$username->last_used_at = null;
|
||||
$username->checked_at = now();
|
||||
$result = $username->save();
|
||||
$this->clearRelatedCache($username);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function bulkUpdateUsage(array $usernameIds): int
|
||||
{
|
||||
$updated = Username::whereIn('id', $usernameIds)->update([
|
||||
'last_used_at' => now(),
|
||||
'checked_at' => now(),
|
||||
]);
|
||||
$this->clearCache();
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
public function bulkResetUsage(array $usernameIds): int
|
||||
{
|
||||
$updated = Username::whereIn('id', $usernameIds)->update([
|
||||
'last_used_at' => null,
|
||||
'checked_at' => now(),
|
||||
]);
|
||||
$this->clearCache();
|
||||
|
||||
return $updated;
|
||||
}
|
||||
}
|
||||
187
app/Repositories/WriteRepository.php
Normal file
187
app/Repositories/WriteRepository.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Repositories\Contracts\WriteRepositoryInterface;
|
||||
use Illuminate\Cache\CacheManager;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
abstract class WriteRepository implements WriteRepositoryInterface
|
||||
{
|
||||
protected Model $model;
|
||||
|
||||
protected CacheManager $cache;
|
||||
|
||||
protected string $cacheTag;
|
||||
|
||||
protected string $readRepositoryClass;
|
||||
|
||||
public function __construct(Model $model, CacheManager $cache)
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->cache = $cache;
|
||||
$this->cacheTag = $this->getCacheTag();
|
||||
$this->readRepositoryClass = $this->getReadRepositoryClass();
|
||||
}
|
||||
|
||||
abstract protected function getCacheTag(): string;
|
||||
|
||||
abstract protected function getReadRepositoryClass(): string;
|
||||
|
||||
protected function getReadRepository(): mixed
|
||||
{
|
||||
return app($this->readRepositoryClass);
|
||||
}
|
||||
|
||||
protected function clearRelatedCache(Model $model): void
|
||||
{
|
||||
$this->getReadRepository()->clearCacheForModel($model);
|
||||
}
|
||||
|
||||
protected function clearCollectionCache(Collection $models): void
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$this->clearRelatedCache($model);
|
||||
}
|
||||
}
|
||||
|
||||
public function create(array $data): Model
|
||||
{
|
||||
$model = $this->model->create($data);
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function createMany(array $data): Collection
|
||||
{
|
||||
$models = $this->model->insert($data) ? $this->model->whereIn('id',
|
||||
$this->model->latest()->take(count($data))->pluck('id')
|
||||
)->get() : collect();
|
||||
|
||||
$this->getReadRepository()->clearCache();
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
public function update(Model $model, array $data): bool
|
||||
{
|
||||
$result = $model->update($data);
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updateById(int $id, array $data): bool
|
||||
{
|
||||
$model = $this->model->findOrFail($id);
|
||||
|
||||
return $this->update($model, $data);
|
||||
}
|
||||
|
||||
public function upsert(array $data, array|string $uniqueBy, ?array $update = null): Collection
|
||||
{
|
||||
$this->model->upsert($data, $uniqueBy, $update);
|
||||
|
||||
// Clear all cache since upsert can affect multiple records
|
||||
$this->getReadRepository()->clearCache();
|
||||
|
||||
// Return the upserted records
|
||||
$uniqueValues = collect($data)->pluck($uniqueBy);
|
||||
|
||||
return $this->model->whereIn($uniqueBy, $uniqueValues)->get();
|
||||
}
|
||||
|
||||
public function delete(Model $model): bool
|
||||
{
|
||||
$result = $model->delete();
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function deleteById(int $id): bool
|
||||
{
|
||||
$model = $this->model->findOrFail($id);
|
||||
|
||||
return $this->delete($model);
|
||||
}
|
||||
|
||||
public function deleteMultiple(array $ids): int
|
||||
{
|
||||
$deleted = $this->model->whereIn('id', $ids)->delete();
|
||||
|
||||
// Clear all cache since multiple records are deleted
|
||||
$this->getReadRepository()->clearCache();
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
public function restore(Model $model): bool
|
||||
{
|
||||
$result = $model->restore();
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function restoreById(int $id): bool
|
||||
{
|
||||
$model = $this->model->withTrashed()->findOrFail($id);
|
||||
|
||||
return $this->restore($model);
|
||||
}
|
||||
|
||||
public function forceDelete(Model $model): bool
|
||||
{
|
||||
$result = $model->forceDelete();
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function forceDeleteById(int $id): bool
|
||||
{
|
||||
$model = $this->model->withTrashed()->findOrFail($id);
|
||||
|
||||
return $this->forceDelete($model);
|
||||
}
|
||||
|
||||
public function sync(Model $model, string $relation, array $ids, bool $detaching = true): array
|
||||
{
|
||||
$result = $model->{$relation}()->sync($ids, $detaching);
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function attach(Model $model, string $relation, array $ids, array $attributes = [], bool $touch = true): void
|
||||
{
|
||||
$model->{$relation}()->attach($ids, $attributes, $touch);
|
||||
$this->clearRelatedCache($model);
|
||||
}
|
||||
|
||||
public function detach(Model $model, string $relation, ?array $ids = null, bool $touch = true): int
|
||||
{
|
||||
$result = $model->{$relation}()->detach($ids, $touch);
|
||||
$this->clearRelatedCache($model);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function clearCache(): void
|
||||
{
|
||||
$this->getReadRepository()->clearCache();
|
||||
}
|
||||
|
||||
public function clearCacheForModel(Model $model): void
|
||||
{
|
||||
$this->clearRelatedCache($model);
|
||||
}
|
||||
|
||||
public function clearCacheForCollection(Collection $models): void
|
||||
{
|
||||
$this->clearCollectionCache($models);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user