【问题标题】:Get original associations after using Containable behavior in CakePHP在 CakePHP 中使用 Containable 行为后获取原始关联
【发布时间】:2018-08-30 08:17:38
【问题描述】:

背景: CakePHP 2.6.3。一个相当稳定的应用程序。创建新行为 (MyCustomBehavior) 以输出一些额外信息。 我有一个模型MyModel 充当Containable(在AppModel 中定义),然后是MyCustom(在MyModel 中定义)。 MyCustomBehavior 的编写方式需要与模型与我的应用程序中的其他模型的关联一起工作。

问题:每当我在MyModelfind() 调用中包含相关模型时,我无法获得MyModel 关联的完整列表,因为Containable 行为会取消绑定未绑定的模型包含。但是,如果我没有在我的find() 选项中设置contain 或设置'contain' => false,一切都会按预期工作。

示例MyModel->belongsTo

public $belongsTo = array(
    'MyAnotherModel' => array(
        'className' => 'MyAnotherModel',
        'foreignKey' => 'my_another_model_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'Creator' => array(
        'className' => 'User',
        'foreignKey' => 'user_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'Approver' => array(
        'className' => 'User',
        'foreignKey' => 'approver_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'Status' => array(
        'className' => 'Status',
        'foreignKey' => 'status_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
);

示例find()

$this->MyModel->find('all', array(
    'fields' => array(...),
    'conditions' => array(...),
    'contain' => array('Approver', 'Status')
));

MyCustomBehavior::beforeFind()MyModel->belongsTo的结果

$belongsTo = array(
    'Approver' => array(
        ...
    ),
    'Status' => array(
        ...
    ),
);

MyCustomBehavior::beforeFind() 中的预期为 MyModel->belongsTo

$belongsTo = array(
    'MyAnotherModel' => array(
        ...
    ),
    'Creator' => array(
        ...
    ),
    'Approver' => array(
        ...
    ),
    'Status' => array(
        ...
    ),
);

明显的解决方案: 解决问题的一种笨方法是简单地在MyModel 中设置Containable 行为而不是AppModel 来控制加载行为的顺序,即@987654349 @。这个解决方案不是最好的,因为其他模型中可能有其他行为依赖Containable,所以Containable的顺序需要在应用程序中的每个模型中明确设置,希望我没有在某个地方破坏应用程序。

在 SO here 上提出了一个类似(相关)的问题,但没有答案。

需要一个更强大的解决方案来满足MyCustomBehavior 的需求,而无需对应用程序的其余部分进行更改并注意任何意外行为。

【问题讨论】:

  • 好吧,我认为有人会发布比我更好的答案,或者至少指出我认为完美的解决方案的潜在问题。由于这篇文章没有太多的活动,我将我的解决方案标记为已接受,直到有人可以提供具有充分理由的更好解决方案。如果值得的话,我不介意改变我接受的解决方案。

标签: cakephp cakephp-2.x


【解决方案1】:

尝试 1 (不完善,容易出错)

恢复所有原始关联的一种方法是调用

$MyModel->resetBindings($MyModel->alias);
$belongsToAssoc = $MyModel->belongsTo;    // will now have original belongsTo assoc

但是,如果我在 find 调用中使用 joins(使用默认 alias)显式加入已关联的模型,则此方法可能无法正常工作(SQL 错误 1066 Not unique table/alias)。这是因为Containable 也会尝试加入由resetBindings() 调用恢复的所有这些表,从而导致使用相同别名执行两次加入。

尝试 2 (完美#,无已知副作用##
进一步挖掘核心Containable 行为和docs 导致我反对由这种行为创建和使用的$MyModel->__backOriginalAssociation$MyModel->__backAssociation(很奇怪,ContainableBehavior 从未使用过$__backContainableAssociation,正如变量名所暗示的那样)执行resetBindings()。因此,我的最终解决方案是简单地检查我的模态是否启用了Containable(在我的情况下是冗余的,因为它附加在AppModel 中并且在整个应用程序中从未禁用或分离)并检查对象是否设置在模型。

// somewhere in MyCustomBehavior
private function __getOriginalAssociations(Model $Model, $type = 'belongsTo') {
    if(isset($Model->__backAssociation['belongsTo']) && !empty($Model->__backAssociation['belongsTo'])) {   // do an additional test for $Model->Behaviors->enabled('Containable') if you need
        return $Model->__backAssociation[$type];
    }

    return $Model->$type;
}

public function beforeFind(Model $Model, $query) {
    // somewhere in MyCustomBehavior::beforeFind()
    ...
    $belongsToAssoc = $this->__getOriginalAssociations($MyModel, 'belongsTo');    // will now have original belongsTo assoc
    ...
return $query;
}

$__backAssociation 临时保存模型关联以允许动态(取消)绑定。 通过合并$Model->belongsTo$Model->__backAssociation['belongsTo'](或hasManyhasOnehasAndBelongsToMany)的结果以包含任何动态绑定的模型,肯定可以进一步改进此解决方案。我不需要它,所以我将跳过合并的代码。


#完美适合我自己的用例和我的应用设置。
## 在我的测试中未发现任何副作用,但受我的专业知识/技能水平的限制。
免责声明:我在这篇文章中的工作已获得 WTF Public License(WTFPL) 许可.所以,用材料做你想做的事。此外,对于因使用上述材料而造成的任何形式的财务、身体或精神损失,我概不负责。在尝试复制/粘贴之前,请自行承担风险并进行自己的研究。不要忘记查看cc by-sa 3.0,因为 SO 说 “根据 cc by-sa 3.0 许可的用户贡献需要注明出处。” (检查此页面上的页脚。我知道您在今天之前从未注意到它!:p)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多