Bu yapı sayesinde CRUD işlemleri, listeleme, güncelleme ve silme gibi ortak işlevler tek bir merkezden yönetilir ve her model için tekrar tekrar yazılmasına gerek kalmaz.
Bu mimari 3 temel parçadan oluşur:
ServiceInterface, tüm servislerin uyması gereken kuralları tanımlar.
Bu sayede her servis:
Interface üzerinde Generic Type (Template) kullanılarak:
tipleri dinamik hale getirilmiştir.
Bu yaklaşım sayesinde IDE desteği artar ve tip güvenliği sağlanır.
BaseService, tüm servislerin ortak kullandığı çekirdek iş mantığını barındırır.
Burada tanımlanan işlemler:
Tüm bu işlemler:
Bu sayede her model için standart CRUD işlemleri otomatik olarak hazır gelir.
Service katmanında doğrudan Request yerine DTO kullanılması:
<?php
// ===== SERVICE INTERFACE =====
namespace App\Contracts\Internal;
use App\Dtos\BaseDTO;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Model;
/**
* @template TModel of Model
* @template TDTO of BaseDTO
* @template TUpdateDTO of BaseDTO
* @template TListDTO of BaseDTO
*/
interface ServiceInterface
{
/**
* @param TListDTO $data
* @return LengthAwarePaginator<TModel>
*/
public function all(BaseDTO $data, array $with = []): LengthAwarePaginator;
/**
* @param TDTO $data
* @return TModel
*/
public function create(BaseDTO $data): Model;
/**
* @param TModel $model
* @return TModel
*/
public function show(Model $model): Model;
/**
* @param TModel $model
* @param TUpdateDTO $data
* @return TModel
*/
public function update(Model $model, BaseDTO $data): Model;
/**
* @param TModel $model
*/
public function delete(Model $model): bool;
}
// ===== BASE SERVICE =====
<?php
namespace App\Services\Internal;
use App\Contracts\Internal\ServiceInterface;
use App\Dtos\BaseDTO;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Model;
/**
* @template TModel of Model
* @template TDTO of BaseDTO
* @template TUpdateDTO of BaseDTO
* @template TListDTO of BaseDTO
*
* @implements ServiceInterface<TModel, TDTO, TUpdateDTO, TListDTO>
*/
class BaseService implements ServiceInterface
{
/**
* @var TModel
*/
protected $model;
/**
* @param TModel $model
*/
public function __construct(Model $model)
{
$this->model = $model;
}
/**
* @param TListDTO $data
* @return LengthAwarePaginator<TModel>
*/
public function all(BaseDTO $data, array $with = []): LengthAwarePaginator
{
$query = $this->model->query();
$query->with($with);
if ($data->search) {
$query->where('name', 'like', '%' . $data->search . '%');
}
return $query->paginate($data->per_page);
}
/**
* @param TDTO $data
* @return TModel
*/
public function create(BaseDTO $data): Model
{
return $this->model::create($data->toArray());
}
/**
* @param TModel $model
* @return TModel
*/
public function show(Model $model): Model
{
return $this->model->find($model->id);
}
/**
* @param TModel $model
* @param TUpdateDTO $data
* @return TModel
*/
public function update(Model $model, BaseDTO $data): Model
{
$this->model->find($model->id)->update($data->toArray());
return $this->model;
}
/**
* @param TModel $model
*/
public function delete(Model $model): bool
{
return $this->model->find($model->id)->delete();
}
}
// ===== BaseDTO =====
<?php
namespace App\Dtos;
abstract class BaseDTO
{
public int $per_page;
public ?string $search;
abstract public static function fromRequest(array $data): static;
abstract public function toArray(): array;
protected function searchStrReplace(string $search): string
{
$search = str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $search);
return $search;
}
}
// ===== MessageServiceInterface =====
<?php
namespace App\Contracts\Internal;
use App\Contracts\Internal\ServiceInterface;
/**
* @extends BaseService<\App\Models\Message, \App\Dtos\Messages\MessageDTO, \App\Dtos\Messages\MessageDTO, \App\Dtos\Messages\MessageListDTO>
*/
interface MessageServiceInterface extends ServiceInterface
{
}
// ===== MessageService =====
<?php
namespace App\Services\Internal;
use App\Contracts\Internal\MessageServiceInterface;
use App\Models\Message;
use App\Services\Internal\BaseService;
/**
* @extends BaseService<\App\Models\Message, \App\Dtos\Messages\MessageDTO, \App\Dtos\Messages\MessageDTO, \App\Dtos\Messages\MessageListDTO>
*/
class MessageService extends BaseService implements MessageServiceInterface
{
/**
* Create a new class instance.
*/
public function __construct(Message $model)
{
parent::__construct($model);
}
}