Has many through many-to-many



我有以下表格布局:

deals:
- id
- price
products:
- id
- name
deal_product:
- id
- deal_id
- product_id
metrics:
- id
- name
metric_product:
- id
- metric_id
- product_id
- value

productsmetrics与值的透视列具有多对多关系。

dealsproducts也有多对多关系。

我可以获取具有$product->metrics的产品的指标,但我希望能够获取与交易相关的所有产品的所有指标,因此我可以执行以下操作:$deal->metrics

我目前在我的Deal模型中有以下内容:

public function metrics()
{
$products = $this->products()->pluck('products.id')->all();
return Metric::whereHas('products', function (Builder $query) use ($products) {
$query->whereIn('products.id', $products);
});
}

但这不会返回关系,所以我不能急于加载它或从中获取相关模型。

它需要采用关系格式,因为它们需要为我的用例急于加载。

感谢您的帮助!

如果你想有一个自定义的关系,你可以创建你自己的扩展到关系抽象类。例如:BelongsToManyThought.

但是如果你不想实现一个关系,我认为它可以满足你的需求:

在App\Deal.php中,可以组合@thomas-van-der-veen的解决方案

public function metrics()
{
return Metric
::join('metric_product', 'metric.id', '=', 'metric_product.metric_id')
->join('products', 'metric_product.product_id', '=', 'products.id')
->join('deal_product', 'products.id', '=', 'deal_product.product_id')
->join('deals', 'deal_product.deal_id', '=', 'deal.id')
->where('deal.id', $this->id);
}

// you can access to $deal->metrics and use eager loading
public function getMetricsAttribute()
{
if (!$this->relationLoaded('products') || !$this->products->first()->relationLoaded('metrics')) {
$this->load('products.metrics');
}
return collect($this->products->lists('metrics'))->collapse()->unique();
}

您可以参考这篇文章,了解如何简单地使用嵌套关系。

此解决方案可以完成查询与方法的关系和对指标属性的访问的技巧。

有一个 Laravel 5.5 作曲家包,可以执行多级关系(深度)

包: https://github.com/staudenmeir/eloquent-has-many-deep

例:

User→属于许多→Role→属于许多→Permission

class User extends Model
{
use StaudenmeirEloquentHasManyDeepHasRelationships;
public function permissions()
{
return $this->hasManyDeep(
'AppPermission',
['role_user', 'AppRole', 'permission_role'], // Pivot tables/models starting from the Parent, which is the User
);
}
}

需要定义外键的示例:

https://github.com/staudenmeir/eloquent-has-many-deep/issues/7#issuecomment-431477943

我没有足够的代表发表评论,所以我会发布一个答案。

几天前,我发布了一个类似的问题,并且能够自己回答。我认为解决方案也适用于这个问题。

通过手动联接表并添加 where 子句,您可以检索所需的指标。

可能的解决方案:

// Deal.php
public function metrics()
{
return Metric
::join('metric_product', 'metric.id', '=', 'metric_product.metric_id')
->join('products', 'metric_product.product_id', '=', 'products.id')
->join('deal_product', 'products.id', '=', 'deal_product.product_id')
->join('deals', 'deal_product.deal_id', '=', 'deal.id')
->where('deal.id', $this->id);
}
// How to retrieve metrics
$deal->metrics()->get();
// You can still use other functions like (what I needed) pagination
$deal->metrics()->paginate(24);
// Or add more where clauses
$deal->metrics()->where(blablabla)->get();

希望这对:)有所帮助

@ntzm评论后编辑

如果您只需要指标表的某些属性而不需要模型功能,则可以在连接之前添加 select('*')。

喜欢这个:

return Metric
::select('*')
->join(...........

它将返回一个指标模型,其中包含联接表的所有属性。

此示例将返回一个对象,如下所示:

Metric (
....
attributes: [
id => 0, // From metrics table
name => 'somename', // Metrics table
metric_id => 0, // metric_product table
product_id => 0, // metric_product table
....
]
....
)

由于有很多同名的列,您将无法访问这些值。但是,您可以多次选择和重命名结果中的列。

喜欢这个:

retrun Metric
::select([
*,
DB::raw('products.name as product_name'),
....
])
->join(....

这将导致类似以下内容:

Metric (
....
attributes: [
id => 0, // From metrics table
name => 'somename', // Metrics table
metric_id => 0, // metric_product table
product_id => 0, // metric_product table
product_name => 'somename' // products table
....
]
....
)

我希望这将解决一些:)当然,有更干净的方法来解决您的问题。

这应该可以解决问题:

型号/产品.php文件:

class Product extends Model
{
public function deals()
{
return $this->belongsToMany(Deal::class);
}
public function metrics()
{
return $this->belongsToMany(Metric::class);
}
}

模型/交易.php文件:

class Deal extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
}

模型/指标.php文件:

class Metric extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
}

从控制器:

class ExampleController extends Controller
{
public function index()
{
$deal = Deal::with('products.metrics')->get();
}
}

现在,您拥有一系列产品交易及其相关指标。有关嵌套的预先加载,请参阅文档。

如果有人仍然需要它:

首先,您将渴望加载产品和指标

$deals->with('products.metrics');

在交易模型中

public function getMetricsAttribute(){
return $this->products->pluck('metrics')->collapse();
}

现在,您可以通过以下方式获取交易产品的所有指标:

$deal->metrics

没有可用的"多对多通过"方法。

要获取特定交易的所有产品中可用的所有指标,请创建一个 getter 以预先加载交易的所有产品和指标,并利用 Laravel 的集合方法。

Deal模型中:

public function products()
{
return $this->belongsToMany('AppProduct');
}
public function getMetrics()
{
return $this->products->lists('metrics')->collapse()->values();
}

然后,您可以获取"交易"的指标$deal->getMetrics()

这将返回指标对象的集合,该对象应该正是您要查找的对象。

如果有人仍在研究这个,请查看我最近开发的这个软件包。它为您提供了belongsToManyThrough()关系,并且非常易于安装和使用:)

https://github.com/shomisha/unusual-relationships

相关内容

  • 没有找到相关文章

最新更新