跳到主要内容
PHP

laravel 反向使用hasOneThrough

管

管理员

PHP

2024年07月13日 1,503 次阅读
本页目录
从Mechanic对象可以使用carOwner()来访问owner,
同样在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表上的外键
        );
    }
}
  1. 从Owner开始,通过car_id外键找到相关的Car。
  2. 然后从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个字段

  1. hasOneThrough方法的参数顺序是固定的:
hasOneThrough(
    $related,
    $through,
    $firstKey,
    $secondKey,
    $localKey,
    $secondLocalKey
)
  1. 在我们的例子中:

    • $related 是 Mechanic::class
    • $through 是 Car::class
  2. 剩下的四个参数按顺序对应:

    • $firstKey: Car表上的本地键
    • $secondKey: Mechanic表上的本地键
    • $localKey: Owner表上的外键
    • $secondLocalKey: Car表上的外键
  3. 根据给定的表结构:

    • Owner通过car_id关联到Car
    • Car通过mechanic_id关联到Mechanic
    • 每个表都有一个id作为主键
  4. 因此,我们可以确定:

    • 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

Related

相关文章

同分类文章 →
2026年07月11日 PHP

laravel什么样的方法适合放在模型中?什么适合用专门的服务类? cachedFavIds适合放在模型中吗?

一、适合放在模型中的方法Laravel 采用 ActiveRecord 风格,模型本身就是"数据 + 围绕该数据的操作"的载体。以下几类方法适合放模型: 关联关系:belongsTo、morphTo、hasMany 等。如 UserFav::userfavable()、UserFav::us

2026年04月13日 PHP

Vue3 静态文件放在同域名 Laravel 项目下

核心思路是:Vue3 构建后的静态文件放到 Laravel 的 public/ 目录下,通过 Laravel 路由的 catch-all 机制让 SPA 的前端路由正常工作。方案说明以 xx.com/admin 为例,整体架构如下:请求流程:xx.com/admin/* → Laravel

2025年08月18日 PHP

Laravel Eloquent 中可以通过静态方式调用的方法

在 Laravel Eloquent 中,可以通过静态方式调用的方法包括:1. 查询作用域 (Scopes)// 可以静态调用UserComment::active()->get();UserComment::where('status', 1)->first();2. Eloquent 内置的查询方法UserComment::fi

WeChat

扫码加我微信

微信二维码