我有一个搜索功能,可以根据用户输入的过滤条件(年龄/年龄,身高/年龄)来搜索用户。问题是age列在users表(用户模型)中,height列在user_profiles表(UserProfile模型)中。我可以轻松地从每个模型获得结果,但是我希望在结合这两个条件时获取结果。例如,获取年龄在30至40岁之间且在180厘米至190厘米之间的用户。任何帮助表示赞赏。这是我的代码。
SearchController.php
class SearchController extends Controller
{
public function search(Request $request, User $user)
{
$query = User::query(); // HERE I NEED TO FETCH USER PROFILE COLUMNS FROM MODEL ALONG WITH USER
dd($query);
// HEIGHT SETTING
if ($request->has('from_cm')) {
$request->get('from_cm');
}
if ($request->has('to_cm')) {
$request->get('to_cm');
}
if ($request->from_cm && $request->to_cm) {
$query->whereBetween('height', [$request->from_cm, $request->to_cm]);
} elseif ($request->from_cm) {
$query->where('height', '>=', $request->from_cm);
} elseif ($request->to_cm) {
$query->where('height', '<=', $request->to_cm);
}
// AGE SETTING
if ($request->has('from_age')) {
$request->get('from_age');
}
if ($request->has('to_age')) {
$request->get('to_age');
}
if ($request->from_age && $request->to_age) {
$query->whereBetween('age', [$request->from_age, $request->to_age]);
} elseif ($request->from_age) {
$query->where('age', '>=', $request->from_age);
} elseif ($request->to_age) {
$query->where('age', '<=', $request->to_age);
}
$results = $query->get();
//dd($results);
}
}
User.php
protected $fillable = [
'username',
'email',
'first_name',
'last_name',
'age',
];
public function userProfile()
{
return $this->hasOne(UserProfile::class);
}
UserProfile.php
protected $fillable = [
'user_id',
'interested_in',
'height',
];
public function user()
{
return $this->belongsTo(User::class);
}
因此,需要明确的是,我不需要特定用户及其用户个人资料,而是将用户和用户个人资料模型中的列合并到一个变量中($ query)。
答案 0 :(得分:1)
据我了解,您需要类似以下查询:
$users = User::with('userProfile')
->whereBetween('age', [$minAge, $maxAge])
->whereHas('userProfile', function($query){
$query->whereBetween('height', [$minHeight, $maxHeight]);
});
这将使用年龄在$minAge
和$maxAge
之间且个人资料的高度在$minHeight
和$maxHeight
之间的个人资料获取所有用户。
编辑
如果您希望能够与文件管理器分别检索数据,那么您需要的是conditional clauses。代码如下所示:
$users = User::with('userProfile')
->when($ageFilterActive, function($query, $ageFilterActive) {
$query->whereBetween('age', [$minAge, $maxAge]);
})->when($heightFilterActive, function($query, $heightFilterActive) {
$query->whereHas('userProfile', function($query){
$query->whereBetween('height', [$minHeight, $maxHeight]);
});
});
我希望我不会弄乱语法,但是您明白了。另外,您可以通过扩展if-else
变量的$query
语句来实现相同的目的,但是我个人更喜欢Laravel优雅的when
语法。
答案 1 :(得分:1)
我将执行以下操作:
$user->filter($request->input('min_height'),$request->input('max_height'),$request->input('min_age'),$request->input('max_age'));
这样,控制器将负责将所需的数据传递到模型,然后您就可以在模型内部进行查询。
这样做的好处是
在您的用户模型中,查询将如下所示:
public function scopeWithUserProfile($query)
{
// Left join or inner join depends on your needs
return $query->join('user_profile', 'users.id', '=', 'user_profile.user_id');
}
public function filter($minHeight, $maxHeight, $minAge, $maxAge) {
$query = $this->query()
->withUserProfile();
if (!is_null($minHeight) && !is_null($maxHeight)) {
$query->whereBetween('height', [$minHeight, $maxHeight]);
}
if (!is_null($minAge) && !is_null($maxAge)) {
$query->whereBetween('age', [$minAge, $maxAge]);
}
return $query;
}
$query->get()
就是这样,我们可以在控制器中以及在每个
我们正在重用此代码,我们可以根据调用地方的需要来执行诸如orderBy
,groupBy
,first
,get
之类的操作。因为如果您进行$query->get()
,则只能使用Collection
。$query->get()
中执行类似的操作,然后从那里我们将收集所需的数据。在最后的控制器中,您必须具有类似的内容
public function search(Request $request, User $user)
{
$user->filter($request->input('min_height'),$request->input('max_height'),$request->input('min_age'),$request->input('max_age'));
return view('your.view.here', [
'userData' => $user->get(),
]);
}
我不知道解释是否足够清楚,但是只要我可以:P
我希望语法不错,但是您可以通过添加更多的If和else语句来根据需要过滤它们,从而满足您的需求。