【问题标题】:Laravel 4: prevent lazy load hasMany relation when foreign_key is null (optional relation)Laravel 4:当 foreign_key 为空时防止延迟加载 hasMany 关系(可选关系)
【发布时间】:2014-09-23 15:38:53
【问题描述】:

我在Command Eloquent 模型中以这种方式定义了一个 hasMany 关系:

public function rows()
{
   return $this->hasMany('\Acme\Models\Row')
}

就我而言,行可以链接到命令,也可以不链接。所以我的Row 迁移文件包含一个可为空的外键:

$table->integer('command_id')->unsigned()->nullable()->index();
$table->foreign('command_id')->references('id')->on('commands')->onDelete('set null');

没有什么真正疯狂的。

我意识到如果我实例化一个新的Command 对象并调用$command->rows,而不是一个空集合,我会得到所有带有空command_id 的行。

$command->rows 调用生成的 SQL 完美地解释了这一点:

select * from `rows` where `rows`.`command_id` is null

我认为 Laravel 选择考虑有效的空外键很奇怪......你怎么看:这是一个错误吗?我错过了什么吗?防止这种行为的最佳方法是什么?

谢谢。

【问题讨论】:

  • 奇怪的行为。我很想将其称为错误。毕竟,在 SQL null <> null 中,两个 null 值的连接不会返回任何值。 Eloquent 在这里做的事情很奇怪。
  • 我会在 Github 上的 Laravel/Framework 上发布这个,看看 Taylor 怎么说...
  • 好的,作为问题发布在 Github repo 中,这里:github.com/laravel/framework/issues/5289

标签: php sql laravel laravel-4 eloquent


【解决方案1】:

两种处理方式:

1为了防止这种行为,在您当前的设置下,您需要在关系定义中添加not null 子句:

public function rows()
{
   return $this->hasMany('\Acme\Models\Row')->whereNotNull('rows.command_id');
}

2您还可以更改架构,因此外键不可为空,但没有CommandRows 将在那里有0 值。


现在,我认为这无论如何都是正确的行为。您正在尝试获取某些内容,以 null 作为先决条件,因此它会找到这些行。这在业务逻辑上是出乎意料的,但绝对没有错。

更不用说我想不出,为什么要在新实例化的模型上调用关系,这显然没有。除非只是好奇。

【讨论】:

  • 首先,感谢您提供简洁明了的第一个解决方案。我会使用它,因为它将问题保留在模型上;关于您的最后一条评论,我可以解释:我正在开发一个通用的内容管理工具,并且在创建案例中,表单中填充了瞬态对象。我的问题是新命令的创建表单(在此示例中)由于空关系而以一些行开头。
  • 哦,我明白了。很公平。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 2013-09-17
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多