我有一个搜索功能,可以根据用户输入的过滤器(从/到年龄,从/到身高)搜索用户。 问题是年龄列在users表(User model)中,而身高列在user_profiles表(UserProfile model)中。 我可以从每个模型中单独地获得结果,但是我想在将这两个条件结合起来时获得结果。 例如,获取年龄在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)中。
据我所知,您需要一个类似于以下内容的查询:
$users = User::with('userProfile')
->whereBetween('age', [$minAge, $maxAge])
->whereHas('userProfile', function($query){
$query->whereBetween('height', [$minHeight, $maxHeight]);
});
这将获取所有用户及其配置文件,其中UER的年龄介于$minage
和$maxage
之间,并且其配置文件的高度介于$minheight
和$maxheight
之间。
编辑
如果您希望能够用filer单独检索数据,那么您需要的是条件子句。 代码如下所示:
$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]);
});
});
我希望我没有搞砸语法,但是你明白了。 或者,您也可以使用扩展$query
变量的if-else
语句来实现同样的功能,但我个人更喜欢Laravel的优雅的when
语法。
我会做以下工作:
$user->筛选器($request->输入('min_height'),$request->输入('max_height'),$request->输入('min_age'),$request->输入('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()
,您将只使用集合
。$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(),
]);
}
我不知道这个解释是否足够清楚,但我会非常乐意回答你的任何问题,只要我能回答的话
我希望语法没有问题,但是您可以通过添加更多的If和else语句来实现您的需要,以便根据需要对它们进行过滤。