Rad*_*ity 0 laravel eloquent laravel-5 eloquent-relationship
我有一个新的 Laravel 5.8 应用程序。我开始使用 Eloquent ORM 及其关系。
我马上就遇到了一个问题。
我有以下表格。(这只是一个示例,出于测试原因,不会成为实际应用程序)
Login table:
--------------------------
| id | user    | data_id |
--------------------------
| 1  | admin   | 1       |
| 2  | admin   | 2       |
| 3  | admin   | 3       |
--------------------------
Data table:
--------------
| id | ip_id |
--------------
| 1  | 1     |
| 2  | 2     |
| 3  | 3     |
--------------
IP table:
----------------------
| id | ip            |
----------------------
| 1  | 192.168.1.1   |
| 2  | 192.168.1.2   |
| 3  | 192.168.1.3   |
----------------------
Run Code Online (Sandbox Code Playgroud)
我想要的是获取属于实际登录的IP。
所以我添加了一个hasOne与Login table具有外键的关系Data table:
public function data()
{
    return $this->hasOne('App\Models\Data');
}
Run Code Online (Sandbox Code Playgroud)
然后我添加了一个hasOne与Data table具有外键的关系IP table:
public function ip()
{
    return $this->hasOne('App\Models\Ip');
}
Run Code Online (Sandbox Code Playgroud)
完成后,我想检索登录表第一条记录的 IP 地址:
Login::find(1)->data()->ip()->get();
Run Code Online (Sandbox Code Playgroud)
但我收到此错误:
Call to undefined method Illuminate\Database\Eloquent\Relations\HasOne::ip()
Run Code Online (Sandbox Code Playgroud)
我在这里缺少什么以及如何以正确的方式获取该登录的 IP?我需要一个belongsTo地方吗?
Laravel 关系是双向的。在one-to-one关系上,您可以定义直接关系 ( HasOne) 和逆关系 (BelongsTo )
直接关系应该是:
             HasOne                HasOne
[ Login ] <----------- [ Data ] <----------- [ IP ]
Run Code Online (Sandbox Code Playgroud)
逆关系应该是:
           BelongsTo             BelongsTo
[ Login ] -----------> [ Data ] -----------> [ IP ]
Run Code Online (Sandbox Code Playgroud)
有关如何定义它的详细信息,请参阅Eloquent:关系 - 一对一文档。
请注意,除非需要,否则无需为关系定义两个方向。在你的情况下,我认为你只需要定义belongsTo方向。
当你这样做时:
Login::find(1)->data()->ip()->get();
Run Code Online (Sandbox Code Playgroud)
您正在调用data定义您的关系的方法,而不是相关模型。这在某些情况下很有用,但对您的情况则不然。
正确的是调用关系魔法属性:
Login::find(1)->data->ip;
Run Code Online (Sandbox Code Playgroud)
请注意,我们不使用,()也不需要get()这里。Laravel 负责为我们加载它。
Laravel Eloquent 有一个Eager Loading关系,这在某些情况下非常有用,因为它预先加载你的关系,并减少你执行的查询数量。
在您描述的情况下(加载单个Login模型),它不会提高任何性能,但也不会减慢速度。
当您加载许多模型时,它很有用,因此它将您的数据库查询计数从 减少N+1到2。
想象一下,您正在加载 100 个Login模型,如果没有预先加载,您将执行 1 次查询以获取Login模型,执行 100 次查询以获取模型,再执行 100 次查询以获取您的Data模型Ip模型。
使用预先加载,它只会执行 3 次查询,从而导致性能大幅提升。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           3051 次  |  
        
|   最近记录:  |