Laravel 5 leftJoin on ownsTo 关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28051839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 10:44:52  来源:igfitidea点击:

Laravel 5 leftJoin on belongsTo relation

phplaravel

提问by Jan-Paul Kleemans

I have two database tables: users and students. A student is a user, but has extra data (address). I have a belongsTo('User') relationship in my Student model.

我有两个数据库表:用户和学生。学生是用户,但有额外的数据(地址)。我的学生模型中有一个belongsTo('User') 关系。

If I now query the Student model like this:

如果我现在像这样查询 Student 模型:

$this->student
    ->with('user')
    ->first();

I get this result:

我得到这个结果:

{
    "id": 1,
    "user_id": 12,
    "street": "Petershof",
    "house_number": "3787",
    "postal_code": "8161 NM",
    "city": "Tienhoven",
    "user": {
        "id": 12,
        "email": "[email protected]",
        "first_name": "Nathan",
        "last_name": "van Dijk",
        "name": "Nathan van Dijk"
    }
}

However, I want to flatten the result, so that the user fields are in the parent (Student) object. Like this:

但是,我想展平结果,以便用户字段位于父 (Student) 对象中。像这样:

{
    "id": 1,
    "user_id": 12,
    "street": "Petershof",
    "house_number": "3787",
    "postal_code": "8161 NM",
    "city": "Tienhoven",
    "email": "[email protected]",  // = user field
    "first_name": "Nathan",        // = user field
    "last_name": "van Dijk",       // = user field
    "name": "Nathan van Dijk"      // = user field
}

I have tried to use leftJoin('users', 'user_id', '=', 'users.id') instead of with(), but then I lose my virtual attribute 'name' (defined in the User model) and also can't query relations of User anymore.

我曾尝试使用 leftJoin('users', 'user_id', '=', 'users.id') 而不是 with(),但随后我丢失了我的虚拟属性 'name'(在用户模型中定义)以及无法再查询用户的关系。

How can I achieve this in a clean way?

我怎样才能以干净的方式实现这一目标?

回答by Jarek Tkaczyk

$this->student
  ->leftJoin('users', 'users.id', '=', 'students.user_id')
  ->select(
    'students.*',
    'users.email',
    'users.first_name',
    'users.last_name',
    DB::raw("concat(users.first_name, ' ', users.last_name) as name"),
  )->first();

You could drop the table in select like users.emailin this case.

users.email在这种情况下,您可以将表格放入 select中。

The relations will work just the same, I suppose the problem was only with overriding studentsid with usersid, if you didn't specify the selectand just grabbed all the fields.

关系的工作原理相同,我想问题仅在于用studentsid覆盖usersid,如果您没有指定select而只是抓取了所有字段。

回答by Lpgfmk

Old question, but here goes.

老问题,但在这里。

Reading your comment it seems you want to make an api for this. If it's only one endpoint formatting the result on the fly shouldn't be an issue however for more endpoints I would suggest a transformer pattern.

阅读您的评论,您似乎想为此制作一个 api。如果它只是一个端点格式化,那么即时结果应该不是问题,但是对于更多端点,我建议使用转换器模式。

This would work by having a separate class return an array based on your db data. Then you take that array and use it in your response().

这可以通过让一个单独的类根据您的数据库数据返回一个数组来实现。然后你使用那​​个数组并在你的response().

So, in your controller, instead of doing something like return response(Student::all());you could do something like return response(StudentTransformer::transform(Student::all())).

因此,在您的控制器中,return response(Student::all());您可以执行类似return response(StudentTransformer::transform(Student::all())).

The advantage here is you have only one folder (your Transformers) to check for response data format. The disadvantage is when your DB changes you also need to update your transformers.

这里的优点是您只有一个文件夹(您的Transformers)来检查响应数据格式。缺点是当您的数据库更改时,您还需要更新转换器。