为什么Laravel/Eloquent不能使用JOIN进行预先加载?

emz*_*ero 22 php join eager-loading eloquent laravel-4

<?php

class Cat extends Eloquent {

    public function user() {
        return $this->belongsTo('User');
    }
}

class User extends Eloquent {

    public function cats() {
        return $this->hasMany('Cat');
    }
}
Run Code Online (Sandbox Code Playgroud)

现在:

$cats = Cat::with('user')->get();
Run Code Online (Sandbox Code Playgroud)

执行2个查询:

select * from `cats`
select * from `users` where `users`.`id` in ('1', '2', 'x')
Run Code Online (Sandbox Code Playgroud)

为什么不能这样做:

select * from cats inner join users on cats.user_id = users.id
Run Code Online (Sandbox Code Playgroud)

对于那些说表中有两个id列的人来说,使用别名可以很容易地避免这种情况:

select 
    c.id as cats__id,
    c.name as cats__name,
    c.user_id as cats__user_id,
    b.id as users__id,
    b.name as users__name
from cats c
inner join users b on b.id = c.user_id
Run Code Online (Sandbox Code Playgroud)

UPDATE

有人指出,Eloquent并不知道模型中表的列,但我猜他们可以提供一种在模型中定义它们的方法,这样它就可以使用别名并进行正确的连接而不是额外的查询.

小智 10

我的猜测是,这允许急切加载多个一对多的关系.比如说,我们还有一张狗桌:

class User extends Eloquent {

    public function cats() {
        return $this->hasMany('Cat');
    }

    public function dogs() {
        return $this->hasMany('Dog');
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们想要用户急切加载它们:

$users = User::with('cats','dogs')->get();
Run Code Online (Sandbox Code Playgroud)

没有联接可以将这些组合成单个查询.但是,对每个"with"元素执行单独查询确实有效:

select * from `users`
select * from `cats` where `user`.`id` in ('1', '2', 'x')
select * from `dogs` where `user`.`id` in ('1', '2', 'x') 
Run Code Online (Sandbox Code Playgroud)

因此,虽然这种方法可能会在某些简单的情况下产生额外的查询,但它提供了在连接方法失败时急切加载更复杂数据的能力.

这是我猜测为什么会这样.