我正在尝试显示一个产品页面,其中包含与特定资产类型匹配的资产列表。例如,对于产品“ Acme Cream”,有两个资产:Nutrition-facts.pdf(文档类型)和marketing-video.mp4(视频类型)。在产品页面上,我要显示与“视频”资产类型(如果有)匹配的第一项资产。
我有以下关系:
产品模型包括一个数据库列asset_id
。
class Product extends Model
{
/**
* The assets that belong to the product.
*/
public function assets()
{
return $this->belongsToMany('App\Asset', 'product_asset');
}
}
资产模型包括数据库列id
和asset_type_id
。
class Asset extends Model
{
/**
* Get the asset type that owns the asset.
*/
public function asset_type()
{
return $this->belongsTo('App\AssetType');
}
/**
* The products that belong to the asset.
*/
public function products()
{
return $this->belongsToMany('App\Product', 'product_asset');
}
}
AssetType模型具有两个数据库列id
和name
。
class AssetType extends Model
{
/**
* A asset type can have many assets
*/
public function assets()
{
return $this->hasMany('App\Asset');
}
}
如何通过对asset_type进行过滤来有效地获取一种产品资产?请记住,我已经使用Product :: find(id)查询数据库并将该数据传递到视图中。这是否需要另一个查询(急于加载可能对此有所帮助)。我知道我可以使用foreach
循环,但是在我看来,肯定有一种更好,更“雄辩”的方式。
在这种情况下,我想在产品详细信息页面( show.blade.php )上使用它(伪代码):
如果资产匹配类型为“视频”,则在此div中首先显示。否则,不要显示div。
似乎应该是一条简单的线:
$product->assets()->asset_type()->where('name', '=', 'Video')->first()
到目前为止,我最接近的是这件难看的东西:
>>> $product = App\Product::with(['assets'])->find(1)
>>> $product->assets()->with(['asset_type' => function ($query) { $query->where('name', '=', 'Video'); }])->get()
但是,它仍然返回所有资产,但对于不匹配的资产,“ asset_type”属性为null。添加->whereNotNull('asset_type')->get()
只会导致无法找到asset_type
列的错误。
另外,这听起来像是使用“ Has Many Through”关系的机会,但是我不清楚如何进行设置。
任何帮助将不胜感激!谢谢。
答案 0 :(得分:1)
您需要通过过滤来渴望加载您的关系:
假设您获取了与您的产品信息的关系
$typeName = 'Video';
$product = App\Product::with([
'asset' => function($query) use($typeName) {
//Filter asset by type
//See: https://laravel.com/docs/5.6/eloquent-relationships#constraining-eager-loads
return $query->whereHas('asset_type',function($query) use($typeName) {
//Filter where the type's name equals..
//Each query is relative to its scope, in this case the 'type' relationship which refers to your 'type' Model
return $query->where('name','=',$typeName);
});
},
//Nested relationship loading: https://laravel.com/docs/5.6/eloquent-relationships#querying-relations
'assets.asset_type'
])
->find(1);
$assets = $product->assets;
假设您仅提取资产
$productId = 1;
$typeName = 'Video';
//Returns a collection of eloquent models
$assets = Asset::whereHas('product',function($query) use ($productId) {
//Filter product by its id
return $query->where('id','=',$productId);
})
->whereHas('asset_type',function($query) use ($typeName) {
//Filter type by its name
return $query->where('name','=',$typeName);
})
->get();