【问题标题】:Duplicate model along with it's associations复制模型及其关联
【发布时间】:2015-09-03 13:44:44
【问题描述】:

我遇到了this post,它给出了有关如何执行此操作的答案,但它对我来说不太有效。

我有一个名为 SitePage 的模型,它有许多 SitePageGroup,而 SitePageContent 又是许多 SitePageContent

// SitePage Model
public $hasMany = array(
    'SitePageGroup' => array(
        'className' => 'FoCMS.SitePageGroup',
        'foreignKey' => 'site_page_id',
        'dependent' => FALSE,
    ),
);

// SitePageGroup Model
public $belongsTo = array(
    'SitePage' => array(
        'className' => 'FoCMS.SitePage',
        'foreignKey' => 'site_page_id',
    ),
);

public $hasMany = array(
    'SitePageContent' => array(
        'className' => 'FoCMS.SitePageContent',
        'foreignKey' => 'site_page_group_id',
        'dependent' => FALSE,
    ),
);

// SitePageContent Model
public $belongsTo = array(
    'SitePageGroup' => array(
        'className' => 'FoCMS.SitePageGroup',
        'foreignKey' => 'site_page_group_id',
    ),
);

使用该链接问题中的答案,我看到父模型 SitePage 被复制,但相关模型已从原始模型中删除并与新模型相关联。

$record = $this->SitePage->find('first', array('condition' => array('SitePage.id' => $id)));
unset($record['SitePage']['id'], $record['SitePageGroup']['id'], $record['SitePageGroup']['SitePageContent']['id'] /* further ids */);
$this->SitePage->create();
$record['SitePage']['name'] = $record['SitePage']['name'].'-copy';
$record['SitePage']['friendly_name'] = $record['SitePage']['friendly_name'].' Copy';
if($this->SitePage->saveAll($record)){
    $this->Session->setFlash('The site page has been saved', 'fo_message');
    $this->redirect(array('action' => 'index'));
}else{
    $this->Session->setFlash('The site page could not be saved. Please, try again.', 'fo_message');
}

更新

调试我尝试重置的记录我看到以下内容

array(
    'SitePage' => array(
        'name' => 'test',
        'friendly_name' => 'Test',
        'order' => '82',
        'created' => '2015-09-03 19:16:40',
        'modified' => '2015-09-03 19:20:27'
    ),
    'SitePageGroup' => array(
        (int) 0 => array(
            'id' => '55e88087-a4dc-4c37-89dc-f9c172b40463',
            'site_page_id' => '55e88078-16c8-46ce-bf02-fa5372b40463',
            'name' => 'group-1',
            'friendly_name' => 'Group 1',
            'order' => '1',
            'created' => '2015-09-03 19:16:55',
            'modified' => '2015-09-03 19:16:55'
        ),
        (int) 1 => array(
            'id' => '55e8809e-d018-4ebe-a4cf-fbef72b40463',
            'site_page_id' => '55e88078-16c8-46ce-bf02-fa5372b40463',
            'name' => 'group-2',
            'friendly_name' => 'Group 2',
            'order' => '2',
            'created' => '2015-09-03 19:17:18',
            'modified' => '2015-09-03 19:17:18'
        )
    )
)

我得到这个结果的方法就是这样做

$sitePage = $this->SitePage->find('first', array(
    'conditions' => array(
        'SitePage.id' => $id,
    ),
));

unset($sitePage['SitePage']['id'], $sitePage['SitePageGroup']['id'], $sitePage['SitePageGroup']['SitePageContent']['id'], $sitePage['SitePageGroup']['site_page_id'], $sitePage['SitePageGroup']['SitePageContent']['site_page_group_id'] /* further ids */);
debug($sitePage);
die();

但也正如您在调试输出中看到的那样,没有包含关联模型的第 3 级,每个 SitePageGroup 也应该有一个 SitePageContent

我认为 SitePageGroup 数组上的简单循环应该重置 id 并将外键设置为 null,但我想我还需要以某种方式包含属于 SitePageGroupSitePageContent 以便我可以也重置那些。

【问题讨论】:

  • HasMany 就是这样做的。模型可以“拥有许多”关联模型。所以通过定义“SitePage hasMany SitePageGroup”,每个SitePage可以有多个SitePageGroup。如果您想在所有三个模型之间共享通用方法,我建议添加一个扩展 AppModel 的新模型类,并且三个模型都扩展了新模型。
  • 是的,我知道关联是如何工作的,我特别想弄清楚如何复制父模型并保持所有关联的模型。
  • 链接问题中的代码现在似乎发生了什么,相关模型正在移动到重复条目并从原始条目中删除。
  • 好的。最简单的方法是获取所有数据,然后从数组中删除 all id 并使用 saveAll 保存该数组。

标签: cakephp model associations duplication


【解决方案1】:

您需要确保在保存之前将所有主键和外键设置为null。您似乎只是在重置模型的主键,但 Cake 需要知道需要生成外键,以便它们引用新记录。

在调用 $record 之前,可能值得使用 debug($record); 检查该数组中的所有内容是否已正确设置/重置,以确保副本按预期工作。

更新

根据您在更新后的问题中发布的数组内容,您似乎没有从保存数据中删除所有主键和外键。您需要确保将这些从您要保存的所有内容中删除,包括有许多关联。

如果您查看您的数组,您应该能够看到 unset($sitePage['SitePageGroup']['id']) 不会删除您的 SitePageGroup 数据的主 ID,因为您取消设置的内容与您的 $sitePage 数组中的数组路径不对应。

您可以使用 CakePHP 的 Hash utility to remove 数组中的主键,如下所示:-

$sitePage = Hash::remove($sitePage, 'SitePageGroup.{n}.id');

对于外键也是如此:-

$sitePage = Hash::remove($sitePage, 'SitePageGroup.{n}.site_page_id');

【讨论】:

  • 我对问题进行了更新,包括我收到的调试输出以及我用来实现它的当前代码。
  • @Jordan,查看您的数据,您并没有按照我的回答中的建议取消设置所有主键和外键。我已经更新了我的答案,以便为您提供更多细节。
  • 就是这样!我还必须contain 更深层次的关联,清除这些关联,并将deep 选项添加为真到saveAll() 方法,这样也可以保存。
猜你喜欢
  • 2016-11-02
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多