在我的应用程序(Laravel 9)中,用户可以属于组,并且用户可以访问“附加”到他们所属组的资源。
但是资源存储在不同的数据库上(我们使用两个不同的 RDS 实例)。组和用户在默认实例上进行管理(我还管理所有用户/组权限),我还创建了数据透视表(在这个简化的情况下是
group_item
)。
class Group extends Model
{
// default connection
public function addItem($item): void
{
$this->items()->attach($item);
}
public function items(): BelongsToMany
{
return $this->belongsToMany(Item::class);
}
}
class Items extends Model
{
protected $connection = 'external';
protected $primaryKey = 'item_id';
}
public function test_group_items()
{
$group = Group::factory()->create();
$i = Item::first();
$group->addItem($i);
$this->assertTrue($group->items->contains($i));
}
在上面的简单测试中,“默认”实现存在数据库引用问题,因为它在传递模型的连接/数据库上查找数据透视表:
Illuminate\Database\QueryException : SQLSTATE[42S02]: Base table or view not found: 1146 Table 'external_db.group_item' doesn't exist (SQL: insert into `group_item` (`group_id`, `items_item_id`) values (49, 1))
调整belongsToMany实例确实解决了将项目附加到项目列表时的问题,但是在返回集合时它会中断
public function items(): BelongsToMany
{
return $this->newBelongsToMany(
$this->newQuery(),
$this,
'group_item',
'item_id',
'group_id',
'id',
'item_id',
'items'
);
}
Illuminate\Database\QueryException : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'groups.item_id' in 'on clause' (SQL: select `groups`.*, `group_item`.`item_id` as `pivot_item_id`, `group_item`.`group_id` as `pivot_group_id` from `groups` inner join `group_item` on `groups`.`item_id` = `group_item`.`group_id` where `group_item`.`item_id` = 74)
(此处
groups.item_id
应该是groups.id
)
即使上述方法有效,并且从数据透视表中定义了正确的项目 ID,我想知道在调用关系方法时代码如何处理 JOIN 以及从其他数据库获取和实例化记录(在本例中为
$group->items()
)。
有什么想法吗?
这个答案确实解决了我的问题,并且(神奇地)该关系只需传递数据库名称即可!
public function items(): BelongsToMany
{
return $this->belongsToMany(
Item::class,
"{$this->getConnection()->getDatabaseName()}.group_item",
null,
'item_id'
);
}