![](/img/trans.png)
[英]Laravel Pagination not working after setConnection() on eloquent model
[英]Is there another way to “setConnection” on an Eloquent Model?
我目前正在处理“多数据库动态交换连接”类型的项目。
所以我最终做的是以下内容:
$connectionName = uniqid();
\Config::set('database.connections.' . $connectionName, [/** db options **/]);
\Artisan::call('migrate', ['--database' => $connectionName]);
或者
$connectionName = uniqid();
\Config::set('database.connections.' . $connectionName,[/** db options **/]);
$user = new User();
$user->setConnection($connectionName);
$user->first_name = 'Daisy';
$user->last_name = 'Demo';
$user->is_not_being_ignored_by_santa_this_year = 0;
$user->email = //and so so on
$user->save();
对于 Artisan 调用,我有点理解为什么 Laravel 需要引用保存在配置数组中的字符串中的连接。
然而,在 Eloquent 模型本身上,我发现将我的数据库连接写入配置数组有点麻烦。 因此,它可以通过模型中的“单例方法”\\Config::get().. 来获取。
有没有更优雅的东西,我可以直接注入配置而不必将其写入一些超级全局?
或者我错过了什么?
您可能最好为每个连接创建一个配置数组,然后您可以通过指定要使用的连接轻松地在连接之间切换。
如果您需要在同一模型上使用多个连接,您可以使用on
方法:
所以它会像User::on('dbconnection2')->find(1)
如果只想为不同的模型使用不同的连接,可以在模型上设置 protected $connection
属性:
class User extends Model
{
protected $connection = 'dbconnection2';
}
希望有帮助。
您可以为您的模型创建一个工厂,并在引导您的应用程序时将连接传递给它:
<?php
class ModelFactory
{
private $db;
public function __construct($dbConnection)
{
$this->db = $dbConnection;
}
public function createNewModel($class)
{
$object = new $class();
$object->setConnection($this->db);
return $object;
}
}
然后在你的代码中:
$user = $factory->createModel(User::class);
像这样的东西! 祝你好运! :-)
我构建了一个多租户 laravel 应用程序,并惊讶于没有开箱即用的方法来做到这一点。
我有一个通过不同子域可用的应用程序,子域应该是不同配置的关键,比如数据库连接。
您可以轻松地将其调整为您需要的任何标准,而不是子域。
所以我的第一次尝试是始终使用“默认”连接并创建一个动态调用Config::set("database.connection.default.host", "1.3.5.7");
的中间件Config::set("database.connection.default.host", "1.3.5.7");
等等所有其他设置。
但也有一些缺点。 例如,它非常慢,因为我从数据库读取所有值,然后从 redis 读取。 但是更大的问题是例如设置到 redis 缓存的连接,因为在调用中间件覆盖配置设置之前已经建立了 redis 连接。
所以我的第二个也是当前的方法是通过配置文件来完成这一切。 所以我创建了以下文件结构:
注意:下划线很重要,因为文件是按字母顺序读取的,我们的新文件必须首先读取才能在其他配置文件中使用它。
目标是使用config('_myapp.DB_HOST')
从 config/subdomain1/_myapp.php 检索 DB_HOST 值并将其用作 config/database.php 中的值。 所以 config/_myapp.php 只返回特定子域的 _myapp.php 的内容。
在 config/_myapp.php: <?php
// get the current subdomain from $_SERVER['HTTP_HOST']
$subdomain = \App\Helper::getSubDomain();
define('SUBDOMAIN', $subdomain);
if(!empty($subdomain) && file_exists($file = __DIR__."/$subdomain/".basename(__FILE__)))
return require($file);
return [
];
并在 config/_myapp.php 中:
return [
...
'DB_HOST' => '1.3.5.7',
...
];
例如在 config/database.php 或任何需要域特定配置的地方使用它:
...
'host' => config('_myapp.DB_HOST'),
...
请询问是否有问题,我花了很长时间才弄明白。
这完全取决于您如何处理多个连接。我曾从事过类似的需求项目。
Tenant Setup after login
检查Tenant Setup after login
。DatabaseConnection
。TenantContextSession
租户模型抽象类
<?php
namespace App\Models\Abstracts;
use App\Models\Abstracts\AbstractBaseModel;
use App\Models\Picklist\PicklistValue;
class TenantAbstractBaseModel extends AbstractBaseModel
{
function __construct(array $attributes = array())
{
parent::__construct($attributes);
if ( ! is_null(app('tenant.context')->getConnectionName())) {
$this->setConnection(app('tenant.context')->getConnectionName());
}
//todo; should be dynamic
if (is_null(app('tenant.context')->getConnectionName())
&& app()->runningInConsole()
) {
//todo; need to resolve database connection through terminal and application.
//dd(config('tenant.tenant_connection'));
//$this->setConnection(config('tenant.tenant_connection'));
}
}
}
登录后的租户设置
$connection = config('tenant.tenant_connection');
//config()->set('database.default', config('tenant.tenant_connection'));
app('tenant.context')->setConnectionName($connection);
app('tenant.context')->setTenantId($company_id);
//$database = config('database.connections.' . $connection . '.database') . $company_id;
$company_system_name
= $this->auth->user()->company->system_name;
config()->set('database.connections.'.$connection.'.database',
$company_system_name);
//config()->set('database.connections.' . $connection . '.database', $database);
config()->set('database.default', $connection);
数据库连接
<?php
namespace App\Tenancy\Tenant;
use Config;
use DB;
use App\Tenancy\Exceptions\TenantDatabaseException;
use App\Tenancy\Models\Tenant;
/**
* Class DatabaseConnection
*
* Helps with tenant database connections
*/
class DatabaseConnection
{
/**
* See the multi-tenant configuration file. Configuration set
* to use separate databases.
*/
const TENANT_MODE_SEPARATE_DATABASE = 'database';
/**
* See the multi-tenant configuration file. Configuration set
* to use prefixed table in same database.
*/
const TENANT_MODE_TABLE_PREFIX = 'prefix';
/**
* Current active global tenant connection.
*
* @var string
*/
protected static $current;
/**
* @var string
*/
public $name;
/**
* @var Tenant
*/
protected $tenant;
/**
* @var \Illuminate\Database\Connection
*/
protected $connection;
public function __construct(Tenant $tenant)
{
$this->tenant = $tenant;
$this->name = "tenant.{$this->tenant->hash_id}";
$this->setup();
}
/**
* Sets the tenant database connection.
*/
public function setup()
{
Config::set("database.connections.{$this->name}", $this->config());
}
/**
* Generic configuration for tenant.
*
* @return array
*/
protected function config()
{
$clone = Config::get(sprintf('database.connections.%s',
static::tenantConnectionName()));
$clone['database'] = $this->tenant->system_name;
return $clone;
}
/**
* Central getter for system connection name.
*
* @return string
*/
public static function systemConnectionName()
{
return Config::get('tenant.master_connection', 'mysql');
}
/**
* Checks whether current connection is set as global tenant connection.
*
* @return bool
*/
public function isCurrent()
{
return $this->name === static::getCurrent();
}
/**
* Loads the currently set global tenant connection name.
*
* @return string
*/
public static function getCurrent()
{
return static::$current;
}
/**
* Sets current global tenant connection.
*/
public function setCurrent()
{
static::$current = $this->name;
Config::set(sprintf('database.connections.%s',
static::tenantConnectionName()), $this->config());
DB::purge(static::tenantConnectionName());
}
/**
* Central getter for tenant connection name.
*
* @return string
*/
public static function tenantConnectionName()
{
return Config::get('tenant.tenant_connection', 'tenant_mysql');
}
/**
* Loads connection for this database.
*
* @return \Illuminate\Database\Connection
*/
public function get()
{
if (is_null($this->connection)) {
$this->setup();
$this->connection = DB::connection($this->name);
}
return $this->connection;
}
/**
* @return bool
*/
public function create()
{
$clone = $this->config();
return DB::connection(static::systemConnectionName())
->transaction(function () use ($clone) {
if ( ! DB::connection(static::systemConnectionName())
->statement("create database if not exists `{$clone['database']}`")
) {
throw new TenantDatabaseException("Could not create database {$clone['database']}");
}
if ( ! DB::connection(static::systemConnectionName())
->statement("grant all on `{$clone['database']}`.* to `{$clone['username']}`@'{$clone['host']}' identified by '{$clone['password']}'")
) {
throw new TenantDatabaseException("Could not create or grant privileges to user {$clone['username']} for {$clone['database']}");
}
return true;
});
}
/**
* @throws \Exception
*
* @return bool
*/
public function delete()
{
$clone = $this->config();
return DB::connection(static::systemConnectionName())
->transaction(function () use ($clone) {
if ( ! DB::connection(static::systemConnectionName())
->statement("revoke all on `{$clone['database']}`.* from `{$clone['username']}`@'{$clone['host']}'")
) {
throw new TenantDatabaseException("Could not revoke privileges to user {$clone['username']} for {$clone['database']}");
}
if ( ! DB::connection(static::systemConnectionName())
->statement("drop database `{$clone['database']}`")
) {
throw new TenantDatabaseException("Could not drop database {$clone['database']}");
}
return true;
});
}
}
*租户上下文会话*
<?php
namespace App\Repositories\Tenant;
use App\Repositories\Tenant\TenantContextRepositoryContract;
/**
* Description of TenantContextSession
*
* @author safoor
*/
class TenantContextSession implements TenantContextRepositoryContract
{
// public function __construct() {
// $this->clearTenantSession();
// }
/**
* Sets the connection name for the actual context
* this tenant
* @param $name
* @return mixed
*/
public function setConnectionName($name)
{
if (session()->has('tenant_connection')) {
session()->set('tenant_connection', '');
}
session()->put('tenant_connection', $name);
}
/**
* Get the name of the current connection in context
* @return mixed
*/
public function getConnectionName()
{
return session()->get('tenant_connection');
}
/**
* Sets the id value filter data in the current context
* @param $id
* @return mixed
*/
public function setTenantId($id)
{
if (session()->has('tenant_id')) {
session()->set('tenant_id', '');
}
session()->put('tenant_id', $id);
}
/**
*
* @return mixed
*/
public function getTenantId()
{
return session()->get('tenant_id');
}
public function clearTenantSession()
{
session()->flush();
session()->set('tenant_id', '');
session()->set('tenant_connection', '');
}
}
我希望这对您的场景有所帮助,我已尝试提及我们必须涵盖的所有方面,但如果仍有一些令人困惑的问题并需要我的解释,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.