CakePHP 保存非常深的关联模型

Posted

技术标签:

【中文标题】CakePHP 保存非常深的关联模型【英文标题】:CakePHP Saving Very Deep Associated Models 【发布时间】:2014-07-11 02:10:15 【问题描述】:

我有一个使用党分析模式来简化关联的数据库(因为它必须存储有关人员和组织的信息,两者都有共同的属性)。因此,我的相关模型可以变得相当深入。我的问题是保存数据的最佳方法是什么?以保存员工为例,Employee 表不直接连接到 Party 表,但是如果我将模型嵌套在这样的数组中:

array(
    'Party' => array(
        'Email' => array(...),
        'Address' => array(
            'Country' => array(...),
            'Location' => array(
                'State' => array(...)
            )
        ),
        'PhoneNumber' => array(...),
        'Person' => array(
            'Language' => array(...),
            'Skill' => array(...),
            'Employee' => array(
                'WorkHistory' => array(...),
                'Qualification' => array(...)
            )
        )
    )
)

我可以使用 saveAll,它会保存所有内容。这意味着在我的表单上,我有诸如 Party.Person.Employee.start_time 之类的字段名称。然而,有人告诉我这样做并没有真正遵循 Cakephp 的约定。另一种选择是让我的数组像这样:

array(
    'Party' => array(...)
    'Email' => array(...),
    'Address' => array(...),
    'Country' => array(...),
    'Location' => array(...),
    'PhoneNumber' => array(...),
    'Person' => array(...),
    'Language' => array(...),
    'Skill' => array(...),
    'Employee' => array(...),
    'WorkHistory' => array(...),
    'Qualification' => array(...)
)

但是,如果我对此调用 saveAll,则不会保存所有内容,因为某些表/模型没有直接连接到 Party。据我所知,保存这种结构的唯一方法是使用事务。

所以我想知道 CakePHP 专家认为解决需要保存非常深的关联模型的情况的最佳方法是什么?

编辑:

根据我收到的响应可以收集到的信息,对于您调用 saveAll 的模型,与它直接关联的其他模型不需要嵌套在该模型数组中。但是,如果您还想保存与它没有直接关联的模型,那么您需要将这些模型嵌套在与您调用 saveAll 的模型直接关联的模型中。抱歉,我知道这很令人困惑,所以这里是我根据这些信息修改后的数组结构:

array(
    'Party' => array(...),
    'Email' => array(...),
    'Address' => array(
        'Country' => 'attribute',
        'Location' => 'attribute',
        'State' => 'attribute'
    ),
    'PhoneNumber' => array(...),
    'Person' => array(
        'Language' => array(...),
        'Skill' => array(...),
        'Employee' => array(
            'WorkHistory' => array(...),
            'Qualification' => array(...)
        )
    )
)

Person 直接与 Party 关联,因此不需要嵌套在 Party 中。但是 Employee(Person 的一种)与 Party 没有直接关联,因此在 Party 上调用 saveAll 时要保存 Employee 数据,需要嵌套在 Person 中,因为 Person 模型直接与 Party 关联。 (仅供参考:Party hasOne Person 和 Person hasOne Employee。这是我能想到的在我的数据库中构建继承的最佳方式)。通过以这种方式构建它,应用程序既符合 CakePHP 标准,又能以最小的努力保存数据。

【问题讨论】:

这个人有没有给你解释为什么不使用第一种方式?如果它有效,我会使用它。 这是我询问的关于“可包含”的问题的链接,我试图在我的视图中以表单的方式格式化数组:***.com/questions/24604104/… 发表的评论是“为什么如果你想一开始就违反 CakePHP 约定,那只会造成麻烦……”。但没有解释。然而,响应者并没有真正了解我为什么要这样构建我的数组。所以我想我应该检查一下是否可以,或者是否有理由不这样做。 【参考方案1】:

好吧,解释就在那里,它只是 CakePHP 约定,我们都知道不遵守约定会发生什么,对吧?

正如我所说,遵循约定有助于 CakePHP 自动将所有内容粘合在一起,并且使用您问题中显示的格式需要手动重组您的 Model::find() 调用接收到的数据。

因此,虽然您的问题中显示的结构可能适用于保存(至少目前是这样),但它至少会为您带来一些实际上不必要的额外工作。

我承认我本来可以更清楚一点,因为你似乎误解了我。我不想说数组应该完全是平的,只是Person条目放错了,所以我只提到了那个。

当然,最终这一切都取决于关联的类型,链接文档中有所有示例:Cookbook > Models > Saving Your Data

一般情况下,只要没有任何 HABTM 关联,​​您就可以使用 saveMany()saveAssociated() 尽可能多地保存。

您可以通过参考 Model::find() 返回的结构开始,确保您保存在主模型上(在本例中为 Party),并取决于使用的关联/记录数

save()(单条记录,无关联(HABTM 除外))

saveAll()saveManysaveAssociated 的包装)

saveMany()(多个主模型记录,可能的关联(需要使用deep 选项))

saveAssociated()(单个主模型记录,包括关联(可能需要使用deep选项)

但是这可能不适用于所有情况,如前所述,您可能会遇到HABTM 关联的问题,具体取决于您是否要创建新记录,您可能需要单独保存它们,但这并不是真的解释每一种可能的情况的地方,尤其是因为基本知识已经包含在 Cookbook 中。

我建议您学习文档,遵守约定,边尝试边学习,并查看核心源代码和测试,我们每个人都是这样学习的。当您对尚未涵盖的特定情况有疑问时,只需创建一个新问题

【讨论】:

在食谱中它说“为了保存一条记录及其相关记录,hasMany 有两个以上的深度关联,数据数组应该如下......”。然后它继续给出一个数组结构的例子,它看起来像我为这个问题提供的第一个例子。因此,基于此,虽然我的关联是 hasOne,但我相信我通过提交该格式的数组来遵循约定。我发现如果我不这样做,它就不会保存员工数据。再次感谢您抽出宝贵时间帮助我完成此过程:) @user3394751 不,它看起来不像你的例子,它看起来像我建议的那样,Cartnot 嵌套像你的 Person key ;) 同样,这只是 Person 键,其他的都正确嵌套了! 好的,我想我明白了。我已经修改了我的问题以反映新的数组结构。在食谱示例中,“Cart”没有嵌套在“Person”中,但是“CartItem”嵌套在“Cart”中。基于该逻辑,如果模型直接连接到您调用 saveAll 的模型,则无需嵌套它,但如果不是,则需要将其嵌套在模型中。它是否正确?你能用新的数组结构看看我修改后的问题,然后告诉我你觉得还可以吗?谢谢! @user3394751 我不了解您示例中的所有关系,但是从您所描述的内容来看,到目前为止看起来还不错,是的,您所说的是正确的,直接的-不要嵌套,间接 - 嵌套,除了 HABTM 关联,它们有点特别:) 非常感谢,非常感谢您对此提供的所有帮助。

以上是关于CakePHP 保存非常深的关联模型的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP 2.1 - 模型关联 - 保存和查找

在 CakePHP 中保存时如何验证关联模型是不是存在

CakePHP 2.1 - 保存(和创建)多个连接模型和关联模型

CakePHP - 如何在保存时将关联记录添加到模型中?

CakePHP 模型关联 HasMany - 保存错误

在 Cakephp 3 中保存关联模型