Todos los artículos

Entendiendo la Diferencia Entre Repositorio y Servicio en Laravel

Julian Beaujardin
Julian Beaujardin November 6th, 2024

En Laravel, los conceptos de "Repositorio" y "Servicio" se utilizan a menudo para organizar el código de una manera que promueva la separación de responsabilidades y una arquitectura limpia. Este artículo te guiará a través de las diferencias entre un repositorio y un servicio en Laravel, y te mostrará cómo usar cada uno de estos patrones con ejemplos de código.

Tabla de Contenidos

  1. ¿Qué es un Repositorio?
  2. ¿Qué es un Servicio?
  3. Diferencias Entre un Repositorio y un Servicio
  4. Cuándo Usar un Repositorio o un Servicio
  5. Ejemplos de Código
  6. Conclusión

¿Qué es un Repositorio?

Un repositorio es un patrón de diseño que se utiliza para separar la capa de datos (lógica de base de datos) de la capa de aplicación. En Laravel, un repositorio abstrae la interacción con la base de datos, facilitando el cambio a una fuente de datos diferente (por ejemplo, de una base de datos MySQL a MongoDB) sin modificar la lógica de la aplicación.

Los repositorios son generalmente interfaces y clases que proporcionan una capa de abstracción para consultar y almacenar datos. Se centran en operaciones CRUD (Crear, Leer, Actualizar, Eliminar) y gestionan las interacciones con la capa de modelos.

Beneficios de Usar Repositorios

  • Desacopla la lógica de la base de datos de la lógica de la aplicación.
  • Promueve la reutilización del código.
  • Proporciona un único punto de acceso a los datos, lo cual ayuda en el mantenimiento del código.

¿Qué es un Servicio?

Un servicio es una clase o módulo en Laravel que contiene la lógica de negocio de una aplicación. Organiza operaciones complejas que involucran múltiples pasos o condiciones, que pueden requerir la interacción con múltiples modelos o APIs externas.

Los servicios son responsables de coordinar acciones, procesar datos e implementar reglas de negocio. A menudo interactúan con repositorios para realizar operaciones de datos y pueden también llamar a otros servicios.

Beneficios de Usar Servicios

  • Separa la lógica de negocio del controlador.
  • Facilita la prueba de la lógica de negocio.
  • Permite un código modular y reutilizable.

Diferencias Entre un Repositorio y un Servicio

Aspecto Repositorio Servicio
Propósito Acceso a datos e interacción con base de datos o modelos. Lógica de negocio y funcionalidad de la aplicación.
Enfoque Operaciones CRUD. Procesos de negocio y flujos de trabajo de la aplicación.
Dependencia A menudo interactúa con un modelo. Puede depender de repositorios, otros servicios o APIs.
Responsabilidad Abstrae el acceso a datos. Gestiona reglas de negocio y coordina la lógica.
Reusabilidad Reutilizable en diferentes partes de la aplicación. Vinculado a operaciones de negocio específicas.

Cuándo Usar un Repositorio o un Servicio

  • Usa un Repositorio si:

    • Necesitas interactuar con la base de datos directamente.
    • Quieres abstraer las operaciones de base de datos y hacerlas reutilizables.
    • Podrías cambiar la fuente de datos subyacente en el futuro.
  • Usa un Servicio si:

    • Tienes lógica de negocio compleja que involucra múltiples operaciones.
    • Quieres mantener limpias las acciones de tu controlador.
    • Necesitas coordinar diferentes modelos o servicios externos.

Ejemplos de Código

Para ilustrar cómo los repositorios y servicios pueden trabajar juntos, veamos una aplicación de ejemplo que administra registros de Post con las siguientes operaciones:

  • Repositorio: Administra las operaciones CRUD para publicaciones.
  • Servicio: Contiene la lógica de negocio para crear una publicación con validaciones específicas y acciones adicionales.

Paso 1: Crear una Interfaz de Repositorio

Primero, define una interfaz para el repositorio en App\Repositories\PostRepositoryInterface.php.

<?php

namespace App\Repositories;

use App\Models\Post;

interface PostRepositoryInterface
{
    public function getAllPosts();
    public function getPostById($id);
    public function createPost(array $data);
    public function updatePost($id, array $data);
    public function deletePost($id);
}

Paso 2: Implementar el Repositorio

Ahora, crea una clase de repositorio que implemente esta interfaz en App\Repositories\PostRepository.php.

<?php

namespace App\Repositories;

use App\Models\Post;

class PostRepository implements PostRepositoryInterface
{
    public function getAllPosts()
    {
        return Post::all();
    }

    public function getPostById($id)
    {
        return Post::findOrFail($id);
    }

    public function createPost(array $data)
    {
        return Post::create($data);
    }

    public function updatePost($id, array $data)
    {
        $post = Post::findOrFail($id);
        $post->update($data);
        return $post;
    }

    public function deletePost($id)
    {
        $post = Post::findOrFail($id);
        return $post->delete();
    }
}

Paso 3: Crear un Servicio

Ahora, crea un servicio que dependa del repositorio para gestionar la lógica de negocio en App\Services\PostService.php.

<?php

namespace App\Services;

use App\Repositories\PostRepositoryInterface;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;

class PostService
{
    protected $postRepository;

    public function __construct(PostRepositoryInterface $postRepository)
    {
        $this->postRepository = $postRepository;
    }

    public function createPost(array $data)
    {
        $validator = Validator::make($data, [
            'title' => 'required|string|max:255',
            'content' => 'required|string',
        ]);

        if ($validator->fails()) {
            throw new ValidationException($validator);
        }

        return $this->postRepository->createPost($data);
    }

    public function getAllPosts()
    {
        return $this->postRepository->getAllPosts();
    }

    // Otros métodos de lógica de negocio según sea necesario...
}

Paso 4: Enlazar la Interfaz de Repositorio a la Implementación del Repositorio

En App\Providers\AppServiceProvider.php, registra el enlace del repositorio en el método register para que Laravel sepa qué implementación usar.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Repositories\PostRepositoryInterface;
use App\Repositories\PostRepository;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(PostRepositoryInterface::class, PostRepository::class);
    }
}

Paso 5: Usar el Servicio en un Controlador

Ahora, inyecta el servicio en un controlador y úsalo para realizar acciones en App\Http\Controllers\PostController.php.

<?php

namespace App\Http\Controllers;

use App\Services\PostService;
use Illuminate\Http\Request;

class PostController extends Controller
{
    protected $postService;

    public function __construct(PostService $postService)
    {
        $this->postService = $postService;
    }

    public function index()
    {
        $posts = $this->postService->getAllPosts();
        return response()->json($posts);
    }

    public function store(Request $request)
    {
        $post = $this->postService->createPost($request->all());
        return response()->json($post, 201);
    }
}

Conclusión

El patrón de Repositorio abstrae el acceso a datos, mientras que el patrón de Servicio organiza la lógica de negocio. Al utilizar estos patrones en Laravel, puedes construir aplicaciones modulares, mantenibles y comprobables. Los repositorios se enfocan en el acceso a los datos, mientras que los servicios manejan flujos de trabajo complejos, lo que permite una separación clara de responsabilidades dentro de tu aplicación.