2014-09-02 62 views
0

我有3个模型:Shop,Products和Tags。商店和产品是一对多的关系,产品可以标签为多对多。Laravel Eloquent ORM - 通过另一个对象返回对象

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

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

回答

1

@狼人的方法将为你工作,但这里有一个技巧,将适用于所有的关系:

$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关系,但显然你不依赖于此。

+0

更好的解决方案 – 2014-09-02 22:48:22

+0

是的,值得注意的是:它执行额外的查询来获取这些标签。这是缺点,但它仍然是实现你所需要的最简单的解决方案。 – 2014-09-02 22:51:42

1

也许你可以试试这个:

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

这将返回所有绑定到任何ProductTags。如果必要的话,你也可以使用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; 
} 
+0

我想获得属于特定商店的唯一标签..有一个模型 – 2014-09-02 18:44:30

+0

检查更新的答案。 – 2014-09-02 19:02:34

+0

很棒的工作,非常感谢。这是我一直在寻找 – 2014-09-02 22:34:29