How can I get multiple repositories with different DB connections when using Repository Pattern.
Hello, I'm building an API Server using Laravel 10.
I choose Repository Pattern for testing, but struggled with multiple DB connections issue.
Added setConnection($connection)
into my BaseRepository
.
This calls Eloquent Model's setConnection($connection)
to change the connection.
Also added getConnectionNames()
to retrive connection's name.
On controller's constuctor, get injected interface and assign to repository.
Before assigning, changed connection.
Calling '/user/test' should returns connection names by repository.
{
'user_repo01': 'db01',
'user_repo02': 'db02',
'user_repo03': 'db03',
}
{
'user_repo01': 'db03',
'user_repo02': 'db03',
'user_repo03': 'db03',
}
It seems injected interface is shared with all the repositories.
Not sure why, I just started applying Repository Pattern and I don't know much about it.
What I missed? How can I achieve what I want?
'connections' => [
'db01' => [ ... ],
'db02' => [ ... ],
'db03' => [ ... ],
]
interface BaseRepositoryInterface
{
public function setConnection(string $connection);
public function getConnectionName();
}
class BaseRepository implements BaseRepositoryInterface
{
public function __construct(Model $model) {
$this->model = $model;
}
public function setConnection(string $connection) {
$this->model->setConnection($connection);
return $this;
}
public function getConnectionName() {
return $this->model->getConnectionName();
}
}
interface UserRepositoryInterface extends BaseRepositoryInterface
{
}
class UserRepository extends BaseRepository implements UserRepositoryInterface
{
public function __construct(User $model) {
parent::__construct($model);
}
}
class RepositoryServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
}
}
class UserController extends Controller
{
private $user_repo01;
private $user_repo02;
private $user_repo03;
public function __construct(UserRepositoryInterface $user_repo) {
$this->user_repo01 = $user_repo->setConnection('db01');
$this->user_repo02 = $user_repo->setConnection('db02');
$this->user_repo03 = $user_repo->setConnection('db03');
}
/**
* /user/test
*/
public function test() {
return [
'user_repo01' => $this->user_repo01->getConnectionName(),
'user_repo02' => $this->user_repo02->getConnectionName(),
'user_repo03' => $this->user_repo03->getConnectionName(),
];
}
Self answered.
Changed to returning instance via resolve()
, also separated getInstance()
from setConnection()
Interface BaseRepositoryInterface
{
public function getInstance(?string $connection = null): self;
public function setConnection(string $connection);
public function getConnectionName(): ?string;
}
class BaseRepository implements BaseRepositoryInterface
{
public function __construct(Model $model) {
$this->model = $model;
}
public function getInstance(?string $connection = null): self {
$new_instance = resolve($this::class);
if($connection)
$new_instance->setConnection($connection);
return $new_instance;
}
public function setConnection(string $connection) {
$this->model->setConnection($connection);
}
public function getConnectionName(): ?string {
return $this->model->getConnectionName();
}
}
class UserController extends Controller
{
private $user_repo01;
private $user_repo02;
private $user_repo03;
public function __construct(UserRepositoryInterface $user_repo) {
$this->user_repo01 = $user_repo->getInstance('db01');
$this->user_repo02 = $user_repo->getInstance('db02');
$this->user_repo03 = $user_repo->getInstance('db03');
}
/**
* /user/test
*/
public function test() {
return [
'user_repo01' => $this->user_repo01->getConnectionName(),
'user_repo02' => $this->user_repo02->getConnectionName(),
'user_repo03' => $this->user_repo03->getConnectionName(),
];
}
{
'user_repo01': 'db01',
'user_repo02': 'db02',
'user_repo03': 'db03',
}