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

我有一个搜索功能,可以根据用户输入的过滤器(从/到年龄、从/到身高)搜索用户。问题是年龄列位于用户表(用户模型)中,身高列位于用户配置文件表(用户配置文件模型)中。我可以轻松地从每个模型中单独获取结果,但我想在结合这两个条件时获取结果。例如,获取年龄在 30 岁到 40 岁、身高在 180 厘米到 190 厘米之间的用户。任何帮助表示赞赏。这是我的代码。


搜索控制器.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);

    }

}

用户.php


protected $fillable = [

        'username', 

        'email', 

        'first_name',

        'last_name',

        'age',

    ];  


public function userProfile()

{

    return $this->hasOne(UserProfile::class);

}

用户配置文件.php


protected $fillable = [

        'user_id',

        'interested_in',

        'height',

      

    ];


    public function user()

    {

        return $this->belongsTo(User::class);

    }

因此,需要明确的是,我不需要特定用户及其用户配置文件,而是将用户和用户配置文件模型中的列连接到一个变量($query)中。


绝地无双
浏览 117回答 2
2回答

米琪卡哇伊

据我所知,您需要一个类似于以下内容的查询:$users = User::with('userProfile')->whereBetween('age', [$minAge, $maxAge])->whereHas('userProfile', function($query){&nbsp; &nbsp; $query->whereBetween('height', [$minHeight, $maxHeight]);});这将获取所有用户的个人资料,其中用户的年龄介于$minAge和 之间$maxAge,个人资料的身高介于$minHeight和之间$maxHeight。编辑如果您希望能够使用文件管理器单独检索数据,那么您需要的是条件子句。代码看起来像这样:$users = User::with('userProfile')->when($ageFilterActive, function($query, $ageFilterActive) {&nbsp; &nbsp; $query->whereBetween('age', [$minAge, $maxAge]);})->when($heightFilterActive, function($query, $heightFilterActive) {&nbsp; &nbsp; $query->whereHas('userProfile', function($query){&nbsp; &nbsp; &nbsp; &nbsp; $query->whereBetween('height', [$minHeight, $maxHeight]);&nbsp; &nbsp; });});我希望我没有搞乱语法,但你明白了。if-else或者,您可以通过扩展变量的语句来实现相同的目的$query,但我个人更喜欢whenLaravel 的优雅语法。

qq_遁去的一_1

我会做以下事情:从控制器中提取此逻辑并将其放入用户模型中。由于您在控制器中对用户模型使用依赖注入,因此您可以在控制器中执行类似的操作$user->filter($request->input('min_height'),$request->input('max_height'),$request->input('min_age'),$request->input('max_age'));这样,控制器将负责将所需的数据传递给模型,然后您可以在模型内部进行查询。这样做的好处是更清晰的控制器控制器将只负责接收请求、传递所需的数据并将结果传递给索引。只要您拥有用户实例,您就可以在任何地方重复使用此过滤器责任将在模型和控制器之间分配,控制器不会做所有事情在您的用户模型中,查询将如下所示:public function scopeWithUserProfile($query){&nbsp; &nbsp; // Left join or inner join depends on your needs&nbsp; &nbsp; return $query->join('user_profile', 'users.id', '=', 'user_profile.user_id');}public function filter($minHeight, $maxHeight, $minAge, $maxAge) {&nbsp; &nbsp; $query = $this->query()&nbsp; &nbsp; &nbsp; &nbsp; ->withUserProfile();&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if (!is_null($minHeight) && !is_null($maxHeight)) {&nbsp; &nbsp; &nbsp; &nbsp; $query->whereBetween('height', [$minHeight, $maxHeight]);&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if (!is_null($minAge) && !is_null($maxAge)) {&nbsp; &nbsp; &nbsp; &nbsp; $query->whereBetween('age', [$minAge, $maxAge]);&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; return $query;}我们返回 eloquent 实例而没有这样做的原因&nbsp;$query->get()是,通过这种方式,我们可以在控制器中执行此操作,并且对于重用此代码的每个地方,我们可以根据需要执行诸如orderBy、groupBy、first和其他操作之类的操作get我们调用它的地方。因为如果你做了一个,$query->get()你就会受到唯一的限制Collection。之后,我们可以在控制器中执行类似的操作$query->get(),然后从那里我们将收集所需的数据。在最后的控制器中你必须有这样的东西public function search(Request $request, User $user){&nbsp; &nbsp; $user->filter($request->input('min_height'),$request->input('max_height'),$request->input('min_age'),$request->input('max_age'));&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; return view('your.view.here', [&nbsp; &nbsp; &nbsp; &nbsp; 'userData' => $user->get(),&nbsp; &nbsp; ]);}我不知道解释是否足够清楚,但只要我能,我将非常乐意回答您的任何问题:P我希望语法没问题,但您可以通过添加更多 If 和 else 语句来根据需要过滤它们来满足您的需求。
打开App,查看更多内容
随时随地看视频慕课网APP