Skip to content

Instantly share code, notes, and snippets.

@xmsi
Created January 3, 2025 10:43
Show Gist options
  • Save xmsi/2610c079f0507107d612615598cb03fa to your computer and use it in GitHub Desktop.
Save xmsi/2610c079f0507107d612615598cb03fa to your computer and use it in GitHub Desktop.
Repository and Strategy Patterns

Author: GPT-4o

In Laravel, Service Pattern and Repository Pattern are two common design patterns used to structure the business logic and data layer. Each pattern has its purpose and responsibilities, and they can even complement each other.

1. Service Pattern

The Service Pattern is used to encapsulate business logic, making it reusable and independent of the controller or other layers. This is where you place the "what needs to be done" logic, such as calculations, complex workflows, or coordination of multiple repositories or APIs.

Key Characteristics:

  • Focuses on business logic.
  • Keeps controllers thin by moving complex logic out.
  • Typically interacts with one or more repositories or models.
  • Promotes separation of concerns by isolating the business rules.

Example:

// Services/UserService.php
namespace App\Services;

use App\Repositories\UserRepository;

class UserService
{
    protected $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function registerUser($data)
    {
        // Business logic
        $data['password'] = bcrypt($data['password']);
        return $this->userRepository->create($data);
    }
}

Usage in Controller:

use App\Services\UserService;

class UserController extends Controller
{
    protected $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function register(Request $request)
    {
        $user = $this->userService->registerUser($request->all());
        return response()->json($user);
    }
}

2. Repository Pattern

The Repository Pattern is used to abstract the data access layer, making the application independent of the underlying database or ORM (like Eloquent). It provides a consistent API for data operations, such as find, create, or delete.

Key Characteristics:

  • Focuses on data access.
  • Acts as a mediator between the database (or ORM) and the application.
  • Simplifies unit testing by mocking the repository.
  • Promotes separation of concerns by isolating database logic.

Example:

// Repositories/UserRepository.php
namespace App\Repositories;

use App\Models\User;

class UserRepository
{
    protected $model;

    public function __construct(User $model)
    {
        $this->model = $model;
    }

    public function find($id)
    {
        return $this->model->find($id);
    }

    public function create($data)
    {
        return $this->model->create($data);
    }

    public function update($id, $data)
    {
        $user = $this->find($id);
        return $user->update($data);
    }
}

Usage in Service or Controller:

use App\Repositories\UserRepository;

class UserService
{
    protected $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function getUserById($id)
    {
        return $this->userRepository->find($id);
    }
}

Key Differences:

Feature Service Pattern Repository Pattern
Purpose Encapsulates business logic and workflows. Encapsulates database and data access logic.
Focus "What needs to be done" (business rules). "How to fetch/store data" (data operations).
Dependency Often depends on repositories or models. Depends on models or raw queries.
Scope Handles multiple repositories or external services. Handles a single model or data source.
Testability Easier to test business logic independently. Simplifies testing of data access logic.
Example Usage User registration, payment processing. Fetching users, paginated queries.

When to Use:

  1. Service Pattern:

    • When you have complex business rules or workflows.
    • To decouple business logic from controllers.
    • For logic that involves multiple repositories or external services.
  2. Repository Pattern:

    • When you want to abstract data access from models.
    • For easier swapping of database/ORM or mocking in tests.
    • To maintain cleaner, reusable, and centralized data access logic.

Can They Work Together?

Yes! They often complement each other.

  • The Service Layer focuses on what needs to be done (business logic).
  • The Repository Layer focuses on how to interact with the database.

For example:

  • A UserService calls UserRepository to handle database operations.
  • The controller interacts only with UserService, keeping it thin and clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment