laravel 反向使用hasOneThrough
更新时间:2024-07-13 16:20
从Mechanic对象可以使用carOwner()来访问owner,
同样在Owner定义一个hasOneThrough来访问mechanic
官方的案例:
在一个汽车维修的应用程序中,每一个
生成的sql如下:
同样在Owner定义一个hasOneThrough来访问mechanic
官方的案例:
在一个汽车维修的应用程序中,每一个
Mechanic
模型都与一个 Car
模型相关联,同时每一个 Car
模型也和一个 Owner
模型相关联。虽然维修师(mechanic)和车主(owner)在数据库中并没有直接的关联,但是维修师可以通过 Car
模型来找到车主。让我们来看看定义这种关联所需要的数据表:
mechanics
id - integer
name - string
cars
id - integer
model - string
mechanic_id - integer
owners
id - integer
name - string
car_id - integer
class Mechanic extends Model
{
/**
* Get the car's owner.
*/
public function carOwner(): HasOneThrough
{
return $this->hasOneThrough(Owner::class, Car::class);
}
}
class Mechanic extends Model
{
/**
* Get the car's owner.
*/
public function carOwner(): HasOneThrough
{
return $this->hasOneThrough(
Owner::class,
Car::class,
'mechanic_id', // Foreign key on the cars table...
'car_id', // Foreign key on the owners table...
'id', // Local key on the mechanics table...
'id' // Local key on the cars table...
);
}
}
从Owner对象访问Mechanic可以使用hasOneThrough关系,但方式略有不同。
在Owner模型中,我们可以定义一个通过Car到Mechanic的hasOneThrough关系。这是因为Owner通过Car间接关联到Mechanic。代码如下:
class Owner extends Model
{
/**
* 获取与此车主关联的机械师。
*/
public function mechanic(): HasOneThrough
{
return $this->hasOneThrough(
Mechanic::class,
Car::class,
'id', // Car表上的本地键
'id', // Mechanic表上的本地键
'car_id', // Owner表上的外键
'mechanic_id' // Car表上的外键
);
}
}
- 从Owner开始,通过car_id外键找到相关的Car。
- 然后从Car,通过mechanic_id外键找到相关的Mechanic。
使用这个关系,您可以这样访问与车主关联的机械师:
$owner = Owner::find(1);
$mechanic = $owner->mechanic;
需要注意的是,这个关系假设每个车主只有一辆车,每辆车只有一个机械师。如果一个车主可能有多辆车,或者一辆车可能有多个机械师,那么关系类型可能需要调整为hasManyThrough。
我们可以在Owner模型中定义一个hasOneThrough关系来访问Mechanic,这提供了一种优雅的方式来遍历这些相关的模型。
如何确定'id', // Car表上的本地键 'id', // Mechanic表上的本地键 'car_id', // Owner表上的外键 'mechanic_id' // Car表上的外键
这4个字段
- hasOneThrough方法的参数顺序是固定的:
hasOneThrough(
$related,
$through,
$firstKey,
$secondKey,
$localKey,
$secondLocalKey
)
-
在我们的例子中:
- $related 是 Mechanic::class
- $through 是 Car::class
-
剩下的四个参数按顺序对应:
- $firstKey: Car表上的本地键
- $secondKey: Mechanic表上的本地键
- $localKey: Owner表上的外键
- $secondLocalKey: Car表上的外键
-
根据给定的表结构:
- Owner通过car_id关联到Car
- Car通过mechanic_id关联到Mechanic
- 每个表都有一个id作为主键
-
因此,我们可以确定:
- Car表的本地键是'id'
- Mechanic表的本地键是'id'
- Owner表上关联到Car的外键是'car_id'
- Car表上关联到Mechanic的外键是'mechanic_id'
这就是为什么我们最终得到了这样的参数顺序:
'id', // Car表上的本地键
'id', // Mechanic表上的本地键
'car_id', // Owner表上的外键
'mechanic_id' // Car表上的外键
其实就是把正向的参数完全反过来.生成的sql如下:
update
`shop_goods_skus`
inner join `shop_order_goods` on `shop_order_goods`.`shop_goods_sku_id` = `shop_goods_skus`.`id`
set
`stock` = `stock` + 1,
`shop_goods_skus`.`updated_at` = '2024-07-13 15:31:57'
where
`shop_order_goods`.`id` = 2