使用 Laravel ORM 抽象保存新的不可为空的关系,而不会违反数据库完整性约束
Posted
技术标签:
【中文标题】使用 Laravel ORM 抽象保存新的不可为空的关系,而不会违反数据库完整性约束【英文标题】:Save new non-nullable relationship using Laravel ORM abstraction without database integrity constraint violation 【发布时间】:2020-10-28 23:02:46 【问题描述】:这个问题与 Laravel 7 有关。
我有两个模型,比如说 Post 和 Comment,它们是典型的一对多关系。定义了关系及其逆关系。在为他们的数据库表进行迁移时,我没有使 Comment 表上的 post_id
可以为空。我认为使其不可为空是一个合理的约束,因为所有评论都必须在逻辑上附加到帖子。
但是,在发表新评论时,我似乎无法使用create()
、save()
等来关联关系。我想做类似的事情:
$post->comments()->create(["text" => "Comment text goes here"]);
我会假设这会创建带有 post_id
填充的评论,但是很遗憾,它会在数据库级别引发“完整性约束违规”(post_id 不能为空)
同样,我试过了:
$comment = new Comment(["text" => "Comment text goes here"]);
$post->comments()->save($comment);
同样的事情 - 违反数据库完整性约束。但为什么?我希望 Laravel 在创建此评论时不会只进行一个包含 post_id
的 INSERT 操作。在这两种情况下,我都不希望在 post_id
为空的情况下插入新的评论。
我知道我可以在创建时手动将 post_id
设置为主键,如果确实没有其他选项,我会这样做 - 我更喜欢尽可能使用 ORM 抽象。
问题:
有谁知道save()
、create()
是否实际上是先在关系字段为空的情况下插入行,然后再更新 - 还是我只是做错了什么?
如果可能的话,使用 Eloquent ORM 抽象的正确方法是什么?
我一直觉得,由于我在 Comment 上定义了关系 post()
,如果我使用 ORM,现在显式处理 post_id
列是不好的做法,因为它破坏了关系抽象的意义。这种哲学合理吗?我的想法是否正确?
注意:我知道this question 存在,但我认为我的不是重复的,因为在那个问题中,他们的 belongsTo 关系是可选的,所以他们接受了“只需删除 DB 约束/使列可为空”的答案. Mine 不是可选字段,因此将其设为可空是没有意义的。是的,更改数据库约束将“解决”问题,但我更喜欢保留完整性约束,因为 post_id=null 的评论会出现故障,因此最好在数据库级别 imo 上实现这一点。
【问题讨论】:
$post
是现有模型实例吗?
@lagbox 我打算回答是的,但我想你刚刚想通了。在我用来测试它的代码中,$post 是现有模型实例,但我在调用 $post 上的 save() 之前尝试关联注释。所以当然 $post 还没有主键。谢谢你看到这个:O
@lagbox 如果您想将其添加为答案,我会接受。
【参考方案1】:
确保$post
是“现有”模型实例。如果这是一个新实例,请务必保存它,这样它将有一个来自数据库的“id”,否则“id”将是null
,它会尝试分配给相关记录的外键字段。
【讨论】:
以上是关于使用 Laravel ORM 抽象保存新的不可为空的关系,而不会违反数据库完整性约束的主要内容,如果未能解决你的问题,请参考以下文章