Laravel 从查询 eloquent 结果中排除当前 id
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37738175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel exclude current id from query eloquent results
提问by Cruzito
I am fairly new to laravel and I built a little "similar posts" section. So every post has a tag and I query all the id's from the current tag. And then I find all the posts with thoses id's. Now my problem is that the current post is always included. Is there an easy way to exclude the current id when querying?
我对 laravel 相当陌生,我建立了一个“类似帖子”部分。所以每个帖子都有一个标签,我从当前标签中查询所有 id。然后我找到了所有带有这些 ID 的帖子。现在我的问题是始终包含当前帖子。查询时是否有一种简单的方法可以排除当前 id?
I can't seem to find anything in the helper function on the laravel docs site
我似乎在 laravel 文档站点上的辅助函数中找不到任何内容
this is my function:
这是我的功能:
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]);
}
回答by EricDS
An easy way to solve your issue would be to use the Relationship
method directly instead of referring to it by property, which you can add additional filters just like any eloquent transaction.
解决您的问题的一种简单方法是Relationship
直接使用该方法,而不是通过属性引用它,您可以像任何 eloquent 事务一样添加额外的过滤器。
In other words, you would need to replace this:
换句话说,你需要替换这个:
Tag::find($tag_ids)->projects
With this:
有了这个:
Tag::find($tag_ids)->projects()->where('id', '!=', $id)->get()
Where $id
is the current project's id. The reason behind this is that by using the method projects()
, you are referring your model's defined Relationship
directly (most probably a BelongsToMany
, judging by your code) which can be used as a Query Builder (just as any model instance extending laravel's own Eloquent\Model
).
$id
当前项目的 id在哪里。这背后的原因是,通过使用 method projects()
,您将Relationship
直接引用您的模型定义(最有可能是 a BelongsToMany
,根据您的代码判断),它可以用作查询构建器(就像任何扩展 laravel 自己的模型实例一样Eloquent\Model
)。
You can find more information about laravel relationships and how the Query Builder works here:
您可以在此处找到有关 Laravel 关系以及查询生成器如何工作的更多信息:
However, the way you are handling it might cause some issues along the way.
但是,您处理它的方式可能会导致一些问题。
From your code i can assume that the relationship between Project
and Tag
is a many to manyrelationship, which can cause duplicate results for projects sharing more than 1 tag (just as stated by user Ohgodwhy).
从您的代码中,我可以假设Project
和之间的关系Tag
是多对多关系,这可能会导致共享超过 1 个标签的项目出现重复结果(正如用户Ohgodwhy 所述)。
In this type of cases is better to use laravel's whereHas()
method, which lets you filter your results based on a condition from your model's relation directly (you can find more info on how it works on the link i provided for eloquent-relationships). You would have to do the following:
在这种情况下,最好使用 laravel 的whereHas()
方法,它可以让您根据模型关系中的条件直接过滤结果(您可以在我为 eloquent-relationships 提供的链接上找到有关它如何工作的更多信息)。您必须执行以下操作:
// 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();
That way you can exclude your current Project while avoiding any duplicates in your result.
这样您就可以排除当前项目,同时避免结果中出现任何重复项。
回答by Ohgodwhy
I don't think that Tag::find($tag_ids)->projects
is a good way to go about this. The reason being is that multiple tags may belong to a project and you will end up getting back tons of project queries that are duplicates, resulting in poor performance.
我不认为这Tag::find($tag_ids)->projects
是解决这个问题的好方法。原因是多个标签可能属于一个项目,您最终会得到大量重复的项目查询,从而导致性能不佳。
Instead, you should be finding all projects that are not the existing project. That's easy.
相反,您应该找到不是现有项目的所有项目。这很容易。
$related_projects = Project::whereNotIn('id', [$project->id])->with('tags')->get();
Also you could improve your code by using Dependency Injection
and Route Model Binding
to ensure that the Model is provided to you automagically, instead of querying for it yourself.
您还可以通过使用Dependency Injection
并Route Model Binding
确保自动向您提供模型来改进您的代码,而不是自己查询它。
public function show(Project $project)
Then change your route to something like this (replacing your controller name with whatever your controller is:
然后将您的路线更改为这样的内容(用您的控制器名称替换您的控制器名称:
Route::get('/projects/{project}', 'ProjectController@show');
Now your $project
will always be available within the show
function and you only need to include tags
(which was performed in the "with" statement above)
现在您$project
将始终在show
函数中可用,您只需要包含tags
(在上面的“with”语句中执行)