Seems like a smart decision. Eloquent is already an extra layer which can handle a lot of things in an easy way. Adding another layer in between should only be done if it really adds something. "so I can easily switch database system" sounds good but the question is how big the chance is that you do that in practice.
Reasons I abandoned repository pattern in Laravel
I used to do database stuff inside repository implementations. This is how I was treating problems:
Scenario : Creating a user :
- Creating validation services like
UserStoreValidator. - Calling the validator inside the controller and passing the user's input to the validator.
- Creating a service class called
UserCreatorand adding a create method to that. - Creating a
UserRepositoryInterfaceand aUserRepositoryclass, adding acreateUserFromArraymethod to it, or sometimes just calling the thecreateRaw(array $data)method from myAbstractEloquentRepositoryimplementation. The method is called from my user creator service. - And doing some other jobs like sending
welcome_emailby Events which are fired inside my service classes.
There are examples of how I was doing stuff inside repositories:
In this strategy I was able to decouple all of the business from each other. But someday I started to move one of my implementations into MongoDb with Doctrine's ODM. What I was expecting was really different from what I experienced. It is not just adding another implementation of my repository interface. In my opinion ** Laravel's power is in Eloquent **. I was just duplicating a lot of logic that eloquent already had into my repositories like SoftDeletes and Eventing system.
By using services I have put lots of repetitive logic inside them and my controllers are still thin. Removing repositories causes models to be fat, but it's ok to have models with +2000 lines of code instead of repositories with +2000 lines of code.
Using repositories with Eloquent does not allow you to swap between different storages or drivers easily. there were lots of eloquent features that I was using inside my eloquent implementation which I rewrote them in my Doctrine implementation like deleting model's related files in model's deleting event, or some recursive calls to update nested parents of a record in my model's updating call, I came to a solution to implement the same features in my abstract repository, but it was a buggy decision, and eloquent is not the right tool if you don't use its features.
My relations were only meaningful in SQL databases, I had a really different approach in my MongoDb implementation.
Generally I don't write unit tests a lot, but moving the query logic into models, makes it easy to mock them inside services.
I used to wrap some cache decorators around my repository calls, which is the main great feature I lost. I still use them arround my models but it is not as clean as it was.
Laravel is meant to be used by eloquent and its great features, using repositories decreases the power of eloquent and also my development speed. Using laravel with another DataMapper ORM like Doctrine causes to loose eloquent features. Repositories are not the right place for putting business logic, they are just data delegators , there is no difference in maintenance cost of a model with +2000 lines of code or of a repository class with +2000 lines of code, moving business logic into service classes allows controllers to be still thin.
I ended up with removing repository pattern from my design and moving the logic into models or service classes, actually I made two contracts for putting business into models or service classes :
- Any single unit of business of records are moved to models (like actions on model events).
- Other businesses like sending text messages, emails, indexing elasticsearch with a nosql data structure, are moved into service classes.
I really like to know your idea on using repositories in your projects .
7 years later and this was one of my best decisions in writing software. Either use DataMapper ORM with separate persistence layer or ActiveRecord models not both.
Keeping application as close as possible to the Laravel way is the best way to keep it maintainable across different teams, official community trends and new versions. Worst applications to maintain and upgrade were those who invented architectural approaches baed on an incorrect or partial summary of a book or medium post.
Today, The same goes for Service objects (use case scenarios) or anything modeling your app outside the scope of the model itself (models backed by eloquent or just rich objects connected to other models.)
Please or to participate in this conversation.