【问题标题】:Laravel nested relationshipsLaravel 嵌套关系
【发布时间】:2014-10-27 00:50:53
【问题描述】:

我无法让非常嵌套的关系在 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中实现这种嵌套的关系链接有那么难吗?

谢谢!

【问题讨论】:

    标签: php mysql database laravel


    【解决方案1】:
    return Event::with('city.companies.persons')->get();
    

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

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

    【讨论】:

    • 哇!那太快了!甚至不知道这件事。是否也可以只选择我想要的字段?因为它现在回来了很多!非常感谢!
    • @MiguelStevens - 字段来自什么?人?
    • @MiguelStevens ...->get(array('column1', 'column2'...)); 详情为here
    • 如何获取城市和公司的选择性列?
    • 您好,$query->select('id', '...'); 返回最后一个 with 的字段。但是如何只返回链中的最后一个嵌套对象呢?
    【解决方案2】:

    对于城市和公司的特定领域,你需要用 eloquent 分发。 例如:

    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();
    

    【讨论】:

    • 如果我也需要在Event模型上传递条件怎么办?
    • 您可以在 get 方法之前调用 where 方法,也可以在顶级 with 方法之前调用它。跨度>
    • 似乎不起作用?可能是因为缺少方括号?
    • @RashmiNalwaya 多重链接对我不起作用……说如果我选择某些领域的城市,它工作正常,但如果我添加 city.companies,我得到的公司为空.. 知道为什么吗? ?
    • @arnaud-bochot 在 city.companies 关系中,请连同 id 一起选择外键/引用键。例如:city_id
    【解决方案3】:

    我为以下情况创建了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', '...']);
    }
    

    【讨论】:

      【解决方案4】:

      扩展@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 子句,毕竟这些都是有的。

      【讨论】:

        【解决方案5】:
        return Event::with(['city:id,name', 'city.companies:id,name', 'city.companies.persons:id,name'])->get();
        

        【讨论】:

          【解决方案6】:

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

          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"
                }
              }
          

          【讨论】:

            【解决方案7】:

            事件模型中的两个级别

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

            【讨论】:

            • 这对我有用,将一个对象及其子对象和孙子对象引入一个查询。
            【解决方案8】:

            为此,许多开发人员都会遇到这个问题; 您可以在 whereRelation 子句中链接关系以模仿连接,例如

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

            关系可以继续用点表示法嵌套。 希望它能帮您省去麻烦。

            【讨论】:

              猜你喜欢
              • 2021-07-19
              • 2019-06-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-02-20
              • 2021-08-05
              • 2020-11-22
              • 2017-03-02
              相关资源
              最近更新 更多