Laravel嵌套关系

daolsyd0  于 2023-04-07  发布在  其他
关注(0)|答案(8)|浏览(145)

在laravel中,我很难让一个非常嵌套的关系正常工作。
所需的行为如下,

**我通过ID选择一个事件,我想看看哪些人订阅了它。**现在的问题是事件和人之间有一些表。

这是有效的查询!

SELECT persons.id, 
       persons.firstname, 
       persons.lastname, 
       event_scores.score 
FROM   events 
       JOIN cities 
         ON cities.id = events.city_id 
       JOIN companies 
         ON cities.id = companies.city_id 
       JOIN persons 
         ON companies.id = persons.company_id 
       JOIN event_scores 
         ON event_scores.person_id = persons.id 
WHERE  event_scores.event_id = 1 
GROUP  BY persons.id

这些是我的亲戚

事件模型

class Event extends Eloquent
{
    protected $table = 'events';

    public function city()
    {
        return $this->belongsTo('City');
    }
}

城市模型

class City extends Eloquent
{
    protected $table = 'cities';

    public function companies()
    {
        return $this->hasMany('Company');
    }

    public function event()
    {
        return $this->hasMany('Event');
    }
}

公司模型

class Company extends Eloquent {

    protected $table = 'companies';

    public function persons()
    {
        return $this->hasMany('Person');
    }

    public function city()
    {
        return $this->belongsTo('City');
    }
}

人员模型

class Person extends Eloquent
{
    protected $table = 'persons';

    public function company()
    {
        return $this->belongsTo('Company');
    }

    public function eventscore()
    {
        return $this->belongsToMany('Event', 'event_scores', 'person_id', 'event_id')
            ->withPivot('score')
            ->withTimestamps();
    }
}

我所尝试的

return Event::with('city')->with('company')->get();

return Event::with('city')
    ->whereHas('companies', function($query) use ($company_id){
        $query->where('company_id', $company_id);
    })->get();

还有很多其他的可能性,我真的被这个卡住了。在laravel中实现这种嵌套关系链接有那么难吗?
谢谢!

3zwtqj6y

3zwtqj6y1#

return Event::with('city.companies.persons')->get();

如果您只想从persons表中选择某些字段,请使用以下命令:

return Event::with(['city.companies.persons' => function ($query) {
    $query->select('id', '...');
}])->get();
bd1hkmkf

bd1hkmkf2#

对于城市和公司的具体领域,你需要分发与雄辩。例如:

return Event::with([
    'city' => function ($query) {
        $query->select('id', '...');
    },
    'city.companies' => function ($query) {
        $query->select('id', '...');
    },
    'city.companies.persons' => function ($query) {
        $query->select('id', '...');
    }
])->get();

请注意,在嵌套的层次中(至少是中层),你必须指定FK到父关系,否则你会得到空集合的嵌套关系!我花了几个小时才弄明白这一点。

62lalag4

62lalag43#

return Event::with(['city:id,name', 'city.companies:id,name', 'city.companies.persons:id,name'])->get();

请注意,在嵌套的层次中(至少是中层),你必须指定FK到父关系,否则你会得到空集合的嵌套关系!我花了几个小时才弄明白这一点。

chhkpiq4

chhkpiq44#

对于事件模型中的两个级别

public function cities()
{
    return $this->belongsToMany(City::class)->with('companies');
}
0sgqnhkj

0sgqnhkj5#

我为这样的情况创建了一个HasManyThrough关系:Repository on GitHub
安装后,您可以像这样使用它:

class Event extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function persons() {
        return $this->hasManyDeep(
            Person::class,
            [City::class, Company::class],
            ['id'],
            ['city_id']
        );
    }
}

您可以使用withIntermediate()从中间表中获取属性:

public function persons() {
    return $this->hasManyDeep(
        Person::class,
        [City::class, Company::class],
        ['id'],
        ['city_id']
    )->withIntermediate(City::class, ['id', '...']);
}
bqucvtff

bqucvtff6#

为了扩展@ rashmi-nalwaya的答案,我在一个5. 8的项目中做了一些调整。
我的例子有点不同,因为我试图引用hasOne关系,而不是hasMany。
因此,作为参考,域名属于一个网站,属于一个服务器。我只想从所有这些表中返回某些列。我必须这样做。

Domain::with([
    'website' => function($q){
        $q->select('id', 'server_id');
    },
    'website.server' => function($q){
        $q->select('id', 'hostname', 'nickname');
    }
])
    ->select('id', 'website_id', 'domain')
    ->get();

必须确保我在任何时候都传递了我所在的表的主键(在我的例子中是id),其次,我试图访问的相关表的外键。因此,来自域的website_id和来自网站的server_id。然后它就完美地工作了。
在我的代码中,我在主域上还有一个where子句,在所有这些with-ness之后。

2skhul33

2skhul337#

下面是我的项目代码,我在其中使用了这个。

Checkout::where('cart_number', $cart_number)->with('orders.product')->first();

结果:

"id": 23,
  "user_id": 4,
  "cart_number": "20219034",
  "phone_number": null,
  "mobile": "01533149024",
  "alternate_phone": "01533149024",
  "country_id": 19,
  "state_id": 750,
  "city_id": 8457,
  "address": "272/1-B, West Nakhalpara,Tejaon,Dhaka",
  "postal_code": "1215",
  "note": "dasd",
  "total": 974,
  "payment_type": "pending",
  "payment_status": 0,
  "courier_id": 3,
  "delivery_status": 0,
  "commented_by": null,
  "rating": null,
  "review": null,
  "coupon_code": null,
  "coupon_status": null,
  "created_at": "2021-10-09T14:59:46.000000Z",
  "updated_at": "2021-10-09T15:33:35.000000Z",
  "orders": [
    {
      "id": 32,
      "user_id": 4,
      "checkout_id": 23,
      "product_id": 2,
      "cart_number": 20219034,
      "courier_id": 3,
      "order_number": "202190340",
      "price": "554",
      "quantity": "1",
      "payment_type": "cod",
      "delivery_status": "pending",
      "created_at": "2021-10-09T14:59:46.000000Z",
      "updated_at": "2021-10-09T14:59:46.000000Z",
      "product": {
        "id": 2,
        "name": "Jasmine Bowers",
        "slug": "jasmine-bowers",
        "media_link": null,
        "description": null,
        "regular_price": 905,
        "sale_price": 554,
        "sku": "32312312",
        "have_stock": 1,
        "stock_quantity": 312,
        "stock_alert_quantity": 50,
        "weight": 5,
        "shipping_class_id": 1,
        "downloadable_file": null,
        "download_limit": null,
        "download_expiry": null,
        "short_description": null,
        "category": "[\"1\"]",
        "brand": 1,
        "tags": "[\"praesentium exceptur\"]",
        "product_image": "http://localhost/Bajaar/media/logo.png",
        "color": "[\"green\"]",
        "size": "[\"fugiat proident del\"]",
        "model": "[\"molestiae quia aute\"]",
        "other": "[\"corrupti enim illo\"]",
        "draft": 1,
        "uploaded_by": 1,
        "created_at": "2021-07-12T20:39:41.000000Z",
        "updated_at": "2021-07-12T20:39:41.000000Z"
      }
    }
ctehm74n

ctehm74n8#

这是一个问题,许多开发人员将遇到,为这一目的;您可以在whereRelation子句中链接关系来模拟连接,例如

Payment::query()->whereRelation('orders.users',auth()->id());

关系可以继续用点表示法嵌套。希望它能节省你的时间。

相关问题