I know this has been asked quite a long time.
This was answered at 2012-03-16.
There is Order model I forgot to draw. And I have to bind interface with repository in RepositoryServiceProvider
public function register()
{
$this->app->bind(RepositoryInterface::class, Repository::class);
$this->app->bind(MemberRepositoryInterface::class, MemberRepository::class);
$this->app->bind(OrderRepositoryInterface::class, OrderRepository::class);
$this->app->bind(OrderItemRepositoryInterface::class, OrderItemRepository::class);
//...
}
Now go back to that question's answer in 2012. Why we need to use interfaces? Because:
public class EmployeeRepositoryEF: IEmployeeRepository
{
public Employee[] GetAll()
{
//here you will return employees after querying your EF DbContext
}
}
public class EmployeeRepositoryXML: IEmployeeRepository
{
public Employee[] GetAll()
{
//here you will return employees after querying an XML file
}
}
public class EmployeeRepositoryWCF: IEmployeeRepository
{
public Employee[] GetAll()
{
//here you will return employees after querying some remote WCF service
}
}
But with the bindings in RepositoryServiceProvider, we can not use these different repositories at the same time. I cannot imaging how. We have to change the bindings. But if so, why not just change the type hint in service layer?
Ok, I saw many articles actually use:
Controller > SomeRepositoryInterface $someRepository > Model
They don't have service layer.
Does it mean, since I have service layer, So I don't need interface?
Controller > SomeService $someService> SomeRepository $someRepository > Model
If we want to change repository, just do:
In SomeService:
use App\Repositories\Abc\SomeRepository;
or
use App\Repositories\Xyz\SomeRepository;
Then
use App\Repositories\Eloquent\Sale\OrderRepository;
use App\Repositories\Eloquent\Sale\OrderItemRepository;
use App\Repositories\Eloquent\Sale\RmaRepository;
use App\Repositories\Eloquent\Member\MemberRepository;
use App\Repositories\Eloquent\Member\MemberGroupRepository;
or
use App\Repositories\MSSQL\Sale\OrderRepository;
use App\Repositories\MSSQL\Member\MemberRepository;
or
use App\Repositories\Oracle\Sale\OrderRepository;
use App\Repositories\Oracle\Member\MemberRepository;
Eloquent can change driver to use mssql or oracle. Then...
use App\Repositories\DbBuilder\Sale\OrderRepository;
use App\Repositories\DbBuilder\Member\MemberRepository;
or
use App\Repositories\RawSql\Sale\OrderRepository;
use App\Repositories\RawSql\Member\MemberRepository;
or
use App\Repositories\AnyOtherKind\Sale\OrderRepository;
use App\Repositories\AnyOtherKind\Member\MemberRepository;
Can someone give me some suggestion?
CodePudding user response:
Because we need a contract for the classes that people create over time. They should implement the same thing, and the customer should be able to use them interchangeably. If you don't have an interface, the next developer might forget implementing some methods and this means bad!
For example we have implemented our repositories to work with MySQL, and we exit the company. After a year, they plan for using something else rather than MySQL, so they have to implement new repositories that are compatible with the previous repositories and this is why we need an interface.
I hope my answer is simple and clear.
CodePudding user response:
To begin with, using Repository pattern is bad with Active Record (which is Eloquent). AR (active record) models already have all the methods to all possible CRUD operations and scopes to encapsulate logic within. Using repositories over them is a good example of overengineering, so I'd recommend not using them at all in Laravel.
When working with DM (data-mapper) models, repositories are used to switch between different databases (like in your example in RepositoryServiceProvider
). So, in case there is a need to change database over the project, you just create another implementation of repository for different database type. And again, in Laravel this is already done at query builder level, so you just don't need to do that by yourself.