我正在尝试找出过滤此查询的最佳方法,我尝试了一些不同的方法,但无法找到可靠的解决方案。
本质上,我们有一个通用查询,它可以完全满足其需要,问题是我需要能够过滤答案表上的用户输入。
$profiles = User::with('photos', 'answers')
->where('id', '!=', $user_id)
->where('gender', $gender)
->where('location', $location)
->where('deleted_at', null)
->whereNotExists(function($query) use ($user_id)
{
$query->select(DB::raw('user_id1, user_id2'))
->from('approves')
->whereRaw("users.id = approves.user_id2 AND approves.user_id1 = '$user_id'");
})
->whereNotExists(function($query) use ($user_id)
{
$query->select(DB::raw('user_id1, user_id2'))
->from('likes')
->whereRaw("users.id = likes.user_id2 AND likes.user_id1 = '$user_id'");
})
->take(15)
->get();
使用几个用户输入来更改查询,现在用户还可以根据用户的个人资料答案按各种其他条件进行过滤,这就是我陷入困境的地方。
answers表的布局是id,user_id,question_id,answer必须是这样的,以便以后可以扩展。
有谁知道如何使用各种其他输入来过滤此内容,例如,如果用户按 Question_id '1' 进行过滤并回答 'awesome'。值得注意的是,有多个输入,而不仅仅是一个可供比较,并且仅需要在已输入的情况下进行比较。
任何想法或建议都非常感激:)
编辑:
id | user_id | question_id | answer
1 | 2 | 1 | dad
2 | 2 | 2 | lion
3 | 2 | 3 | 5
对于多个可能的问题/答案对,我将定义一个查询范围。现在这不是一个特别有效的查询,其他人可能有更好的答案,但这就是我要做的。
$profiles = User::with('photos', 'answers')
->where('id', '!=', $user_id)
->where('gender', $gender)
->where('location', $location)
->where('deleted_at', null)
->questionAnswer($questionAnswerArray)
->whereNotExists(function($query) use ($user_id)
{
$query->select(DB::raw('user_id1, user_id2'))
->from('approves')
->whereRaw("users.id = approves.user_id2 AND approves.user_id1 = '$user_id'");
})
->whereNotExists(function($query) use ($user_id)
{
$query->select(DB::raw('user_id1, user_id2'))
->from('likes')
->whereRaw("users.id = likes.user_id2 AND likes.user_id1 = '$user_id'");
})
->take(15)
->get();
然后在用户模型内部:
public function scopeQuestionAnswer($query, $qaArray)
{
foreach($qaArray as $question => $answer)
{
$query->whereHas('answers', function($query) use ($question, $answer)
{
$query->whereQuestionId($question)
->whereAnswer($answer);
});
}
return $query;
}
这使用了带有 where array($question => $answer) 的参数数组,但应该很容易修改为您希望传递它们的方式。
我测试了这种用法,效果很好,但我再次无法评价它的效率。如果您需要按所有正确的问题/答案对进行过滤,则该解决方案并不适用,您可以在范围函数中使用“orWhereHas”来过滤其中的任何一个。
<?php
namespace App\Http\Filters\V1;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
abstract class QueryFilter {
protected $builder;
protected $request;
protected $sortable = [];
public function __construct(Request $request)
{
$this->request = $request;
}
public function apply(Builder $builder) {
$this->builder = $builder;
foreach($this->request->all() as $key => $value) {
if (method_exists($this, $key)) {
$this->$key($value);
}
}
return $builder;
}
protected function filter($arr) {
foreach($arr as $key => $value) {
if (method_exists($this, $key)) {
$this->$key($value);
}
}
return $this->builder;
}
protected function sort($value) {
$sortAttributes = explode(',', $value);
foreach($sortAttributes as $sortAttribute) {
$direction = 'asc';
if (strpos($sortAttribute, '-') === 0) {
$direction = 'desc';
$sortAttribute = substr($sortAttribute, 1);
}
if (!in_array($sortAttribute, $this->sortable) && !array_key_exists($sortAttribute, $this->sortable)) {
continue;
}
$columnName = $this->sortable[$sortAttribute] ?? null;
if ($columnName === null) {
$columnName = $sortAttribute;
}
$this->builder->orderBy($columnName, $direction);
}
}
}