Laravel Eloquent ORM 中的多租户

2021-12-26 00:00:00 database php laravel eloquent

这是来自

强制 Eloquent 模型重新解析数据库连接

有多个数据库连接:

return [
    'default' => 'mysql-key1',
    'connections' => [
        'mysql-key1' => [
            'driver'    => 'mysql',
            'database'  => 'key1_dbname,
            // etc
        ],
        'mysql-key2' => [
            'driver'    => 'mysql',
            'database'  => 'key2_dbname',
            // etc
        ]
    ]
];

我有一个使用模型 setConnection 更改连接属性的产品存储库:

I have a product repository which uses the Model setConnection to change the connection attribute :

public function setConnection($name) {
    // assumes $this->product is your Product model
    $this->product->setConnection($name);
}

然而,我发现它只适用于查询方法,而不适用于 Model::create ::

However, i found out that it only worked on query methods and not methods like Model::create ::

$productRepo = new ProductRepository();
foreach ($array as $key => $value) {
   $productRepo->setConnection($key . '_' . $database);
   // this works
   $products = $productRepo->all();
   // this doesn't work and will use the old connection 
   $product = $productRepo->create($data); 
}

似乎一旦创建了实例,::create 方法就不会解析连接.有人知道修复吗?

Seems that the ::create method does not resolve the connection once the instance has been created. Anyone knows a fix?

推荐答案

问题是 setConnection() 作用于一个类的实例,但是 create()> 方法是类本身的静态方法.在您的存储库中,$this->product 是 Product 类的一个实例.在执行查询之前在此实例上使用 setConnection() 会正常工作,但是如果您想在静态方法上使用单独的连接(例如 create()).

The problem is that setConnection() works on an instance of a class, but the create() method is a static method on the class itself. In your repository, $this->product is an instance of the Product class. Using setConnection() on this instance before doing queries will work fine, but you'll need to do a little more manual work if you want to use separate connections on the static methods (such as create()).

create() 方法所做的就是用给定的属性实例化一个新实例,然后调用 save().因此,无需在 Product 模型上调用 create(),您只需手动执行此操作:

All the create() method does is instantiate a new instance with the given attributes and then call save(). So, instead of calling create() on the Product model, you'll just need to do this manually:

class ProductRepository {
    public function create(array $attributes, $connection = null) {
        $product = $this->product->newInstance($attributes);
        $product->setConnection($connection ?: $this->product->getConnectionName());
        $product->save();
        return $product;
    }
}

您还可以覆盖 Product 模型上的静态 create() 方法以接受连接.

You could also override the static create() method on the Product model to accept a connection, as well.

class Product extends Model {
    public static function create(array $attributes, $connection = null) {
        $model = new static($attributes);
        $model->setConnection($connection ?: $this->connection);
        $model->save();
        return $model;
    }
}

class ProductRepository {
    public function create(array $attributes, $connection = null) {
        $connection = $connection ?: $this->product->getConnectionName()
        return $this->product->create($attributes, $connection);
    }
}

相关文章