Laravel有一对零或一的Eloquent关联吗?

4

能否将Laravel的HasOne关系也用作HasOneOrZero关系?

示例:文档中,描述了用户和电话之间的HasOne关系。如果每个用户只有01个电话,是否可以使用此关系?还是我需要拥有一个OneToMany关系才能允许0

我不确定如果将HasOne关系用作HasOneOrZero关系是否会导致任何问题。

2个回答

19

是的,你可以将 HasOne 视为 HasOneOrZero 关系来使用。

HasOne 关系可以为 null,在数据库中不需要有关联行。只需要在获取时检查即可。

此外,你可能需要并且会喜欢新的 5.5 版本中的 optional 函数。

其工作原理如下:

optional($user->phone)->number;
如果你有电话号码,它会返回一个数字,但如果没有,则会返回null而不是尝试获取非对象属性

3

除了astratyandmitry之外,我还想补充一下我发现的内容。在我自己思考HasOneHasMany之间实际上有什么区别后,我得出了以下结论。

首先,它们都具有相同的表结构。

用户表:

id | name
 1 | Alice
 2 | Bob

电话表:
id | user_id  | phone
 1 |   1      |  123
 2 |   2      |  321

Model类中,hasManyhasOne方法是一样的,唯一不同的是它们返回的对象:

public function hasOne($related, $foreignKey = null, $localKey = null)
{
    $foreignKey = $foreignKey ?: $this->getForeignKey();
    $instance = new $related;
    $localKey = $localKey ?: $this->getKeyName();
    return new HasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
}

并且

public function hasMany($related, $foreignKey = null, $localKey = null)
{
    $foreignKey = $foreignKey ?: $this->getForeignKey();
    $instance = new $related;
    $localKey = $localKey ?: $this->getKeyName();
    return new HasMany($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
}

然而,返回的对象(class HasOne 和 class HasMany)仅在3个函数中有所不同:
  • getResults()
  • initRelation()
  • match()
getResults() 方法是通过神奇的 __get() 方法调用的,每当关系在没有括号的情况下被调用时(参见 此处),就像这样。
$user->phone

这是类hasOnegetResults()方法:

public function getResults()
{
    return $this->query->first() ?: $this->getDefaultFor($this->parent);
}

因此输出将是:

enter image description here

如果关系被声明为hasOne
public function phone()
{
    return $this->hasOne('App\Phone');
}

相比之下,hasMany 类中的 getResults() 方法如下:
public function getResults()
{
    return $this->query->get();
}

因此,输出为空集合:

enter image description here

如果关系被声明为hasMany
public function phone()
{
    return $this->hasMany('App\Phone');
}

如果数据库中不存在关联行,则HasOne关系将返回null,可以按照astratyandmitry在他的帖子中描述的方式处理它。
不幸的是,我找不到initRelation()方法或match()方法何时被调用。

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