为了账号安全,请及时绑定邮箱和手机立即绑定

在搜索功能中从模型访问表列时出现问题

在搜索功能中从模型访问表列时出现问题

PHP
绝地无双 2023-07-07 10:38:47
我有一个搜索功能,可以根据用户输入的过滤器(从/到年龄、从/到身高)搜索用户。问题是年龄列位于用户表(用户模型)中,身高列位于用户配置文件表(用户配置文件模型)中。我可以轻松地从每个模型中单独获取结果,但我想在结合这两个条件时获取结果。例如,获取年龄在 30 岁到 40 岁、身高在 180 厘米到 190 厘米之间的用户。任何帮助表示赞赏。这是我的代码。搜索控制器.phpclass 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);    }}用户.phpprotected $fillable = [        'username',         'email',         'first_name',        'last_name',        'age',    ];  public function userProfile(){    return $this->hasOne(UserProfile::class);}用户配置文件.phpprotected $fillable = [        'user_id',        'interested_in',        'height',          ];    public function user()    {        return $this->belongsTo(User::class);    }因此,需要明确的是,我不需要特定用户及其用户配置文件,而是将用户和用户配置文件模型中的列连接到一个变量($query)中。
查看完整描述

2 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

据我所知,您需要一个类似于以下内容的查询:


$users = User::with('userProfile')

->whereBetween('age', [$minAge, $maxAge])

->whereHas('userProfile', function($query){

    $query->whereBetween('height', [$minHeight, $maxHeight]);

});

这将获取所有用户的个人资料,其中用户的年龄介于$minAge和 之间$maxAge,个人资料的身高介于$minHeight和之间$maxHeight。


编辑


如果您希望能够使用文件管理器单独检索数据,那么您需要的是条件子句。代码看起来像这样:


$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,但我个人更喜欢whenLaravel 的优雅语法。


查看完整回答
反对 回复 2023-07-07
?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

我会做以下事情:

  1. 从控制器中提取此逻辑并将其放入用户模型中。

  2. 由于您在控制器中对用户模型使用依赖注入,因此您可以在控制器中执行类似的操作

$user->filter($request->input('min_height'),$request->input('max_height'),$request->input('min_age'),$request->input('max_age'));

这样,控制器将负责将所需的数据传递给模型,然后您可以在模型内部进行查询。

这样做的好处是

  1. 更清晰的控制器

  2. 控制器将只负责接收请求、传递所需的数据并将结果传递给索引。

  3. 只要您拥有用户实例,您就可以在任何地方重复使用此过滤器

  4. 责任将在模型和控制器之间分配,控制器不会做所有事情

在您的用户模型中,查询将如下所示:

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;

}

  1. 我们返回 eloquent 实例而没有这样做的原因 $query->get()是,通过这种方式,我们可以在控制器中执行此操作,并且对于重用此代码的每个地方,我们可以根据需要执行诸如orderBygroupByfirst和其他操作之类的操作get我们调用它的地方。因为如果你做了一个,$query->get()你就会受到唯一的限制Collection

  2. 之后,我们可以在控制器中执行类似的操作$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 语句来根据需要过滤它们来满足您的需求。


查看完整回答
反对 回复 2023-07-07
  • 2 回答
  • 0 关注
  • 116 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信