【问题标题】:Laravel exclude current id from query eloquent resultsLaravel 从查询 eloquent 结果中排除当前 id
【发布时间】:2016-06-10 00:23:48
【问题描述】:

我对 laravel 还很陌生,我建立了一个小的“类似帖子”部分。所以每个帖子都有一个标签,我从当前标签中查询所有 id。然后我找到所有带有这些 id 的帖子。现在我的问题是始终包含当前帖子。查询时有没有简单的方法可以排除当前id?

我似乎在 laravel 文档网站的帮助函数中找不到任何内容

这是我的功能:

public function show($id)
    {
       $project = Project::findOrFail($id);

        foreach ($project->tags as $tag){
            $theTag = $tag->name;
        }

        $tag_ids = DB::table('tags')
            ->where('name', "=", $theTag)
            ->value('id'); 

        $similarProjects = Tag::find($tag_ids)->projects;

       return view('projects.show', ['project' => $project, 'similarProjects' => $similarProjects]);
   }

【问题讨论】:

    标签: php mysql laravel eloquent


    【解决方案1】:

    解决您的问题的一种简单方法是直接使用Relationship 方法,而不是通过属性引用它,您可以像任何雄辩的事务一样添加额外的过滤器。

    换句话说,你需要替换这个:

    Tag::find($tag_ids)->projects
    

    有了这个:

    Tag::find($tag_ids)->projects()->where('id', '!=', $id)->get()
    

    $id 是当前项目的 ID。这背后的原因是,通过使用方法projects(),您直接引用了您的模型定义的Relationship(很可能是BelongsToMany,根据您的代码判断),它可以用作查询构建器(就像任何模型一样实例扩展 laravel 自己的 Eloquent\Model)。

    您可以在此处找到有关 laravel 关系以及查询构建器如何工作的更多信息:

    但是,您处理它的方式可能会导致一些问题。

    从您的代码中,我可以假设ProjectTag 之间的关系是多对多 关系,这可能会导致共享多个标签的项目重复结果(正如所述用户Ohgodwhy)。

    在这种情况下,最好使用 laravel 的 whereHas() 方法,它可以让您根据模型关系中的条件直接过滤结果(您可以在我为 eloquent 提供的链接上找到有关它如何工作的更多信息——关系)。您必须执行以下操作:

    // Array containing the current post tags
    $tagIds = [...];
    
    // Fetch all Projects that have tags corresponding to the defined array 
    Project::whereHas('tags', function($query) use ($tagIds) {
        $query->whereIn('id', $tagIds);
    })->where('id', !=, $postId)->get();
    

    这样您可以排除当前项目,同时避免结果中出现任何重复。

    【讨论】:

    • 非常感谢朋友!因此,如果我理解正确,如果我使用此代码:Tag::find($tag_ids)->projects()->where('id', '!=', $id)->get() 只要我每个项目只选择 1 个标签,它就不会出错?
    • 是的,没错,因为多个标签会返回一个Collection,它不会有关系方法。很高兴它有帮助。
    【解决方案2】:

    我不认为Tag::find($tag_ids)->projects 是解决这个问题的好方法。原因是多个标签可能属于一个项目,您最终会得到大量重复的项目查询,从而导致性能不佳。

    相反,您应该找到所有不是现有项目的项目。这很容易。

    $related_projects = Project::whereNotIn('id', [$project->id])->with('tags')->get();
    

    您还可以通过使用Dependency InjectionRoute Model Binding 来改进您的代码,以确保模型自动提供给您,而不是自己查询。

    public function show(Project $project)
    

    然后将您的路线更改为类似的内容(将您的控制器名称替换为您的控制器名称:

    Route::get('/projects/{project}', 'ProjectController@show');
    

    现在您的$project 将始终在show 函数中可用,您只需要包含tags(在上面的“with”语句中执行)

    【讨论】:

    • 对不起,因为我对 laravel 很陌生,所以我不太明白你想说什么 :)
    猜你喜欢
    • 1970-01-01
    • 2018-06-14
    • 2020-09-24
    • 2018-10-22
    • 2021-10-26
    • 2019-12-24
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多