【问题标题】:How to group one to many relationships with join in Laravel如何在 Laravel 中通过 join 对一对多关系进行分组
【发布时间】:2017-02-16 10:31:05
【问题描述】:

我正在使用 Laravel 5.3 并尝试使用连接从多个表中返回数据。

我正在使用 3 个模型/表,客户、业务和网站,它们的相关性如下:

在 Customer.php 中:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
  public function businesses()
  {
    return $this->hasMany('App\Business');
  }
}

在 Business.php 中:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Business extends Model
{
  public function customer() 
  {
    return $this->belongsTo('App\Customer');
  }

  public function websites()
  {
    return $this->hasMany('App\Website');
  }
}

在 Website.php 中:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Website extends Model
{  
  public function business() {
    return $this->belongsTo('App\Business');
  }
}

所以Customer 可以有很多Businesses,而Websites 可以有很多Websites。 现在我正在尝试使用 join 语句返回客户列表及其相关业务和网站信息。我正在使用以下代码返回此信息:

$customers = \DB::table('customers')
                ->join('businesses', 'customers.id', '=', 'businesses.customer_id')
                ->join('websites', 'businesses.id', '=', 'websites.business_id')
                ->select('customers.x', 'businesses.y', 'websites.z')
                ->get();

我希望数据以关联客户数组的数组返回,业务和网站数据嵌套在关联数组中,如下所示:

[
  0 => {
    $customer1Data,
    $customer1BusinessData,
    $customer1WebsiteData
  }
  1 => {
   $customer2Data,
   $customer2BusinessData,
   $customer2WebsiteData
  }
  ...
]

如果客户有一个企业有一个网站,但假设 $customer1 有两个企业,那么上面的连接会以这种格式返回一些东西:

[
  0 => {
    $customer1Data,
    $customer1BusinessData1,
    $customer1WebsiteData
  }
  1 => {
   $customer1Data,
   $customer1BusinessData2,
   $customer1WebsiteData
  }
  ...
]

有没有办法可以修改连接语句以这种格式返回该场景:

[
  0 => {
    $customer1Data,
    businesses => {
      $customer1BusinessData1,
      $customer1BusinessData2
    }
    ...
  }
] 

有没有办法通过连接语句实现这一点?或者我应该以不同的方式解决这个问题?任何帮助将不胜感激,非常感谢。

【问题讨论】:

  • 你还没有完全使用雄辩。您可以只使用 ` $customer = Customer::with('business', 'business.websites')->all() ` 这将加载所有客户及其业务及其网站。所以你可以简单地使用`$customer->business`来获取所有的业务和一个嵌套循环来获取企业的网站。

标签: php mysql laravel eloquent


【解决方案1】:

在我深入解释雄辩的模型关系之前,请阅读以下内容:https://laravel.com/docs/5.4/eloquent。这样就可以解决问题了。

在模型关系中,您可以指定将这两个表链接在一起的数据库字段名称。这甚至适用于数据透视表。有关基本文档,请阅读:https://laravel.com/docs/5.4/eloquent-relationships#defining-relationships

例如在客户模型中:

public function businesses() 
{
    return $this->hasMany(Business::class, 'id', 'customer_id');
}

public function websites()
{
    //Argument order: final class, pivot class, pivot foreign key, foreign key final model, primary key start model (customer)
    return $this->hasManyThrough(Website::class, Business::class, 'customer_id', 'id', id);
}

如果最后一部分有点难以理解,请阅读文档:https://laravel.com/docs/5.4/eloquent-relationships#has-many-through

对于商业模式:

public function website()
{
    return $this->hasMany(Website::class, 'id', 'business_id');
}

现在您可以使用 eloquent 检索数据了。

//This will retrieve all customers with all of their website information.
Customer::with('websites')->get();

//This will retrieve all customers with their business information.
Customer::with('businesses')->get();

//This will retrieve all customers with business and website information
//Retrieves: [ 
//    customer: [ 
//        customerDetails: [] 
//        businesses: [ b1, b2], 
//        websites: [w1, w2]
//    ]
//]
Customer::with('businesses', 'websites')->get();

//This will retrieve all customers with business information and the website information for each business
//Retrieves: [ 
//    customer: [ 
//        customerDetails: [] 
//        businesses: [ 
//            b1: [ websites: [w1] ],
//            b2: [ websites: [w2] ]
//        ], 
//    ]
//]
Customer::with('businesses.websites')->get();

我希望这会有所帮助!

【讨论】:

  • 如果在 ->get() 中放置一个键值数组,则可以指定要检索的列。不要忘记表名!
【解决方案2】:

根据@Rooshan Akthar 的评论,由于您创建的关系,您可以使用 eloquent 执行以下操作之一:

// Loading with relationships (i.e single query)
Customer::with('businesses.websites');

// Lazy loading (i.e. multiple queries)
Customer::find($id)->load('businesses.websites');

你也可以直接去$customer-&gt;businesses-&gt;websites;而不用调用上述任何一个,laravel 会为你获取这些关系。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-02
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多