【问题标题】:CakePHP 3 patch entity creates new associated entitiesCakePHP 3 补丁实体创建新的关联实体
【发布时间】:2020-03-23 05:51:14
【问题描述】:

我正在尝试使用具有 ClientContactAddresses 关联的 patchEntity() 函数更新 ClientContactName 实体。 ClientContactName 实体按我的预期更新。然而,即使 ClientContactAddress 是一个现有的实体,patchEntity() 函数也会创建一个 new ClientContactAddress 实体,并将其添加到表中保存。

如果我在视图中包含一个隐藏的 id 字段并将 id 添加为关联数组中的 accessibleField,它确实会更新现有的 ClientContactAddress,但我难以想象这是做事的正确方式。

我的问题是:我如何对修补函数进行编码,以便更新现有关联而不是创建新关联?

关系是 ClientContactName hasMany ClientContactAddresses。下面是我的代码,没有隐藏的id 字段和accessibleField 调整。

我在控制器中的edit() 函数如下所示:

public function edit($id = null) 
{
    $clientContactName = $this->ClientContactNames->get($id, [
        'contain' => [
            'Clients',
            'ClientContactAddresses'
        ]
    ]);
    if ($this->getRequest()->is(['patch', 'post', 'put'])) {
        $data = $this->getRequest()->getData();
        $clientContactName = $this->ClientContactNames->patchEntity(
            $clientContactName,
            $data, [
                'associated' => ['ClientContactAddresses']
            ]
        );
        if ($this->ClientContactNames->save($clientContactName)) {
            $this->Flash->success(__('The client contact has been saved.'));
            return $this->redirect(['controller' => 'Clients', 'action' => 'view', $clientContactName->client->id]);
        }
        $this->Flash->error(__('The client contact could not be saved. Please, try again.'));
    }
    $this->set(compact('clientContactName'));
}

视图如下所示:

<div class="container-fluid clearfix col-lg-10">
    <?= $this->Form->create($clientContactName) ?>
    <fieldset>
        <!--bits that matter-->
        <div class="row stack-row">
            <div class="col-6">
                <?= $this->Form->control('first_name') ?>
            </div>
            <div class="col-6">
                <?= $this->Form->control('last_name') ?>
            </div>
        </div>
        <?= $this->element('address_form', ['showTopper' => true, 'entity' => 'client_contact_addresses.0']) ?>
    </fieldset>
    <?= $this->Form->button(__('Submit'), ['class' => 'btn btn-primary']) ?>
    <?= $this->Form->end() ?>
</div>

这是元素:

<?php
$prefix = ((empty($entity)) ? '' : $entity . '.');
if (!empty($showTopper)):
?>
<div class="row stack-row">
    <div class="col">
        <legend class="sub-topper"><?= __('Address') ?></legend>
    </div>
</div>
<?php endif; ?>
<div class="row stack-row">
    <div class="col-lg-6">
        <?php
        echo $this->Form->control($prefix . 'address_1');
        echo $this->Form->control($prefix . 'address_2');
        echo $this->Form->control($prefix . 'address_3');
        ?>
    </div>
</div>
<!--etc.-->

在打补丁之前,实体的相关部分如我所料,即[new]设置为false:

object(App\Model\Entity\ClientContactName) {
    'id' => (int) 1,
    'first_name' => 'xxxx',
    'last_name' => 'xxxx',
    'client_id' => (int) 19,
    'client_contact_addresses' => [
        (int) 0 => object(App\Model\Entity\ClientContactAddress) {
            'id' => (int) 12,
            'address_1' => 'xxxx',
            'address_2' => 'xxxx',
            'address_3' => 'xxxx',
            etc...
            'client_contact_name_id' => (int) 1,
            '[new]' => false,
            '[accessible]' => [
                'address_1' => true,
                'address_2' => true,
                'address_3' => true,
                etc.
                'client' => true
             ],
            '[dirty]' => [],
            '[original]' => [],
            '[virtual]' => [],
            '[hasErrors]' => false,
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'ClientContactAddresses'
     }],
     //..//

请求数据显示地址字段值。虽然因为我没有隐藏的 id 字段,所以不会出现 id 值:

'first_name' => 'xxxx',
'last_name' => 'xxxx',
'client_contact_addresses' => [
    (int) 0 => [
        'address_1' => 'xxxx',
        'address_2' => 'xxxx',
        'address_3' => 'xxxx',
        etc.
    ]
],

并且在打补丁之后,新实体就创建好了,即[new]设置为true:

object(App\Model\Entity\ClientContactName) {

    'id' => (int) 1,
    'first_name' => 'xxxx',
    'last_name' => 'xxxx',
    'client_id' => (int) 19,
    'client_contact_addresses' => [
        (int) 0 => object(App\Model\Entity\ClientContactAddress) {
            'address_1' => 'xxxx',
            'address_2' => 'xxxx',
            'address_3' => 'xxxx',
            etc.
            '[new]' => true,
            '[accessible]' => [
            'address_1' => true,
            'address_2' => true,
            'address_3' => true,
            etc.
            'id' => true
            ],
            '[dirty]' => [
                'address_1' => true,
                'address_2' => true,
                'address_3' => true,
                etc.
            ],
            '[original]' => [],
            '[virtual]' => [],
            '[hasErrors]' => false,
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'ClientContactAddresses'

        }],
     //..//

【问题讨论】:

    标签: php cakephp associations cakephp-3.0


    【解决方案1】:

    您不需要使 id 字段可访问,实际上您真的不应该这样做,因为这可能会带来安全风险。

    您需要做的就是在数据中传递记录的 ID。编组器需要该值,以便能够确定要使用其余数据修补哪些现有实体。

    使用隐藏字段传递 ID 绝对没问题。表单助手在为主键列生成控件时会自动选择隐藏字段。

    另见

    【讨论】:

    • 谢谢。伙计,你很了解 CakePHP。你是它的设计者吗?如果你是,我想让你知道,我认为这是一部了不起的作品。
    • @Ambie 不客气,不,我既不是创始人也不是核心开发者,只是用户和偶尔的贡献者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多