O Laravel Repository é um padrão de arquitetura que melhora a organização e separação de responsabilidades dentro de um projeto Laravel. Ele atua como uma camada intermediária entre os Models e os Controllers, encapsulando a lógica de acesso a dados, tornando o código mais modular, reutilizável e testável.
O que é um Repository?
O padrão Repository é uma abstração que centraliza todas as operações de banco de dados em uma classe específica, removendo a necessidade de consultas diretas dentro dos Controllers ou Services. Isso facilita a manutenção e a evolução do sistema sem impactar diretamente outras camadas da aplicação.
Benefícios do uso de Repository no Laravel
- Separa responsabilidades: Mantém a lógica de acesso a dados separada da lógica de negócio, seguindo o príncipio da responsabilidade única (SRP).
- Facilita a reutilização: Um repositório bem projetado pode ser utilizado em múltiplos pontos da aplicação sem duplicar código.
- Facilidade na troca de banco de dados: Se for necessário mudar o banco de dados (por exemplo, de MySQL para MongoDB), basta modificar a implementação do repositório sem alterar outras camadas da aplicação.
- Melhoria na testabilidade: Como os repositórios encapsulam a lógica de acesso a dados, fica mais fácil criar mocks e realizar testes unitários sem interagir diretamente com o banco de dados.
Como Implementar um Repository no Laravel
Vamos construir um exemplo prático para gerenciar usuários dentro de um sistema Laravel utilizando o padrão Repository.
Criando a Interface do Repository
Criar a interface do repository é um passo essencial para garantir que todas as implementações sigam um contrato bem definido, facilitando a manutenção e permitindo a substituição da implementação sem afetar outras partes do código.
Aqui está um exemplo de interface para um repositório de usuários:
namespace App\Repositories;
interface UserRepositoryInterface
{
/**
* Retorna todos os usuários.
*
* @return mixed
*/
public function getAll();
/**
* Encontra um usuário pelo ID.
*
* @param int $id
* @return mixed
*/
public function findById($id);
/**
* Cria um novo usuário.
*
* @param array $data
* @return mixed
*/
public function create(array $data);
/**
* Atualiza um usuário existente.
*
* @param int $id
* @param array $data
* @return mixed
*/
public function update($id, array $data);
/**
* Remove um usuário pelo ID.
*
* @param int $id
* @return bool
*/
public function delete($id);
}
Explicação:
1. Métodos bem definidos: A interface contém métodos essenciais para a manipulação de usuários.
2. Facilidade de manutenção: Qualquer classe que implemente essa interface precisará seguir essa estrutura.
3. Desacoplamento: O código que utilizar essa interface não precisará saber qual a implementação real do repositório, permitindo fácil troca de implementações.
Registrando o Repository no Service Provider
Agora que criamos a interface e a implementação do repositório, precisamos registrar essa classe no Service Provider do Laravel. Isso garante que o Laravel possa injetar a dependência correta sempre que precisarmos do repositório.
Passo 1: Registrar no AppServiceProvider
Abra o arquivo app/Providers/AppServiceProvider.php e adicione o seguinte código dentro do método register():
use App\Repositories\UserRepositoryInterface;
use App\Repositories\Eloquent\UserRepository;
public function register()
{
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
}
Explicação:
• bind(): Define a ligação entre a interface UserRepositoryInterface e a implementação concreta UserRepository. Assim, sempre que o Laravel encontrar a UserRepositoryInterface, ele saberá que deve instanciar UserRepository.
• Desacoplamento: Isso permite que possamos alterar a implementação do repositório sem modificar os controladores ou serviços que o utilizam.
Passo 2: Limpar Cache de Configuração (se necessário)
Caso o Laravel não reconheça as alterações imediatamente, execute os seguintes comandos para limpar os caches da aplicação:
php artisan config:clear
php artisan cache:clear
php artisan optimize:clear
Agora o Laravel reconhecerá e injetará automaticamente o UserRepository sempre que a interface UserRepositoryInterface for solicitada.
O próximo passo é utilizar o repositório dentro de um Controller. Vamos para essa parte? 🚀
Utilizando o Repository no Controller
Agora que registramos o repositório no Service Provider, podemos utilizá-lo dentro de um Controller para manter a lógica de acesso a dados organizada e desacoplada.
Passo 1: Injetando o Repository no Controller
Abra ou crie o UserController.php dentro de app/Http/Controllers/ e adicione o seguinte código:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Repositories\UserRepositoryInterface;
class UserController extends Controller
{
protected $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* Lista todos os usuários.
*/
public function index()
{
return response()->json($this->userRepository->getAll());
}
/**
* Retorna um usuário específico pelo ID.
*/
public function show($id)
{
$user = $this->userRepository->findById($id);
if (!$user) {
return response()->json(['message' => 'Usuário não encontrado'], 404);
}
return response()->json($user);
}
/**
* Cria um novo usuário.
*/
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:6'
]);
$data['password'] = bcrypt($data['password']); // Hash da senha
$user = $this->userRepository->create($data);
return response()->json($user, 201);
}
/**
* Atualiza um usuário existente.
*/
public function update(Request $request, $id)
{
$data = $request->validate([
'name' => 'sometimes|string|max:255',
'email' => 'sometimes|email|unique:users,email,' . $id,
'password' => 'sometimes|min:6'
]);
if (isset($data['password'])) {
$data['password'] = bcrypt($data['password']);
}
$user = $this->userRepository->update($id, $data);
return response()->json($user);
}
/**
* Remove um usuário pelo ID.
*/
public function destroy($id)
{
$deleted = $this->userRepository->delete($id);
if (!$deleted) {
return response()->json(['message' => 'Usuário não encontrado'], 404);
}
return response()->json(['message' => 'Usuário removido com sucesso']);
}
}
Explicação:
1. Injeção de Dependência: O UserRepositoryInterface é injetado diretamente no UserController, garantindo que ele use a implementação correta.
2. Separação de Responsabilidades: O Controller apenas delega as operações ao repositório, sem lidar diretamente com o banco de dados.
3. Melhoria na Manutenção: Se o método de persistência mudar (por exemplo, de Eloquent para outro ORM), basta alterar o repositório, sem modificar o Controller.
4. Tratamento de Erros: Validação de entrada e resposta JSON padronizada para erros e sucesso.
Passo 2: Definir as Rotas
No arquivo routes/api.php, adicione as rotas para o Controller:
use App\Http\Controllers\UserController;
Route::apiResource('users', UserController::class);
Isso cria automaticamente as seguintes rotas RESTful:
• GET /users → Lista todos os usuários
• GET /users/{id} → Exibe um usuário específico
• POST /users → Cria um novo usuário
• PUT /users/{id} → Atualiza um usuário existente
• DELETE /users/{id} → Remove um usuário
Passo 3: Testar a API
Agora você pode testar as rotas usando Postman, Insomnia ou o comando curl no terminal.
Exemplo de requisição para criar um usuário:
curl -X POST http://localhost:8000/api/users \
-H "Content-Type: application/json" \
-d '{
"name": "João Silva",
"email": "joao@email.com",
"password": "123456"
}'
Conclusão
Agora temos um Controller totalmente desacoplado do modelo e que segue boas práticas de arquitetura. O repositório centraliza as operações com o banco de dados, tornando a aplicação mais modular e fácil de manter.
Conclusão
O padrão Repository no Laravel é uma prática recomendada para organizar e modularizar a lógica de acesso a dados, reduzindo a complexidade dos Controllers e Services. Ele permite maior manutenção, escalabilidade e flexibilidade, facilitando mudanças futuras, testes unitários e reuso de código.
Se você busca um código mais estruturado e profissional em seus projetos Laravel, adotar o padrão Repository é um excelente caminho!