Laravel Eloquent ORM-通过另一个对象返回对象


Laravel Eloquent ORM - return objects thru another objects

我有三种型号:商店、产品和标签。商店和产品是一对多的关系,产品与标签是多对多的。

我想为每个商店获取所有独特的标签(因为许多产品可以有相同的标签)。

class Shop extends Eloquent {
    public function products() {
        return $this->hasMany('Product');
    }
}

class Product extends Eloquent {
    public function shop() {
        return $this->belongsTo('Shop');
    }
    public function tags() {
        return $this->belongsToMany('Tag');
    }
}
class Tag extends Eloquent {
    public function products() {
        return $this->belongsToMany('Product');
    }
}

我想出的一个解决方案如下。问题是我没有唯一的标签。有一种解决方案是放置另一个foreach循环来遍历标记数组并比较标记对象中的id。我想优化一下,你认为什么是更好/更清洁的解决方案?

class Shop extends Eloquent {
    ...
    public function getTagsAttribute() {
        $tags = array();
        foreach($this->products as $product)
        {
            foreach ($product->tags as $tag)
            {
                $tags[] = $tag;
            }
        }
        return $tags;
    }
}

@WereWolf的方法对你有效,但这里有一个技巧对所有关系都有效:

$shop = Shop::with(['products.tags' => function ($q) use (&$tags) {
  $tags = $q->get()->unique();
}])->find($someId);
// then:
$tags; // collection of unique tags related to your shop through the products

请注意,每个$tags都将具有pivot属性,因为它是belongsToMany关系,但显然您不依赖于此。

也许你可以试试这个:

$tags = Tag::has('products')->get();

这将返回绑定到任何Product的所有Tags。如果有必要,你也可以使用distinct,就像这样,但我认为在这种情况下没有必要:

$tags = Tag::has('products')->distinct()->get();

更新:然后你可以尝试这样的东西:

public function getTagsAttribute()
{
    $shopId = $this->id;
    $tags = Tag::whereHas('products', function($query) use($shopId) {
        $query->where('products.shop_id', $shopId);
    })->get();
    return $tags;
}