简体   繁体   English

laravel查询生成器:依赖于主要内容的联接

[英]laravel query builder: join dependent on primary content

I'm using luman and Database Query Builder to fetch full user info from database. 我正在使用luman和Database Query Builder从数据库中获取完整的用户信息。

First, Please Take a lock at my database structure: I have a table called users and a series of other tables that are related to user groups (Ex: secretaries , patients , doctors and admins ) which stores additional information about the users. 首先,请锁定我的数据库结构:我有一个名为users的表以及与用户组(例如: secretariespatientsdoctorsadmins )相关的一系列其他表,这些表存储有关用户的其他信息。

Also To determine user access, I have a level column on user table which can have one of this value as enum: 'admin', 'doctor', 'secretary', 'patient' . 另外,为了确定用户访问权限,我在user表上有一个level列,该列可以具有以下值之一作为枚举: 'admin', 'doctor', 'secretary', 'patient'

So, I want to get this information using one query by join and select . 因此,我想通过joinselect使用一个查询来获取此信息。

My training code is something like this: 我的训练代码是这样的:

$userInfo = User::where("userID", $userID)
           ->limit(1)
           ->join('[GROUP_TABLE_NAME]', function ($join) {
                  $join->on('user.userID', '=', '[GROUP_TABLE_NAME]' .'.'.
                                         '[GROUP_NAME]' . 'ID');
            })
            ->get();

The GROUP_NAME comes from level column on user table and the GROUP_TABLE_NAME can be built based on the GROUP_NAME value(Ex: ['secretary' => 'secretaries' , 'patient' => 'patients' , ...] ). GROUP_NAME来自user表的level列,并且GROUP_TABLE_NAME可以基于GROUP_NAME值构建(例如: ['secretary' => 'secretaries' , 'patient' => 'patients' , ...] GROUP_TABLE_NAME ['secretary' => 'secretaries' , 'patient' => 'patients' , ...] GROUP_TABLE_NAME ['secretary' => 'secretaries' , 'patient' => 'patients' , ...] )。

Any idea to handle the join structure using laravel query builder? 有什么想法使用laravel查询构建器来处理联接结构吗?

First you should be aware of the fact that this code architecture is not convenient and not easy to understand for other developers. 首先,您应该意识到以下事实:该代码体系结构对其他开发人员而言并不方便,也不容易理解。

SQL You can achieve your goal by using union and join . SQL您可以通过使用unionjoin来实现您的目标。

Just convert this query for laravel builder or use it directly with DB::statement : select users.*, infos.info from users left join (( select secretaries.* from secretaries ) UNION (select doctors.* from doctors)) infos ON users.id = infos.user_id where users.id=? 只需将查询转换为laravel生成器或直接将其与DB::statement一起使用即可: select users.*, infos.info from users left join (( select secretaries.* from secretaries ) UNION (select doctors.* from doctors)) infos ON users.id = infos.user_id where users.id=? .

But

The easiest way to do it is to fetch info in two queries, both indexed and fast: user from users by primary key and then info by indexed field user_id in it. 最简单的方法是在两个查询中获取信息,这两个查询都是索引的和快速的:通过主键从用户获取users信息,然后通过其中的索引字段user_id获取信息。 Create Doctorinfo , Admininfo models and correspondent migrations. 创建DoctorinfoAdmininfo模型和相应的迁移。 So user class can be smth like this: 所以用户类可以像这样:

public function getInfo() {
    switch($this->level) {
        'doctor':
            return $this->doctorinfo;
         ...
    }
}

private function doctorinfo() {
    $this->hasOne('App\Doctorinfo');
}

Builder 建造者

You can use left join to join all sub tables as well. 您也可以使用左联接来联接所有子表。 The following builder selects info column. 以下构建器选择info列。

User::where("userID", $userID)->limit(1)
   ->leftJoin('patients', 'users.id', '=', 'patients.user_id')
   ->leftJoin('doctors', 'users.id', '=', 'doctors.user_id')
   ->leftJoin('admins', 'users.id', '=', 'admins.user_id')
   ->select('users.*', DB::raw('IF(users.level="admin", admins.info, (IF users.level="doctors", doctors.info, patients.info))'))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM