从Eloquent关系中选择特定列

8
我在我的应用程序中有以下模型:
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function customer_details()
    {
        return $this->hasOne(CustomerDetails::class);
    }
}

CustomerDetails.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class CustomerDetails extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

现在我正在尝试运行以下查询:
$user = User::select('email', 'phone')
    ->where('id', Auth::user()->id)
    ->with('customer_details')
    ->first();

现在我想要它从我的“users”表中仅选择“电子邮件”和“电话号码”,并从我的“customer_details”表中选择“first_name”、“last_name”,但每当我尝试这样做时,它总是返回“customer_details”为“null”。

在您的User.php文件中,您忘记指定localKey与外键进行比较:return $this->hasOne('App\Models\CustomerDetails', 'user_id');应该是:return $this->hasOne('App\Models\CustomerDetails', 'user_id','id'); - Punit Patel
7年前的一个问题注释:这个普遍性问题有价值,但是特定的问题可以通过$user = Auth::user()->load("customer_details");避免。 - miken32
4个回答

14
你需要在选择中包含 id,否则急切加载将无法匹配。我刚刚在自己的项目中测试了这一点,并遇到了同样的问题,添加 id 到选择中可以解决它。
$user = User::select('id', 'email', 'phone')->where('id', Auth::user()->id)->with('customer_details')->first();

为了进一步解释这个问题,急切加载通过先调用父级(在本例中,是对users的调用),然后执行第二个调用 SELECT * FROM customer_details WHERE customer_details.user_id IN (?),其中?是用户ID列表。然后它循环遍历第二个调用的结果,并将它们附加到相应的用户对象上。如果用户对象上没有id,则无法在第二次调用或附加时进行匹配。
编辑
要从急切加载的表中选择特定的列,可以使用闭包功能,如此处所解释的那样。因此,您可以使用关系名称作为键,使用一个接收Builder对象作为值的闭包,例如:
$user = User::select('id', 'email', 'phone')
    ->where('id', Auth::user()->id)
    ->with('customer_details' => function (Builder $query) {
        $query->select('id', 'user_id', 'name', 'foo');
    })
    ->first();

请注意,您必须为两者选择关系列,否则 Laravel 将不知道如何连接这两个。

谢谢,那个起作用了 :) 不过我还想问一下,如何从“customer_details”中仅选择特定的列呢? - user3718908x100
@user3718908 请查看我刚刚对我的答案所做的编辑。 - Josh
闭包的代码有问题,它被用红线标出来了。我把“Builder”拿掉了,只留下“$query”。现在它可以正常工作了。 :) - user3718908x100
1
你需要导入Builder类 (use Illuminate\Database\Eloquent\Builder;)。 - Josh
是的,答案和解释都是正确的。请注意,您必须为两个表格选择关系列,否则 Laravel 将不知道如何连接它们。 - Elby
你选择特定列的代码在 Laravel 7 上报错。请更新 "with" 部分,使用以下代码:->with(array('customer_details' => function ($query) {$query->select('id', 'user_id', 'name', 'foo');})) - habib

-1
在您的User.php文件中,您忘记指定本地键与外键进行比较: < p > < code > return $this->hasOne('App\Models\CustomerDetails', 'user_id'); 应该是:有3个参数:(模型,“用于比较的键”,“本地键”) < p > < code > return $this->hasOne('App\Models\CustomerDetails', 'user_id','id');

-1
这是绝对正确的。如果您使用此代码抛出异常错误,则会出现如下错误信息。 例如:
"error": "mb_strpos()期望参数 1 是字符串,但得到的是对象"
    $user = User::select('id', 'email', 'phone')
            ->where('id', Auth::user()->id)
            ->with('customer_details' => function (Builder $query) {
             $query->select('id', 'user_id', 'name', 'foo');
        })->first();

然后在使用类似这样的[]。
$user = User::select('id', 'email', 'phone')
        ->where('id', Auth::user()->id)
        ->with(['customer_details' => function (Builder $query) {
       $query->select('id', 'user_id', 'name', 'foo');
}])->first();

-1

我认为你的查询语句有问题。在Laravel中使用查询构建器。

试试这个

$user=DB::table('users')->join('customer_details','user.id','=','customer_details.id')->select('email','phone','first_name','last_name')->where('id','=',Auth::user()->id)->first();

我猜你在 customer_details 表中也使用 id 作为主键。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接