toby's avatar
Level 31

BelongsToMany with different DB connections

Hi everyone,

I've got two Models:

  • Action is a model on my local database (mysql connection)
  • Repair is a model on a different database (sqlsrv connection; read-only)

Now I need to link those models via belongsToMany; therefore I created a action_repair-table as a pivot table with the columns action_id and repair_id; this pivot table is created on the mysql connection.

But as soon as I try to save new relations, Laravel assumes, that the pivot table lives on the sqlsrv connection (like the Repair model), which is wrong.

How can I set a $connection for this pivot table?!

Thanks in advance!

0 likes
7 replies
grenadecx's avatar

You need to setup a custom model for the pivot relation and then you should be able to use it to store it on the right connection.

Look under "Defining Custom Intermediate Table Models" https://laravel.com/docs/5.8/eloquent-relationships

Example:

// Action class
class Action extends Model
{
    public function repair()
    {
    // use ActiolnRepair model for the pivot table
        return $this->belongsToMany('App\Repair')->using('App\ActionRepair'); 
    }
}

// Repair class
class Repair extends Model
{
    public function action()
    {
    // use ActiolnRepair model for the pivot table
        return $this->belongsToMany('App\Action')->using('App\ActionRepair'); 
    }
}

And then the ActionRepair model needs to extend Illuminate\Database\Eloquent\Relations\Pivot

<?php

namespace App;

use Illuminate\Database\Eloquent\Relations\Pivot;

class ActionRepair extends Pivot
{
    // setup db connections on this model
}
toby's avatar
Level 31

Hi and thanks for your reply,

In the meantime I tried exactly this; with no luck :(

I tried the following approaches:

// App/Action.php

public function repairs()
{
    return $this->belongsToMany(Repair::class)->using(ActionRepair::class);
}

with this Pivot class:

// App/ActionRepair.php

use Illuminate\Database\Eloquent\Relations\Pivot;

class ActionRepair extends Pivot
{
    protected $connection = 'mysql'; // tested 'default' as well...

    // and setting it in the constructor also doesn't work
    public function __construct(array $attributes = [])
    {
        $this->setConnection('mysql'); // tested 'default' as well...
        parent::__construct($attributes);
    }
}

The connection attributes seems to be ignored, even if I write gibberish in there like asdf, it doesn't do anything :(

grenadecx's avatar

Oh, that seems a bit weird, since

Illuminate\Database\Eloquent\Relations\Pivot;

in turn extends the

Illuminate\Database\Eloquent\Model;

So I would assume it would use the connection as usual. The only thing in the Pivot class that I can see that maybe affects this is the:


    // This function in 5.8 comes from the trait AsPivot which the extending Pivot relation is using.
    // /src/Illuminate/Database/Eloquent/Relations/Concerns/AsPivot.php
    public static function fromAttributes(Model $parent, $attributes, $table, $exists = false)
    {
        $instance = new static;
        $instance->setConnection($parent->getConnectionName())
                ->setTable($table)
                ->forceFill($attributes)
                ->syncOriginal();
    // more code
    }

Here it seems it sets the connection to the parent model. Maybe this causes the problem? You could try to override this function and see if that changes anything.

Edit: It might break other stuffs, I've no idea how this is used in conjunction with everything else, but that should be easy to find out, if it's the culprit or not.

grenadecx's avatar

Alrighty then, interesting that this isn't possible already to be honest. Well I guess you just need to find the right function to ovverride. Good luck!

Please or to participate in this conversation.