【问题标题】:Eloquent filtering of nested嵌套的 Eloquent 过滤
【发布时间】:2014-09-18 13:24:45
【问题描述】:

我有一个这样建模的数据库:

User
+ id
+ email
+ password 

Profile
+ id
+ owner_id (FK user.id)
+ type_id (FK types.id)
+ address_id (FK addresses.id)
+ org_name
+ phone
+ email
+ url
  etc

Postings
+ id
+ profile_id (FK profiles.id)
+ title
+ description

Addresses
+ id
+ street
+ city 
+ province_id (FK provinces.id)
+ country_id (FK countries.id)
  etc

Countries
+ id
+ name

Provinces
+ id
+ name
+ abbreviation
+ country_id

我正在尝试使用 Eloquent ORM 根据 type_id、city、country_id 和/或 Province_id 从中查询一组 Postings。这些字段位于从属对象 $posting->profile->address 等上。

我是否将不得不简化我的数据库 - 通过将地址数据合并到其中来平整配置文件?或者有没有办法在 Eloquent 中做到这一点,而无需重塑我的所有数据?

【问题讨论】:

标签: laravel orm eloquent relationship


【解决方案1】:

这是您根据相关表中的约束过滤表的方式:

// we need to pass all the ids to the closure, so use one array for convenience:
$filters = [
    'typeId'     => 1,
    'addressId'  => 5,
    'provinceId' => 10,
    'countryId'  => 15
];

$posts = Posting::whereHas('profile', function ($q) use ($filters) {
  $q->where('type_id', $filters['typeId'])
    ->whereHas('address', function ($q) use ($filters) {
      $q->where('id', $filters['addressId'])

        // both below wheres don't make sense used together, just an example
        ->where('province_id', $filters['provinceId'])
        ->where('country_id', $filters['countryId']);
    });
});

它将设置 2 个连接并检查那些 where 子句,因此您将只获取那些满足要求的帖子,但这里没有任何内容是预先加载的(with 用于预先加载,但它不过滤主模型,只有那些急切加载的)。

【讨论】:

  • 使用$q->where(..)->orWhereHas( .. ) 可以工作吗?即,orWhereHas 是合法的结构吗?我假设我必须随后调用$posts->get() 才能获得结果集?
  • 是的,orWhereHas 是正确的,是的,你当然需要get 来执行查询。
【解决方案2】:

假设您已经为profile 定义了address 的关系,

$posts = Posting::with([
    'profile' => function($query) use ($type_id)
    {
        $query->whereTypeId($type_id)
    },
    'profile.address' => function($query) use ($country_id, $province_id)
    {
        $query->whereCountryId($country_id)
              ->whereProvinceId($province_id);
    }
])->get();

【讨论】:

  • 是的,我在 Profile.php 中定义了这个:public function address() { return $this->belongsTo('Address'); } 不幸的是 $posts 仍然未定义。啊。
  • 这可能是因为数据库中没有匹配项?
  • 不错的一个。不,只有两条记录。我确定符合任一条件的标准。
  • 这确实很有趣。好的。尝试一步一步地做到这一点。只检查type_id 重写上面的语句。看看这是否会返回任何东西。如果是,则添加profile.address
  • 我的视图文件中有错误。更正后,我现在一直都能得到所有结果。也就是说,没有发生过滤。嗯。
猜你喜欢
  • 2020-04-18
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 2015-02-17
  • 2021-11-07
  • 2021-08-23
  • 1970-01-01
相关资源
最近更新 更多