Laravel 基于另一列的可空迁移

Laravel Migration Nullable Based on Another Column

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

例如:

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

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

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

关联规则 (AR)

c => f(A)

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

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
  • 您可以在数据库中实现一个触发器,它会在 insert/update 之前检查并执行您需要的规则
  • 架构解决方案
  • 定期运行数据修复

触发器

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

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

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

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

架构解决方案

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

的新 table 的正确外键

优点:您只使用 RDBMS 开箱即用的资源

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

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

定期运行数据修复

您可以允许暂时不符合您的规则,并定期自动解决问题。

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

缺点:你不能指望你的规则每时每刻都在每条记录上得到执行。

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

应用程序级支持

您可以实现具有 set 方法的 class。该 set 方法将获得一个实体和一个 returns 布尔值的函数。如果函数returns为真,则调用set。否则抛出异常或设置默认值。