Laravel Repository: O que é e como implementar corretamente
Laravel Repository: O que é e como implementar corretamente

Laravel Repository: O que é e como implementar corretamente

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!