Home » Php » php – Different db connection for models using hasManyThrough relationship in laravel 5.1

php – Different db connection for models using hasManyThrough relationship in laravel 5.1

Posted by: admin July 12, 2020 Leave a comment

Questions:

I am trying to use the hasManyThrough relationship in laravel 5.1 but the sql query is not using the appropriate prefix defined in each connection for each model used.
I have 3 models 2 of which use the same connection and one of them uses a different one. The only difference between the connections is the prefix the database is the same.

  • Model A has connection A which uses prefix A_
  • Model B has connection B which uses prefix B_
  • Model C has connection B which uses prefix B_

The relationship:

Inside Model B:

public function relationshipWithA()
{
    return $this->hasManyThrough(A::class, C::class, 'Cid', 'Aid');
}

The final query logic is correct but instead of using the B_ prefix for the joined tables its using the A_ prefix for all the tables in the query.

Is this a bug/limitation of laravel? Is there a solution to this or I will have to do manual join to achieve what I want?

How to&Answers:

Other relationship types work with multiple database connections:

public function foos()
{
    return $this->belongsToMany(Foo::class, 'other_db.foos');
}

But hasManyThrough does not have the $table parameter in its signature, so the same solution is not applicable.

However,

You can make an imperfect workaround like this:

public function bars()
{
    return $this->belongsToMany(Bar::class, 'other_db.bars');
}

public function foos()
{
    $barIds = $this->bars->pluck('id');
    return Foo::whereIn('bar_id', $barIds);
}

It does not offer the exact same functionality (Since it is a different return-type), but fulfills the purpose for more simple things.

If you want, you can also replicate some more of the syntax by doing something like this:

protected $appends = [
    'foos',
];

/**
 * @return Foo[]
 */
public function getFoosAttribute()
{
    return $this->foos()->get();
}

That way you can still use it in your code like you would most of the time with a regular relationship (Meaning you can use $this->foos instead of $this->foos()->get())

Answer:

Actually, it seems to work fine if you specify the connections inside your model classes via the $connection property. I tested it (Laravel 5.5) between a MySQL and SQL connection using a morphMany relationship:

Account Model:

class Account extends Model
{
    protected $connection = 'sqlsrv';

    public function notifications()
    {
        return $this->morphMany(Notification::class, 'notifiable');
    }
}

Notification Model:

class Notification extends Model
{
    protected $connection = 'mysql';

    public function notifiable()
    {
        return $this->morphTo();
    }
}