Multi tenancy in Laravel Eloquent ORM

后端 未结 2 429
耶瑟儿~
耶瑟儿~ 2020-12-22 05:51

This is sort of a follow up question from

Forcing Eloquent models to re resolve database connection

With multiple database connections :

re         


        
2条回答
  •  半阙折子戏
    2020-12-22 06:41

    You should be able to utilize Model Events & Observers to manipulate the connection being used, documentation is available here:

    • http://laravel.com/docs/4.2/eloquent#model-events

    • http://laravel.com/docs/4.2/eloquent#model-observers

    You could create a single DatabaseModelObserver (As below) that you could attached to each of the relevant models that will set the connection before saving and reset it after saving as below:

    class DatabaseModelObserver {
    
        protected $databases = [
            'default' => 'mysql-key1',
            'products' => 'mysql-key2'
        ];
    
        protected $connection;
    
        public function __construct(Connection $connection)
        {
            $this->connection = $connection;
        }
    
        public function saving($model)
        {
            $this->connection->reconnect($this->databases['products']);
        }
    
        public function saved($model)
        {
            $this->connection->reconnect($this->databases['default']);
        }
    }
    

    You would then attach the observer to the relevant models via a Service Provider, utilizing the boot method as detailed below:

    class ModelServiceProvider extends ServiceProvider {
    
        public function register()
        {
        }
    
        public function boot()
        {
            ProductModel::observe(
                $this->app->make('DatabaseModelObserver')
            );
        }
    }
    

    You could attach this same Observer to as many models as required, you just need to add them to the boot method, eg:

    public function boot()
    {
        ProductModel::observe(
            $this->app->make('DatabaseModelObserver')
        );
        CategoryModel::observe(
            $this->app->make('DatabaseModelObserver')
        );
        StoreModel::observe(
            $this->app->make('DatabaseModelObserver')
        );
    }
    

    This should work with all your existing repositories, providing your repositories use Eloquent under the hood, which I'm assuming them do.

    The code above is untested, and the specifics surrounding the connection class injected into the observer may be off, but are based on the documentation on the DB Facade - Can't post any more links :(

    EDIT

    Having looked into patricus answer in a little more detail, using a model event should solve his issue with the static nature of the create method.

    The instance of the Model being saved is passed to each model event, in my example above as $model therefore there should be no issues doing the below in your model observer instead:

    public function saving($model)
    {
        $model->setConnection($this->databases['products']);
    }
    
    public function saved($model)
    {
        $model->setConnection($this->databases['default']);
    }
    

    This should be a much more efficient solution.

提交回复
热议问题