Laravel – override connection but model still returns data from previous connection

So this is my process. I run a command and it creates a new connection. It then sets that connection as default. THIS works perfectly.

It also overrides another connection. However, since we can only have one default instead of creating a new connection and setting it to default it simply copies the old connection / replaces the database info and then overrides that connection.

I then immediately create a model that uses this connection. I even go into it and dump out $this->getConnection() and see that its pulled in my new settings and configs. My issue is that when I do a ->all() I am getting info from the PREVIOUS overridden connection. I have no clue why.

Here is a sample of my code:

    public function handle()
    {
        if (!is_null($this->env = $this->option('env'))) {
            (new Dotenv(base_path(), ".env.{$this->env}"))->overload();
        }

        $this->setClientConnection();
        dd(Override::getModel('User')->changeConnection('webApp')->get()->pluck('login_name', 'users_id'));
    }

    /**
     * Create the database and a temporary connection
     *
     * @return null
     */
    protected function setClientConnection()
    {
        $clientDb = env('DB_DATABASE');
        $userDb   = env('DB_APP_DATABASE');
        // Create temporary connection
        $newConnection             = config('database.connections.data');
        $newConnection['database'] = $clientDb;
        config(['database.connections.' . $clientDb => $newConnection]);

        // Set new connection as default
        config(['database.default' => $clientDb]);

        // Override Webapp database
        $newUserConnection             = config('database.connections.webApp');
        $newUserConnection['database'] = $userDb;
        config(['database.connections.webApp' => $newUserConnection]);
    }

Just to reiterate, creating a new connection and setting it to default works perfectly. Creating a new connection and using it to override an existing connection SEEMS to work. config('database.connections.webApp') gives the new connection info. (new AppUser)->getConnection() returns the proper config and database is set to the new database. looking at the model object, all appears right. Then I go to make a ->all() call and it pulls in the overridden connection and pulls from the old database.

P.S. the changeConnection method i added to test out some things and to look at different protected attributes. Most of my dumping i did from there and it LOOKS like it should be using the new connection…till it actually makes the call…then no go.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

When you run get() on an Eloquent Model it runs the query on the IlluminateQueryBuilder object (after going through the IlluminateEloquentQueryBuilder wrapper function).

TheIlluminateQueryBuilder object stores a reference of the connection object used for the query.

Since your model is created first and then the connection is changed, the Query Builder object still uses the old connection

To solve this issue you need to create a fresh instance of the model query builder with the new connection

There are multiple ways to do this:

  1. Use the static function on like so: User::on('connection_name')->find($userId)
  2. Use the newFromBuilder method like so: $model->newFromBuilder($model->getAttributes, 'connection_name')
  3. Use the newQuery method to get a fresh Eloquent builder like so: $model->setConnection('connection_name')->newQuery()->find($userId)
  4. Use the fresh method like so: $model->setConnection('connection_name')->fresh().

Do note however that the fresh method fires a new query whereas the other options set the connection without firing a new query.

Your choice of function would be based on

  1. Whether you already have a model instance or whether you want to use static methods and
  2. Whether you only need the builder object (like #3) or you actually need the model instance


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x