I’m refactoring my Laravel application to follow a clean architecture approach with clear separation of concerns:
Controller → Service → Repository
The Controller handles the HTTP layer,the Service contains business logic, and the Repository is responsible for data persistence (Eloquent, API, or cache).
Problem
I’m trying to design my UserRepositoryInterface to be fully abstract and independent of Laravel’s Eloquent implementation, ensuring that higher layers (like services or controllers) depend only on a data-access contract rather than a specific ORM or framework.
Here’s the current design:
interface UserRepositoryInterface
{
public function findClientById(int $id): ?User;
public function update(User $user, array $data): User;
}
The implementation looks like this:
class EloquentUserRepository implements UserRepositoryInterface
{
public function findClientById(int $id): ?User
{
return User::role('client')->find($id);
}
public function update(User $user, array $data): User
{
$user->fill($data);
$user->save();
return $user;
}
}
However, this ties the interface to Eloquent (User $user). If I switch to an API-based repository, this will break, since there’s no Eloquent model anymore.
Possible alternative
I was thinking of changing it to use a Data Transfer Object (DTO):
interface UserRepositoryInterface
{
public function findClientById(int $id): ?UserDTO;
public function update(int $id, UserDTO $dto): mixed;
}
That way, both Eloquent-based and API-based repositories can share the same interface while staying decoupled from the ORM.
My question
From a senior-level laravel architecture / clean architecture perspective:
Is it better for repositories to work directly with Eloquent models (User $user) since they’re data-specific anyway?
Or should I pass DTOs (or domain entities) to keep the repository layer framework-agnostic?
If DTOs are better, should the conversion (from Eloquent → DTO or vice versa) happen in the repository or service layer?