首页 > 解决方案 > Eloquent:在链式 whereHas() 中使用中间表

问题描述

不幸的是,我有一个相对复杂的数据库组织,我无法更改和优化。

长话短说,这里大致是这个数据库的组织,与我的问题相关:

user→ hasMany → role_assignments→ belongsTo → context→ belongsTo (其实是一个morphTo) → course→ hasMany → enrol→ hasMany → user_enrolments→ belongsTo →user

所有这些模型都有自己的资源,目前我正在尝试将所有用户作为一个集合,例如:

user→ 多个与 → course→ 与 → enrolwhere('user_enrolments.userid', 'user.id')

这是我的UserController.php

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\userResource;
use App\Models\user;
use Illuminate\Http\Request;

class userController extends Controller
{
    public function index()
    {
        return new userResource::collection(
            user::query()
            ->where(function ($q) {
                $q
                ->whereHas('role_assignments', function ($q) {
                    $q->
                    ->where('role', 'student')
                    ->whereHas('context', function ($q) {
                        $q->whereHas('course', function ($q) {
                            $q->whereHas('enrol', function ($q) {
                                // And this is where I don't know what to do.
                                // I think it should look like:
                                $q->whereHas('user_enrolments', function ($q) {
                                    $q->where('userid', 'user.id');
                                });
                            });
                        });
                    });
                })

            ->with([
                // ...
            }])
            
            ->get()
        );
    }

所以,我真的不知道该怎么办!

在此先感谢您的帮助。

编辑:

Alex T 的回答之后,我觉得我需要精确一些东西。

首先,我->where('role', 'student')在上面的代码中添加了这行代码,让它看起来更像我自己的代码。当我第一次发布时,我试图略读它以使其更具可读性并专注于我当前的问题,但我可能略读它太多了。对于那个很抱歉。

我可以很容易地找到用户的所有课程,无论是通过用户的注册,还是通过他的角色分配。但我需要这两个中间表中的信息。理想情况下,我的 Controller 将返回以下 JSON 示例:

[
    {
        id: 1,
        name: "exampleUser1",
        otherInfoAboutThisUser: "...",
        role_assignmentsWhereTheUserIsAStudent:
            [
                {
                    id: 357,
                    role: "student",
                    courseid: 1000,
                    course:
                        {
                            id: 1000,
                            name: "Course Example",
                            user_enrolmentConcerningOnlyUser1:
                                {
                                    id: 9,
                                    timestart: 1540974600,
                                    duration: 3600,
                                    userid: 1
                                }
                        }
                },
                {
                    otherRoleAssignmentsWithTheirCourses...
                },
            ]
    },
    {
        otherUserWithHisOwnCharacteristics...
    }
]

标签: laraveleloquent

解决方案


如果我正确理解了您的问题,您希望获得所有注册至少一门课程的用户

enrol在这种情况下,我将使用 Laravel 的查询关系存在查询构建器来构建我的查询以获取至少拥有一个 的用户,并假设 anerol意味着他们已注册课程。

您只需要whereHas在需要对关系存在的查询进行更多控制时使用 - 根据上面的代码,您似乎没有对此设置任何条件。

如果您只是想让用户注册至少一门课程,您的查询将采用以下形式:

$query = user::has('enrols')
->with([...])
->get([...])

如果您需要用户注册,例如,作为特定课程,您可以执行以下操作:

$query = user::whereHas('enrols', function ($query) {
    // Assuming you have a 'courseid' key on your enrols table
    $query->where('courseid', $requestedCourseId);
})
->with([...])
->get([...])

在您的user模型上,您的enrols关系定义为:

public function enrols() 
{
    return $this->belongsToMany(Enrol::class, 'user_enrolments', 'userid', 'enrolid';
}

这使用您的user_enrolmentswhich 本质上用作多对多关系的数据透视表。


推荐阅读