In my judgment, We have a repository substitute in Laravel - It is custom query builder. When we put there our logic, we can use this methods like a scopes, and we don't have to create a additional layer on the eloquent. Additionaly, we can chaining this methods like a typical Eloquent Builder methods moreover models are not bloated.
Eloquent/Query builder are just (parts of) ORM, Repository pattern introduces decoupling between application core and used ORM. Lets say that you move your table(s) from SQL db to noSQL db. If you have repo that implements a repo contract, your code uses repo to access what is hidden behind it (ORM -> sql queries), then you create another repo that will implement the same contract but will use noSQL db as source of the data. You swap concrete implementations in a provider, and most likelly you can even re-use unit/integration tests you have for sql repo.
ORM is part of the application infrastucture and not the app itself, and thus it (ORM models) should be abstracted via Repositories.
"But how often db engine is changed? " this is wrong question, the correct question is "How often do we hear that existing app, developed over years by number of developers needs a full rewrite?"
Have a look at Explicit Architecture described by Herberto Graca.
I think it is important to say that laravel and eloquent itself acts as repository because you can setup different DB_CONNECTION in env which can be setup in database.php. This means eloquent can run same functions like where(), select() on mysql and mssql and other database engines as well. Maybe you can think of repository in case you want to start coding on mysql and you know that you want to switch to some moder DB like firebase or any other engine which is not supported by eloquent by default etc in future.
The only time time it make sense to me to use repository is when you get data from source like elastic search or algolia etc and you want a backup to eloquent in case the elastic search server drops down.
If your app has a chance to grow to mid size, will be activelly developed over a years, and you use some application architecture (Hexagonal, Onion, Clean, Explicit) then it makes sense to use repositories from the very beginning, and actually is mandatory.
I was of the same mindset until Domain Driven Design (DDD), which helped me see the value of repositories.
For example, Order application logic might aggregate **Order (aggregate root), Order Item (entity), and Address (value object) **around a bounded context of Ordering. You would have an OrderRepository that would then persist as a “unit of work.” For example, a method PlaceOrder() {} would be a single transaction that involves multiple insert, update, or delete operations across Order, Address, and OrderItem models. You end up with a single Order aggregate root, i.e., with a single data layer OrderRepository, which implements an OrderRepository Interface. Suppose the Order becomes more complex, channels, third party, etc. PlaceOrder() will remain the same.
The problem with how Laracasts taught repositories, which is the problem with most courseware, is a simplistic model of abstracting model logic into effectively a 1:1 model relationship, which serves little purpose. Per your example, getId(), find() immediately a code smells for a problem repository, but a method like placeOrder(Order $order, OrderItem $orderitem, Address $address) {} would make more sense. It has many benefits, i.e., such as simplifying testing, abstract logic to serve, adhering to SOLID principles, etc.
That said, repositories get abused, hide persistence logic, and often become bloated, so it depends on the developer. With Laravel, there is definitely an overlap with Eloquent
In my judgment, We have a repository substitute in Laravel - It is custom query builder. When we put there our logic, we can use this methods like a scopes, and we don't have to create a additional layer on the eloquent. Additionaly, we can chaining this methods like a typical Eloquent Builder methods moreover models are not bloated.
Eloquent/Query builder are just (parts of) ORM, Repository pattern introduces decoupling between application core and used ORM. Lets say that you move your table(s) from SQL db to noSQL db. If you have repo that implements a repo contract, your code uses repo to access what is hidden behind it (ORM -> sql queries), then you create another repo that will implement the same contract but will use noSQL db as source of the data. You swap concrete implementations in a provider, and most likelly you can even re-use unit/integration tests you have for sql repo.
But how often db engine is changed? In my judgment, repository in active record pattern is overenginering.
ORM is part of the application infrastucture and not the app itself, and thus it (ORM models) should be abstracted via Repositories.
"But how often db engine is changed? " this is wrong question, the correct question is "How often do we hear that existing app, developed over years by number of developers needs a full rewrite?"
Have a look at Explicit Architecture described by Herberto Graca.
diagram
Design he has for ORM part comes from Hexagonal Architecture described by Alistair Cockburn.
description
They abstract ORM for a reason.
I think it is important to say that laravel and eloquent itself acts as repository because you can setup different DB_CONNECTION in env which can be setup in database.php. This means eloquent can run same functions like where(), select() on mysql and mssql and other database engines as well. Maybe you can think of repository in case you want to start coding on mysql and you know that you want to switch to some moder DB like firebase or any other engine which is not supported by eloquent by default etc in future.
The only time time it make sense to me to use repository is when you get data from source like elastic search or algolia etc and you want a backup to eloquent in case the elastic search server drops down.
If your app has a chance to grow to mid size, will be activelly developed over a years, and you use some application architecture (Hexagonal, Onion, Clean, Explicit) then it makes sense to use repositories from the very beginning, and actually is mandatory.
I was of the same mindset until Domain Driven Design (DDD), which helped me see the value of repositories.
For example, Order application logic might aggregate **Order (aggregate root), Order Item (entity), and Address (value object) **around a bounded context of Ordering. You would have an OrderRepository that would then persist as a “unit of work.” For example, a method PlaceOrder() {} would be a single transaction that involves multiple insert, update, or delete operations across Order, Address, and OrderItem models. You end up with a single Order aggregate root, i.e., with a single data layer OrderRepository, which implements an OrderRepository Interface. Suppose the Order becomes more complex, channels, third party, etc. PlaceOrder() will remain the same.
The problem with how Laracasts taught repositories, which is the problem with most courseware, is a simplistic model of abstracting model logic into effectively a 1:1 model relationship, which serves little purpose. Per your example, getId(), find() immediately a code smells for a problem repository, but a method like placeOrder(Order $order, OrderItem $orderitem, Address $address) {} would make more sense. It has many benefits, i.e., such as simplifying testing, abstract logic to serve, adhering to SOLID principles, etc.
That said, repositories get abused, hide persistence logic, and often become bloated, so it depends on the developer. With Laravel, there is definitely an overlap with Eloquent
Would you mind to shed some linght on your DDD implementaion (if you use laravel)?
I can't imagine creatig app without using repositories.