2013-06-24 115 views
0

我有“示例”表,“标记”表和中间的“examples_has_tags”表。所以一个例子可以有一些标签,一个标签可以属于一些例子。Laravel 4过滤关系

在index.php中,我显示了所有的例子和标签列表。

$examples = Example::with('tags')->where('public', true)->get(); 

$tags = Tag::all(); 

return View::make('index')->with('examples', $examples) 
          ->with('tags',  $tags); 

完美地工作。 但是,我怎样才能过滤标签名称的例子?我在stackoverflow上找到了一些东西:你应该在Example类中创建一个静态方法,它返回我需要的东西。但是我显示数据很麻烦。在上面的代码中,我将它显示为:

@foreach ($examples as $example) 
     <div class="widgetbox"> 
      <h4 class="widgettitle">{{ $example->name }}</h4> 
      <div class="widgetcontent"> 
       {{ $example->body }} 
       <div class="tags-list"> 
        @foreach ($example->tags as $tag) 
         <span class="label label-info tag">{{ $tag->name }}</span> 
        @endforeach 
       </div> 
      </div> 
     </div> 
    @endforeach 

有没有简单的方法来做到这一点?我发现了一些有关筛选集合,但没有例子

更新

我找到了一个解决方案:

$examples = $examples->filter(function($example) { 
     $tags = $example->tags->toArray(); 
     foreach ($tags as $tag) { 
      if ($tag["name"] == Input::get('tag')) return true; 
     } 
     return false; 
    }); 

UPDATE2

试图做到这一点没有PHP过滤,但我不能得到属于一个例子的标签:

$tagId = Tag::where('name', '=', Input::get('tag'))->first()->id; 

     $examples = Example::with('tags') 
          ->join('examples_has_tags', 'examples_has_tags.example_id', '=', 'examples.id') 
          ->where('examples_has_tags.tag_id', '=', $tagId)->get(); 

$例子不包含标签列表(它实际上是空的)

+0

我的替代(in_array)方法怎么样,请您检查一下吗? –

+0

没有工作,$ example-> tags-> toArray()不仅返回数组(“tagName1”,“tagName2”...)所以...我试过array_pluck但没有成功(不知道为什么id didn不为我工作)。 – Victor

+0

您的解决方案是否正常工作? –

回答

0

如下(Eager Loading

型号你可以这样做:(例)

class Example extends Eloquent { 
    public function tags() 
    { 
     return $this->hasMany('Tag'); 
    } 
} 

现在查询:

$examples = Example::with(array('tags' => function($query) 
{ 
    $query->where('name', '=', 'someName'); 
}))->get(); 

更新:

$examples = $examples->filter(function($example) { 
    $tags = $example->tags->toArray(); 
    return in_array(Input::get('tag'), $tags) ?: FALSE; 
}); 
+0

据我所知,我会得到所有的例子,在每个例子中,我将过滤标签。但这不是我想要得到的 - 我想过滤示例列表本身。我想我已经尝试了你的解决方案,但我会在几个小时内检查,谢谢 – Victor

+0

也许我误解了,反正,欢迎:-) –

+0

在我的文章(我更新了)看看我的解决方案。似乎它的工作 – Victor

0

你应该做的是创建一个连接,然后创建你想要的东西where子句。根据您希望如何通过标签筛选,你可以做这样的事情:

首先提取有效标签ID:

$tagIDs = array_pluck(Tag::whereIn('name', array(
    'tag1', 
    'tag2', 
    'tag3', 
))->toArray(), 'id'); 

然后通过TAG_ID过滤的例子:

return Example::select('examples.*') 
    ->join('examples_has_tags', 'examples.id', '=', DB::raw('examples_has_tags.example_id')) 
    ->whereIn(DB::raw('examples_has_tags.tag_id'), $tagIDs) 
    ->get(); 

有可能(也可能是)这样做的更有效的方法,但这是我如何接近它。

+0

我的解决方案呢(我更新了我的文章)?似乎它的工作 – Victor

+1

是的,这个你的解决方案应该工作。但是,有一个区别。你正在使用PHP进行过滤。这比数据库引擎慢,因为它没有被优化来做到这一点。 此外,您将所有示例提取到脚本中,然后再开始过滤。想象一下拥有一个拥有1.000.000记录的数据库......它会变得非常缓慢。如果让数据库引擎执行过滤,则不会(真的)出现此问题。 – DerLola

+0

我想你是对的,但是我怎样才能得到每个例子的标签列表?看看我的帖子update2。由于我只用一个标签进行过滤,因此我略微更改了查询,并且不使用DB :: raw,因为它没有这个工作。我得到正确的例子,但当我循环他们,我尝试显示每个示例的标签列表(如@foreach($ example->标签为$标签)标签数组为空...... – Victor