Traits

Are an alternative approach to inheritance that solves some limitations of single class inheritance, which PHP uses. Since all Eloquent models extends Model it can not extend another class. This is commonly used to share similar logic across objects. Let's imagine a couple of models have a Company relationship.

trait HasCompany {
   public function company() {
       return $this->belongsTo(Company::class);
   }
}

Now the user can easily share code from the trait, by the keyword using. This is an example and most often a more complex use case would be needed for it to make sense.

class User extends Model {
   use HasCompany;
}

Repositories

Repositories is a design pattern to abstract data layers from the application. Your logic should not care about how you store data, so if you wanted to change from Mysql to Mongodb, you would only swap out the repository and not have to change business logic.

Very opinionated here, but this is not a fitting design pattern for Laravel. Laravel has Eloquent and the database layer is therefor already abstracted. Repositories is sometimes used for Laravel applications, but rather an outlier, than a common sight. One of the main reasons for repositories, is to be data implementation agnostic, which already exists and you can swap between SQL servers flawlessly. Also Eloquents features like ::find(), scopes etc. feels like a replacement for Repositories and is quirky to use at the same time.

If you use Doctrine as the ORM, which you can in Laravel, it is the core of their architecture and repositories should be used.

It sometimes occurs that the repository pattern is used to encapsulate business logic, with a similar approach as used with services or action pattern.

Services

Is commonly used for a place to store business logic or the building blocks of your actions in your application. In traditional MVC design, Controllers should only handle input. Normally you would put your logic in Models, but they get "fat" very quickly, when this happens services is a common place to put business logic. Sometimes action or command design pattern are used, which is similar but still different.

One of the core things it solves, is to make your business logic reusable. Imaging filtering all users by an active flag, when you retrieve it in its controller.

public function all() {
    return User::where('active', true)->get();
}

Now you have your business logic, that enforces that you only work on active users, later you want to notify all active users with an email, by notifications using a command.

class NotifyUsers extends Command {
    public function handle() {
        foreach (User::where('active', true)->get() as $user) {
            $user->notify();
        }
    }
}

Now you manually have to keep business logic up to date. Next time you add a second condition or change the logic, you have to change the code in two places. In a big application where this code block is used often, it can make it quite hard to maintain the conditions without forgetting one of the places. If you make a service with this logic, you can easily utilize the same business logic across the application. While one have one place to change the code, if this logic had to change.

class UserService {
    public function all() {
        return User::where('active', true)->get();
    }
}

Everywhere you want to use this business logic getting active users, you can use the service. Therefor only having one place to maintain the logic. A call can be as simply as resolve(UserService::class)->all(). Example of the updated logic with services would be.

// controller
public function all(UserService $userService) {
    return $userService->all();
}

// command
class NotifyUsers extends Command {
    public function handle(UserService $userService) {
        $userService->all()->each->notify();
    }
}

Conclusion

The world is not black and white, you have to figure out your own approach. My advice is, do not spend time on Repositories, Laravel has a lot of features to handle data related operations scopes, getters setters etc. that conflicts with the Repository design pattern. See if a service like design approach suits you and you can utilize em. Traits is not as much an architectural design pattern, as it is a Class inheritance alternative, simply to share logic between classes.

Answer from mrhn on Stack Overflow
🌐
GitHub
github.com › adobrovolsky97 › laravel-repository-service-pattern
GitHub - adobrovolsky97/laravel-repository-service-pattern: Laravel Repository-Service Pattern
The purpose of using the repository service pattern in Laravel is to decouple the application's business logic from the specific implementation details of data storage. By doing so, it promotes code reusability, maintainability, and testability.
Starred by 28 users
Forked by 6 users
Languages   PHP 100.0% | PHP 100.0%
🌐
DEV Community
dev.to › blamsa0mine › structuring-a-laravel-project-with-the-repository-pattern-and-services-11pm
Structuring a Laravel Project with the Repository Pattern and Services 🚀 - DEV Community
November 21, 2024 - The Repository Pattern provides an abstraction layer between the database and the business logic of your application. Instead of directly interacting with Eloquent models in controllers or services, you use repositories to handle data access.
Discussions

php - When to use Repository vs Service vs Trait in Laravel? - Stack Overflow
If you use Doctrine as the ORM, which you can in Laravel, it is the core of their architecture and repositories should be used. It sometimes occurs that the repository pattern is used to encapsulate business logic, with a similar approach as used with services or action pattern. More on stackoverflow.com
🌐 stackoverflow.com
php - Laravel: Service/Repository Pattern and duplicating code - Stack Overflow
In my project I have decided to use the Service Pattern (Possibly with the Repository Pattern) to deal with the business logic in my application. I have for example a Client model which represents a More on stackoverflow.com
🌐 stackoverflow.com
Yet another repository pattern post... Developers that don't use repository pattern and think it's redundant and over-engineering, where do you leave the complex queries of your project at?
I tend to create a service class for the things with complex queries or functionality (reports for example, or a model with big or complex methods) but then just use the regular controller-model setup for everything else. If I have a lot of reports I'll often create a class per report. It doesn't feel perfect to me either, but one thing Laravel has taught me, is to separate things out as much as possible so you don't have gigantic files doing everything. More on reddit.com
🌐 r/laravel
37
17
August 8, 2024
Is using the repository pattern best practise?
I'm not a big fan of the repository pattern in Laravel apps, even in a big ones – when working in a team. It's a hard concept to do right. If done wrong it does more harm than good; it's hard to maintain, hard to refactor and hard to change behaviour. Laravel has a great way to write custom query builders to extract business logic. Great for querying models. For writing models I would suggest using Action Closes. One example of them can be found in Jetstream's sourcecode . Actions are great to test in isolation and link to user stories. More on reddit.com
🌐 r/laravel
40
22
January 29, 2023
🌐
Reddit
reddit.com › r/laravel › mastering the service-repository pattern in laravel
r/laravel on Reddit: Mastering the Service-Repository Pattern in Laravel
June 29, 2024 - At work, we had a consultant migrate one of our legacy PHP apps to Laravel, and they decided to use QueryBuilder and loosely-typed arrays, rather than Eloquent and strongly-typed objects. The good thing is they used the repository pattern, so we could still switch to Eloquent without breaking anything but the way the service layer consumes the repository layer.
🌐
Medium
medium.com › @binumathew1988 › mastering-the-service-repository-pattern-in-laravel-751da2bd3c86
Mastering the Service-Repository Pattern in Laravel | by Binu Mathew | Medium
September 2, 2024 - The Service-Repository pattern isn’t just about following best practices — it’s about setting your Laravel application up for long-term success.
🌐
DEV Community
dev.to › safventure11000 › implement-crud-with-laravel-service-repository-pattern-1dkl
Implement CRUD with Laravel Service-Repository Pattern - DEV Community
June 27, 2025 - I agree with you. I think laravel repository pattern implementation is easier because you only need to add the repository. But if you're thinking on the readability and flexibility of your system, I highly recommend the service-repository pattern.
Top answer
1 of 1
102

Traits

Are an alternative approach to inheritance that solves some limitations of single class inheritance, which PHP uses. Since all Eloquent models extends Model it can not extend another class. This is commonly used to share similar logic across objects. Let's imagine a couple of models have a Company relationship.

trait HasCompany {
   public function company() {
       return $this->belongsTo(Company::class);
   }
}

Now the user can easily share code from the trait, by the keyword using. This is an example and most often a more complex use case would be needed for it to make sense.

class User extends Model {
   use HasCompany;
}

Repositories

Repositories is a design pattern to abstract data layers from the application. Your logic should not care about how you store data, so if you wanted to change from Mysql to Mongodb, you would only swap out the repository and not have to change business logic.

Very opinionated here, but this is not a fitting design pattern for Laravel. Laravel has Eloquent and the database layer is therefor already abstracted. Repositories is sometimes used for Laravel applications, but rather an outlier, than a common sight. One of the main reasons for repositories, is to be data implementation agnostic, which already exists and you can swap between SQL servers flawlessly. Also Eloquents features like ::find(), scopes etc. feels like a replacement for Repositories and is quirky to use at the same time.

If you use Doctrine as the ORM, which you can in Laravel, it is the core of their architecture and repositories should be used.

It sometimes occurs that the repository pattern is used to encapsulate business logic, with a similar approach as used with services or action pattern.

Services

Is commonly used for a place to store business logic or the building blocks of your actions in your application. In traditional MVC design, Controllers should only handle input. Normally you would put your logic in Models, but they get "fat" very quickly, when this happens services is a common place to put business logic. Sometimes action or command design pattern are used, which is similar but still different.

One of the core things it solves, is to make your business logic reusable. Imaging filtering all users by an active flag, when you retrieve it in its controller.

public function all() {
    return User::where('active', true)->get();
}

Now you have your business logic, that enforces that you only work on active users, later you want to notify all active users with an email, by notifications using a command.

class NotifyUsers extends Command {
    public function handle() {
        foreach (User::where('active', true)->get() as $user) {
            $user->notify();
        }
    }
}

Now you manually have to keep business logic up to date. Next time you add a second condition or change the logic, you have to change the code in two places. In a big application where this code block is used often, it can make it quite hard to maintain the conditions without forgetting one of the places. If you make a service with this logic, you can easily utilize the same business logic across the application. While one have one place to change the code, if this logic had to change.

class UserService {
    public function all() {
        return User::where('active', true)->get();
    }
}

Everywhere you want to use this business logic getting active users, you can use the service. Therefor only having one place to maintain the logic. A call can be as simply as resolve(UserService::class)->all(). Example of the updated logic with services would be.

// controller
public function all(UserService $userService) {
    return $userService->all();
}

// command
class NotifyUsers extends Command {
    public function handle(UserService $userService) {
        $userService->all()->each->notify();
    }
}

Conclusion

The world is not black and white, you have to figure out your own approach. My advice is, do not spend time on Repositories, Laravel has a lot of features to handle data related operations scopes, getters setters etc. that conflicts with the Repository design pattern. See if a service like design approach suits you and you can utilize em. Traits is not as much an architectural design pattern, as it is a Class inheritance alternative, simply to share logic between classes.

🌐
GitHub
github.com › yaza-putu › laravel-repository-with-service
GitHub - yaza-putu/laravel-repository-with-service: With repository and service you can separate business logic and query logic, slim controller and DRY. Simple generate repository and service with artisan command, automatically bind interface to class implement with IOC container and dependecy injection (SOLID) · GitHub
php artisan make:repository User // or php artisan make:repository UserRepository // or create together with a service php artisan make:repository User --service // or php artisan make:repository UserRepository --service // or create a service separately php artisan make:service User // or php artisan make:service UserService // or php artisan make:service UserService --repository // create service with blank template php artisan make:service UserService --blank
Starred by 143 users
Forked by 34 users
Languages   PHP 92.2% | Shell 7.8%
Find elsewhere
🌐
GitHub
github.com › rudrakshpathak › laravel-service-repository-pattern
GitHub - rudrakshpathak/laravel-service-repository-pattern: Decouple your code in service and repository layers to have more robust project structure. Trim down the controllers and focus the main business logic at service layer. In this architecture repository layer communicates with data source and returns a define response.
Decouple your code in service and repository layers to have more robust project structure. Trim down the controllers and focus the main business logic at service layer. In this architecture repository layer communicates with data source and ...
Starred by 41 users
Forked by 9 users
Languages   PHP 96.0% | HTML 4.0% | PHP 96.0% | HTML 4.0%
🌐
YouTube
youtube.com › watch
Laravel Services and Repositories: 3 Example Projects - YouTube
Service classes in Laravel is one of the most misunderstood concepts because developers use them in a very different way. Let's take a look at three examples...
Published   March 31, 2021
🌐
Medium
joe-wadsworth.medium.com › laravel-repository-service-pattern-acf50f95726
Repository & Service Pattern in Laravel | by Joe Wadsworth | Medium
January 26, 2021 - By keeping to this pattern, an example controller would be below. <?php declare(strict_types=1); namespace App\Http\Controllers\User; use App\Http\Requests\Users\CreateUserRequest; use App\Modules\Users\Repositories\UserRepository; use App\Modules\Users\Services\CreateUserService; use App\Http\Responses\Users\UserResponse; use App\Http\Responses\Response; class UserController { /** * @var UserRepository */ private UserRepository $repository; /** * @param UserRepository $repository */ public function __construct(UserRepository $repository) { $this->repository = $repository; } /** * @return Resp
🌐
ASPER BROTHERS
asperbrothers.com › home › product development › laravel repository pattern – php design pattern
Laravel Repository Pattern – PHP Design Pattern | ASPER BROTHERS
September 10, 2022 - A repository is a separation between a domain and a persistent layer. The repository provides a collection interface to access data stored in a database, file system, or external service.
🌐
Medium
medium.com › @soulaimaneyh › laravel-repository-pattern-da4e1e3efc01
PHP Laravel Repository Pattern. The Repository Pattern is a software… | by Soulaimaneyh | Medium
February 28, 2025 - The Service Class: This class uses the Repository Class to perform business logic operations. It acts as an intermediary between the Controller and the Repository, providing a layer of abstraction between the presentation layer and the data storage layer. To implement the Repository Pattern in Laravel...
Top answer
1 of 2
1

I think if you break this down into smaller steps you can achieve DRY architecture. The steps I'm seeing are:

  • Create Client
  • Create User
  • Associate (via pivot table, junction table etc)
  • Email

To avoid having the dreaded duplicate code you'd create a method around each of these in your service class or classes. You'd then create an action encapsulating all of the steps involved based around these methods.

Don't be scared to implement things outside of your service class - this doesn't mean it is outside of your service layer.

I see registering client interest as an action. You follow synchronous steps to achieve your desired action. So based on methods like creating a user, client etc we can build an action to register client interest, like so:

<?php

class ClientService {

public function addAction(IAction $action)
{
  return $action->process();
}

public function createUser() {} // business logic for creating a user.

public function createClient() {} // business logic for creating a client.

public function createAssociation() {} // business logic for creating an association.

} 

interface IAction {

  public function process();

}

class RegisterClientInterestAction implements IAction {

  protected $client; 

  public function __construct(ClientService $client)
  {
    $this->client = $client; 
  }

  public function process()
  {
    $this->createUser()->createClient()->createAssociation();
  }

  private function createUser() {} // interact with your client service to call the method $client->createUser()

  private function createClient() {} // interact with your client service to call the method $client->createClient()

  private function createAssociation() {} // interact with your client service to call the method $client->createAssociation()

}

//USAGE

$service  = new ClientService; 
$results  = $service->addAction(new RegisterClientInterestAction($service));

?> 

By doing it this way you are able to utilise the createUser etc methods in a new action but without duplicating the code. By having the addAction on the service class you are still executing the business logic inside of your service layer.


If two or more services are required, I'd take a slightly different approach by moving where I would execute the action.

In terms of handling more than one service you can use DI within the constructor of your action.

Like this:

<?php

class Service {

  public function addAction(IAction $action)
  {
    return $action->process();
  }

  // Other stuff for a base service...

}

class UserService extends Service {

  public function createUser() {} // business logic for creating a user.

}

class ClientService extends Service {

public function createClient() {} // business logic for creating a client.

public function createAssociation() {} // business logic for creating an association.

} 

interface IAction {

  public function process();

}

class RegisterClientInterestAction implements IAction {

  protected $client; 

  protected $service; 

  public function __construct(ClientService $client, UserService $user)
  {
    $this->user   = $user; 
    $this->client = $client; 
  }

  public function process()
  {
    $this->createUser()->createClient()->createAssociation();
  }

  private function createUser() {} // interact with your user service to call the method $client->createUser()

  private function createClient() {} // interact with your client service to call the method $client->createClient()

  private function createAssociation() {} // interact with your client service to call the method $client->createAssociation()

}

//USAGE

$service  = new Service; 
$results  = $service->addAction(new RegisterClientInterestAction(new ClientService, new UserService));

?>
2 of 2
1

What feels best for me is your proposed solution of #2.

What I like to do is build out the two service classes and see what the duplication there is, then refactor/extract any duplication to another class. This way all classes are very testable and you have the least chance of breaking any SOLID principles.

🌐
Medium
medium.com › @devajayantha › laravel-service-repository-pattern-my-experience-and-key-benefits-afa985cd8b18
Laravel Service Repository Pattern: My Experience and Key Benefits | by Deva Jayantha | Medium
February 21, 2025 - This article explain a simple implementation of the Repository-Service Pattern in Laravel to keep the code organized and scalable. By separating logic into services and handling the database through repositories, this pattern enhances cleanliness, flexibility, and readability of the code.
🌐
Twilio
twilio.com › en-us › blog › repository-pattern-in-laravel-application
How to Use the Repository Pattern in a Laravel Application | Twilio
January 26, 2024 - The last thing we need to do is bind OrderRepository to OrderRepositoryInterface in Laravel's Service Container; we do this via a Service Provider. Create one using the following command. ... Open app/Providers/RepositoryServiceProvider.php and update the register function to match the following.
🌐
DevDojo
devdojo.com › amp › tosellimattia › the-repository-service-pattern-in-your-laravel-application
The Repository Service Pattern in your Laravel application
December 6, 2022 - <?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Repository\UserRepositoryInterface; use App\Repository\UserRepository; /** * Class RepositoryServiceProvider * @package App\Providers */ class RepositoryServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->bind(UserRepositoryInterface::class, UserRepository::class); } } Now, in config/app.php, register the Service in the providers: 'providers' => [ /* * Laravel Framework Service Providers...
🌐
LinkedIn
linkedin.com › pulse › working-laravel-repository-pattern-kais-chrif-nacvf
Working with Laravel Repository Pattern
March 17, 2024 - The Service Class: This class uses the Repository Class to perform business logic operations. It acts as an intermediary between the Controller and the Repository, providing a layer of abstraction between the presentation layer and the data storage layer. To implement the Repository Pattern in Laravel...
🌐
GitHub
github.com › manowartop97 › repository-service-laravel-pattern
GitHub - manowartop97/repository-service-laravel-pattern: Package which provides a structure for Repository-Service Pattern for Laravel
Create a repository PostRepository extends Manowartop\BaseRepositoryAndService\Repositories\BaseRepository · Define property protected $modelClass = Post::class; in PostRepository · Create a service PostService extends Manowartop\BaseRepositoryAndService\Services\BaseCrudService
Starred by 8 users
Forked by 4 users
Languages   PHP 100.0% | PHP 100.0%