简体   繁体   English

Laravel口才ORM中的多租户关系

[英]Relationships in multi tenancy in Laravel Eloquent ORM

Once again this is a follow up question to : 再次这是对以下问题的跟进问题:

Multi tenancy in Laravel Eloquent ORM Laravel Eloquent ORM中的多租户

This time around I have questions for using relationships in a multi-tenancy environment for eloquent models. 这次,我对在雄辩模型的多租户环境中使用关系存在疑问。

Given a Product model : 给定产品模型:

class Product extends Eloquent {

public function accessories()
{
    return $this->belongsToMany('Accessory', 'product_accessory', 'product_id', 'accessory_id')
                ->withPivot('id')
                ->withTimestamps();
}

Is that any easy way to make sure that the relationship method accessories() uses the correct database connection? 有什么简单的方法可以确保关系方法Accessories()使用正确的数据库连接? Right now when I do a attach method like this : 现在,当我执行这样的attach方法时:

$product->accessories()->attach($accessory->id, $attributes);

the accessories method seem to be pointing to another database different from the $product entity. 附件方法似乎指向与$ product实体不同的另一个数据库。 I believe this is because the Accessory model connection does not get changed when the relationship is instantiated. 我相信这是因为实例化关系时,附件模型连接不会更改。

If you see my answer to your original question regarding Model Events & Observers, this should inherently solve this problem too: Multi tenancy in Laravel Eloquent ORM 如果您看到我对有关模型事件和观察者的原始问题的回答,这也应该从本质上解决此问题: Laravel Eloquent ORM中的多租户

All the Eloquent relational methods: attach, associate etc... all trigger the respective Model Events as detailed here: http://laravel.com/docs/5.0/eloquent#model-events 所有雄辩的关系方法:附加,关联等...均触发相应的模型事件,如此处所述: http : //laravel.com/docs/5.0/eloquent#model-events

If you setup a Model Observer to manipulate the connection in use pre & post saving of specific models, all your relational calls will have the database connection set appropriately automatically. 如果您设置了模型观察器以在保存特定模型之前或之后使用操纵模型的连接,则所有关系调用都将自动适当地设置数据库连接。

Hope this helps 希望这可以帮助

-- Edit in response to comment -编辑以回应评论

Hi yulun, 嗨,玉伦

Sorry I mistook your accessories call for associate. 对不起,我误把您的配件电话联系了。 (Saving relations) (保存关系)

However you should be able to achieve a similar result where your relationship is defined. 但是,在定义您的关系后,您应该能够获得类似的结果。 See below example: 请参见以下示例:

class ProductModel extends Eloquent {

    protected $table = 'products';

    protected $connection;

    protected $databases = [
        'default' => 'mysql-key1',
        'products' => 'mysql-key2'
    ];

    public function __construct(Connection $connection)
    {
        $this->connection = $connection;
    }

    public function accessories()
    {
        $this->connection->reconnect($this->databases['products']);
        $accessories = $this->hasMany('AccessoriesModel');
        $this->connection->reconnect($this->databases['default']);

        return $accessories;
    }
}

You could then take it further by creating an abstract class that all affected models can extend, eg: 然后,您可以通过创建所有受影响的模型都可以扩展的抽象类来进一步扩展它,例如:

abstract class DatabaseModel extends Eloquent {

     protected $connection;

     protected $databases = [
         'default' => 'mysql-key1',
         'products' => 'mysql-key2'
     ];

     public function __construct(Connection $connection)
     {
         $this->connection = $connection;
     }

    protected function setProductsDatabase()
    {
        $this->connection->reconnect($this->databases['products']);
    }

    protected function resetDatabaseConnection()
    {
        $this->connection->reconnect($this->databases['default']);
    }
}

class ProductModel extends DatabaseModel {

    protected $table = 'products';

    public function accessories()
    {
        $this->setProductsDatabase();
        $accessories = $this->hasMany('AccessoriesModel');
        $this->resetDatabaseConnection();

        return $accessories;
    }
}

This way, everything will behave "naturally" without the need for any additional code providing your relationships have been configured correctly. 这样,只要您的关系已正确配置,一切都将“自然”地进行,而无需任何其他代码。

A neater, but more complicated solution would be to instead of manipulating the database in the model you could fire your own "retrieving" event, you could then add an event handler to the Model Observer for your custom "retrieving" event - This would be my preference, and you can find more information on how to do it here: http://laravel.io/forum/05-24-2014-how-could-i-create-custom-model-events?page=1 一个更巧妙但更复杂的解决方案是,您可以触发自己的“检索”事件,而不是在模型中操作数据库,然后可以为自定义“检索”事件向模型观察器添加事件处理程序-这将是我的喜好,您可以在此处找到有关操作方法的更多信息: http : //laravel.io/forum/05-24-2014-how-could-i-create-custom-model-events?page=1

Hope this helps 希望这可以帮助

Using cues from Beevee's answer, we can also extend the Eloquent class as an base model to use a session based or config based connection such as 根据Beevee的回答,我们还可以将Eloquent类扩展为基本模型,以使用基于会话或基于配置的连接,例如

class BaseModel extends Eloquent {

public function __construct(array $attributes = array())
{
    parent::__construct($attributes);

    $this->setConnection(\DB::getDefaultConnection());
}

} }

This way, all the relation methods will automatically be instantiated to use the connection. 这样,所有关联方法将自动实例化以使用连接。

class Product extends BaseModel {

public function accessories()
{
  return $this->belongsToMany('Accessory', 'product_accessory', 'product_id', 'accessory_id')
            ->withPivot('id')
            ->withTimestamps();
}

provided the Accessory class also extends BaseModel. 如果Accessory类也扩展了BaseModel。 This way, you can change the database connection at runtime at will. 这样,您可以在运行时随意更改数据库连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM