基于另一列的Laravel迁移为Null



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

例如:

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

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

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

关联规则(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
  • 您可以在数据库中实现一个触发器,在插入/更新之前,该触发器将检查并强制执行您需要的规则
  • 架构解决方案
  • 定期运行数据修复

触发器

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

优势:即使写入操作发生在应用程序之外,您的数据一致性也将得到维护。

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

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

架构解决方案

所以,如果c1有某个值,那么c2是不可为null的。您可以将c1移到另一个表,并将c2设为外键。如果满足c1的条件,请确保c2是保存c1的新表的正确外键。

优势:您只使用RDBMS为您提供的现成资源

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

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

定期运行数据修复

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

优点:解决方案可能是对数据库服务器的单个请求,该服务器将执行存储过程或类似操作,从而快速执行任务。

缺点:您不能依赖于您的规则在每一个记录的每一刻都得到执行。

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

应用程序级支持

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

最新更新