@codeatbusiness I want to thank you for taking me to the idea to set on the fly the database name of the dynamic connection.
What i did worked well, but still don't know if there is a better approach, here it is:
- Have a ContextService to keep in session which database the model's database connection should be in context of.
<?php namespace Ghi\Providers;
use Illuminate\Support\ServiceProvider;
class ContextServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->bind(
'Ghi\Domain\Core\Services\Context',
'Ghi\Domain\Core\Services\ContextSession'
);
$this->app->bindShared('ghi.context', function()
{
return $this->app->make('Ghi\Domain\Core\Services\ContextSession');
});
}
}
- Have a connection used only by models that must be set in a dynamic database connection context.
'compac' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST_COMPAC'),
'database' => env('DB_DATABASE_COMPAC'),
'username' => env('DB_USERNAME_COMPAC'),
'password' => env('DB_PASSWORD_COMPAC'),
'prefix' => '',
],
Even if by default i'm setting the database name via a environment variable, with the BaseRepository i can read this and set it to other database name on the fly.
- Have a BaseRepository which will set the database name of the model before it establishes a connection.
<?php namespace Ghi\Domain\Core;
use Ghi\Domain\Core\Services\Context;
use Illuminate\Config\Repository;
abstract class BaseRepository {
/**
* @var Context
*/
protected $context;
/**
* @var Repository
*/
private $config;
/**
* @param Context $context
* @param Repository $config
*/
function __construct(Context $context, Repository $config)
{
$this->context = $context;
$this->config = $config;
$this->config->set('database.connections.compac.database', $this->context->getDatabaseName());
}
}
Here is where i set the database name on the fly using the database configuration.
- Then a Repository that extends BaseRepository
<?php namespace Ghi\Infraestructure\Polizas;
use Ghi\Domain\Core\BaseRepository;
use Ghi\Domain\Polizas\MovimientoPoliza;
use Ghi\Domain\Polizas\Poliza;
use Ghi\Domain\Polizas\PolizaRepository;
class EloquentPolizaRepository extends BaseRepository implements PolizaRepository {
/**
* Obtiene todas las polizas
*
* @return mixed
*/
public function getAll()
{
return Poliza::all();
}
/**
* Obtiene todas las polizas paginadas
*
* @param int $howMany
* @return mixed
*/
public function getAllPaginated($howMany = 50)
{
return Poliza::orderByRaw('Fecha DESC, Folio ASC' )
->paginate($howMany);
}
/**
* Obtiene los movimientos de una poliza por id
*
* @param $polizaId
* @return mixed
*/
public function getMovimientos($polizaId)
{
return MovimientoPoliza::where('IdPoliza', $polizaId)->get();
}
/**
* Obtiene una poliza por su id
*
* @param $id
* @return mixed
*/
public function getById($id)
{
return Poliza::find($id);
}
/**
* @param $folio
* @return mixed
*/
public function getByFolio($folio)
{
return Poliza::where('Folio', $folio)->firstOrFail();
}}
- Finally the Eloquent model used in the repository
<?php namespace Ghi\Domain\Polizas;
use Carbon\Carbon;
use Ghi\Domain\Core\TenantModel;
use Illuminate\Database\Eloquent\Model;
class Poliza extends Model {
/**
* @var string
*/
protected $connection = 'compac';
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'Polizas';
/**
* @var string
*/
protected $primaryKey = 'Id';
/**
* @var bool
*/
public $timestamps = false;
/**
* @var array
*/
protected $dates = ['Fecha'];
Every single model that should work on any database, needs the $connection attribute to be set to 'compac' because that is the connection "template" to be used to change its database name.
This was my solution until now, i think it is simple and clean, i am not a software engineer or software architect and think this can be done better.
What do you think about it?
Thank you!