Laravel 与拉威尔混淆';她有一段很有说服力的关系

Laravel 与拉威尔混淆';她有一段很有说服力的关系,laravel,laravel-5,eloquent,eloquent-relationship,Laravel,Laravel 5,Eloquent,Eloquent Relationship,我有一个新的Laravel 5.8应用程序。我开始玩能言善辩的ORM及其关系 我马上遇到了一个问题 我有以下表格。(出于测试原因,这只是一个示例,不会成为实际应用程序) 我想要的是获得属于实际登录的IP 因此,我在登录表中添加了一个hasOne关系,该关系为数据表提供了一个外键: public function data() { return $this->hasOne('App\Models\Data'); } public function ip() { return

我有一个新的Laravel 5.8应用程序。我开始玩能言善辩的ORM及其关系

我马上遇到了一个问题

我有以下表格。(出于测试原因,这只是一个示例,不会成为实际应用程序)

我想要的是获得属于实际登录的IP

因此,我在
登录表
中添加了一个
hasOne
关系,该关系为
数据表
提供了一个外键:

public function data()
{
    return $this->hasOne('App\Models\Data');
}
public function ip()
{
    return $this->hasOne('App\Models\Ip');
}
然后,我将一个
hasOne
关系添加到
数据表
,该表为
IP表
提供了一个外键:

public function data()
{
    return $this->hasOne('App\Models\Data');
}
public function ip()
{
    return $this->hasOne('App\Models\Ip');
}
完成后,我希望检索登录表第一条记录的IP地址:

Login::find(1)->data()->ip()->get();
但我得到了这个错误:

Call to undefined method Illuminate\Database\Eloquent\Relations\HasOne::ip()

我在这里遗漏了什么?如何以正确的方式获取登录的IP?我需要一个
以下的
吗?

你可以这样试试:

登录

public function data()
{
    return $this->belongsTo('App\Models\Data', 'data_id');
}
数据

public function ip()
{
    return $this->belongsTo('App\Models\Ip', 'ip_id');
}

数据
中,您将拥有
ip
,如
$login->data->ip
和您的数据库结构:

登录
belongsTo
数据

数据
hasOne
Login

数据
属于IP

IP
hasOne
数据

在修正了你的方法之后,你可以像这样使用你的关系

$login=login::with(['data.ip'])->查找(1)

第一个错误:错误的关系定义 拉维关系是双向的。在一对一关系中,您可以定义直接关系(
HasOne
)和反向关系(
BelongsTo

直接关系应该是:

             HasOne                HasOne
[ Login ] <----------- [ Data ] <----------- [ IP ]
           BelongsTo             BelongsTo
[ Login ] -----------> [ Data ] -----------> [ IP ]
有关如何定义它的详细信息,请参见文档

注意除非需要,否则不需要为关系定义两个方向。在您的情况下,我认为您只需要定义
belongsTo
方向

第二个错误:您正在调用关系方法,而不是关系本身 当您这样做时:

Login::find(1)->data()->ip()->get();
您正在调用定义关系的方法
data
,而不是相关模型。这在某些情况下是有用的,但在您的情况下不是

正确的方法是调用relationship magic属性:

Login::find(1)->data->ip;
请注意,这里不使用
()
,也不需要
get()
。Laravel负责为我们装货

使用即时加载 Laravel Eloquent为关系提供了一个解决方案,这在某些情况下非常有用,因为它预加载了您的关系,并减少了您的查询数量

在您描述的情况下(加载单个
登录
模型),它不会带来任何性能改进,但也不会减慢速度

它在加载许多模型时非常有用,因此它将数据库查询计数从
N+1
减少到
2

假设您正在加载100个
Login
模型,在不急于加载的情况下,您将执行1个查询以获取
Login
模型,100个查询以获取
数据
模型,以及100多个查询以获取
Ip
模型


通过快速加载,它将只执行3次查询,导致性能大幅提高。

不幸的是,我收到了以下错误消息:
SQLSTATE[42S22]:未找到列:1054未知列“data.login\u id”在“where子句”中(SQL:select*from'data'where'data.'login\u id'在(1)中)
因为您使用了
hasOne
方法。因此,如果我理解正确,我总是必须有一个belongsTo+a hasOne-并且我不能没有另一个吗?还有,外键应该放在哪里?或者我现在怎么拥有它们还可以吗?@radial_Activity请检查惊奇,谢谢你的描述性解释,我现在明白了。我认为我思考的问题是,我认为
Login
表是“主”表,其余部分是Login表的一部分。这是真的,但我们需要想一想,在这种情况下。无论如何,非常感谢你,你救了我一天!:)