【问题标题】:Laravel Migration Nullable Based on Another Column基于另一列的 Laravel 迁移可为空
【发布时间】:2021-03-20 23:29:46
【问题描述】:

我正在使用 Laravel 编写数据库迁移,我想知道是否可以根据另一列的值将一列设置为不可为空。

例如:

If    User.owns_cat === true  
Then  User.cat_name->nullable(false)

我知道我可以稍后通过验证规则来处理这个问题,但希望在数据库级别拥有这个规则。

【问题讨论】:

  • 该列的某一行中的内容无关紧要,整列将是nullable 或不是nullable。稍后您将不得不使用 DB 触发器(或类似的东西)或通过 Laravel 的 requried_with 验证来处理。
  • 啊,触发器。这可能就是我正在寻找的。谢谢!
  • 没问题!我认为这就是你要找的东西,但我不能说我曾经不得不在数据库级别强制这个条件。如果您碰巧找到了解决方案,请随时发布自我回答,或在遇到任何其他问题时更新您的问题。干杯!
  • @TimLewis 触发器和 Eloquent 事件一样吗?
  • @TimLewis 啊,好的...谢谢。

标签: database laravel laravel-migrations


【解决方案1】:

您真正需要的是对条件函数依赖和关联规则的支持。

关联规则 (AR)

c => f(A)

其中 c 是一个逻辑上可确定的值,如果满足,则列集 A 将填充 where 的内容

A = (A1, A2, ..., An)

条件函数依赖 (CFD)

c => A -> B

其中c是逻辑上可确定的值,如果满足,则列集A确定列集B的值,其中

A = (A1, A2, ..., An)

B = (B1, B2, ..., Bn)

问题

RDBMS 系统不倾向于支持开箱即用的 AR 或 CFD,至少我上次检查时是这样。因此,由于底层系统可能不支持您需要的功能,Laravel 迁移可能也无法实现。

解决方案

基于应用程序代码定义架构的问题在于,该任务在技术堆栈的 ORM 级别上不太合适,因为:

  • 您使用了一些只能间接影响的模式生成器
  • 更复杂的问题很难通过这样的系统解决
  • 架构更改生成器可能存在错误,这会不必要地为您的问题增加新的担忧

那么,你可以做什么:

  • 您可以在应用程序级别实现一个功能来检查某些条件,如果满足,则强制执行规则,也就是说,如果要违反规则,则抛出错误或设置默认值,而如果满足规则,然后调用 set
  • 您可以在数据库中实现一个触发器,该触发器在插入/更新之前会检查并执行您需要的规则
  • 架构解决方案
  • 定期运行数据修复

触发器

您将创建一个触发器,该触发器将检查 column2 的值,如果满足您的条件,则检查 column1 是否为空。如果是这样,那么您可能会选择抛出错误或设置默认值。

优势:即使写操作发生在您的应用程序之外,您的数据也会保持一致。

缺点:如果规则经常更改并且无法访问您的应用程序级资源,这将很难维护。

这种方法是否适合您,取决于您的需求。

架构解决方案

因此,如果 c1 具有某个值,则 c2 不可为空。您可以将 c1 移动到另一个表并使 c2 成为外键。如果满足 c1 的条件,请确保 c2 是包含 c1 的新表的正确外键。

优势:您只使用 RDBMS 提供的开箱即用的资源

缺点:如果您的 c2 条件很复杂,这种方法会违反直觉

这种方法的适用性取决于您病情的复杂程度。

定期运行数据修复

您可以允许暂时与您的规则不一致并定期自动解决问题。

优势:解决方案可能是对数据库服务器的单个请求,它会执​​行存储过程或类似的东西,快速执行任务。

缺点:你不能依赖你的规则在每条记录上每时每刻都被执行。

如果您不担心您的规则会被暂时违反,只要它很快就正确了,这就是适用的。

应用级支持

您可以实现一个具有 set 方法的类。该 set 方法将获得一个实体和一个返回布尔值的函数。如果函数返回true,则调用set。否则要么抛出异常,要么设置默认值。

【讨论】:

  • 感谢详细解释!
猜你喜欢
  • 2012-12-10
  • 2014-08-16
  • 2016-01-07
  • 2019-05-29
  • 1970-01-01
  • 2019-04-16
  • 2023-03-19
  • 2020-11-11
  • 1970-01-01
相关资源
最近更新 更多