【问题标题】:Laravel 4 filter relationshipLaravel 4过滤器关系
【发布时间】:2013-06-24 05:57:42
【问题描述】:

我有“examples”表、“tags”表和中间“examples_has_tags”表。所以一个例子可以有一些标签,一个标签可以属于一些例子。

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

更新2

尝试在没有 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();

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

【问题讨论】:

  • 我的替代方法(in_array)怎么样,你能检查一下吗?
  • 没用,$example->tags->toArray() 不仅返回 array("tagName1", "tagName2"...) 所以......我尝试了 array_pluck 但没有成功(不知道为什么 id 对我不起作用)。
  • 您的解决方案有效吗?

标签: php laravel laravel-4 eloquent


【解决方案1】:

你应该做的是创建一个连接,然后在你想要的东西上创建一个 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();

可能有(并且可能有)更有效的方法来做到这一点,但这是我的做法。

【讨论】:

  • 我的解决方案怎么样(我更新了我的帖子)?好像行得通
  • 是的,您的解决方案应该可以工作。但是,有区别。您正在使用 PHP 进行过滤。这比 DB 引擎慢,因为它没有为此进行优化。此外,您正在将所有示例提取到您的脚本中,然后开始过滤。想象一下拥有一个包含 1.000.000 条记录的数据库......它会变得非常慢。如果您让数据库引擎进行过滤,您就不会(真的)遇到这个问题。
  • 我猜你是对的,但是我怎样才能得到每个例子的标签列表呢?在我的帖子中查看 update2。由于我仅按一个标签进行过滤,因此我稍微更改了查询,并且我不使用 DB::raw,因为它没有它就可以工作。我得到了正确的示例,但是当我遍历它们时,我尝试显示每个示例的标签列表(例如 @foreach($example->tags as $tag),标签数组为空...
【解决方案2】:

你可以这样做(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;
});

【讨论】:

  • 据我所知,我将获得所有示例,并且在每个示例中我都会过滤标签。但这不是我想要得到的 - 我想过滤示例列表本身。我想我已经尝试过您的解决方案,但我会在几个小时后检查,谢谢
  • 在我的帖子中查看我的解决方案(我更新了它)。好像行得通
猜你喜欢
  • 2021-12-15
  • 1970-01-01
  • 2020-12-17
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 1970-01-01
  • 2021-08-07
相关资源
最近更新 更多