11

我有 2 个模型,Client并且Security. 它们与 HATBTM 关系相关联。我制作了一个名为clients_securities. 所以aClient可以有很多证券,aSecurity可以属于很多Clients。

在此处输入图像描述

这是我的关系定义:

 //Client Model:
public $hasAndBelongsToMany = array(
    'Security' =>
        array(
            'className' => 'Security',
            'joinTable' => 'clients_securities',
            'foreignKey' => 'client_id',
            'associationForeignKey' => 'security_id',
            'unique' => true,
        )
);

 //Security Model:
public $hasAndBelongsToMany = array(
    'Client' =>
        array(
            'className' => 'Client',
            'joinTable' => 'clients_securities',
            'foreignKey' => 'security_id',
            'associationForeignKey' => 'client_id',
            'unique' => true,
        )
);

然后,我在客户端控制器中进行了编辑操作并执行了以下操作:

public function edit($id = null) {
        if (!$id) {
            throw new NotFoundException(__('Invalid client'));
        }

        $client = $this->Client->findById($id);
        if (!$client) {
            throw new NotFoundException(__('Invalid client'));
        }

        if ($this->request->is('post') || $this->request->is('put')) {
            $this->Client->id = $id;
            if ($this->Client->saveAll($this->request->data)) {
                $this->Session->setFlash(__('Client has been updated.'));
                return $this->redirect(array('action' => 'edit', $id));
            }
            $this->Session->setFlash(__('Unable to update client.'));
        }

        if (!$this->request->data) {
            $this->request->data = $client;
            $this->set('securities', $this->Client->Security->find('list'));
        }
    }

在我的编辑视图中,我使用 HtmlHelper 构建表单,添加客户端表字段并生成多重选择:

echo $this->Form->create('Client'); //start the form for the client model
echo $this->Form->input('Security'); //generates a multi-select popuplated with securities

此外,我也有Client相同形式的正常直接形式输入。例如

echo $this->Form->input('name'); //Input for the client name
echo $this->Form->input('currency'); //Input for the client currency
...

当呈现表单时,所有这些输入都会生成并填充正确的值,但只保存直接客户端数据,而不是来自多选的 HABTM 数据。

当我提交表单时,clients_securities表中没有填充连接 ID。

我需要做什么才能正确保存它,然后在我重新加载“编辑”视图时预先选择保存的证券。


编辑:为了澄清事情,这里pr()$this->request->data. (值(“ALLCMCT LX Equity”)是securities表的正确外键):

Array
(
    [Client] => Array
        (
            [id] => 1212
            [name] => Example Client
            [currency] => GBP
            [partner] => 
            [risk_category_id] => 4
            [client_code_id] => 1
            [min_cash_balance] => 0
            [active] => 1
            [model] => 0
            [institutional] => 0
            [non_uk_situs] => 0
            [reporting_status] => 0 
        )

    [Security] => Array
        (
            [Security] => Array
                (
                    [0] => .1muslib3 index
                    [1] => .eurib3 index
                    [2] => .ukcpi2 index
                )

        )

)

所以基本上,假设我的客户 ID 是 12345,Cake 应该在表中插入 2 条记录,如下clients_securities所示:

id | client_id | security_id
----------------------------
1  | 12345     | ALLCMCT LX Equity
2  | 12345     | APMKNTD LX Equity

如果我手动将一些连接记录添加到clients_securities中,当我去编辑客户端时,多选中的证券会正确预选,表明正在从连接表中读取数据。当我保存表单时,它实际上删除了连接记录,但不保存新记录。

附加说明:如果有任何影响,我的安全 ID 将存储为 CHAR(36) 。这不是一个自动递增字段,它包含证券的代码并且每个都是唯一的。

4

6 回答 6

5

问题在于security_idand Security.id: char 的格式不受支持。

我找到了这张(但我在文档中没有找到任何参考资料)

您必须创建另一个带有数字的列id才能在 HABTM 关联中使用

于 2013-09-27T06:29:45.277 回答
1

像这样修改表单输入:

echo $this->Form->input('Security.Security');
于 2013-09-24T22:42:00.473 回答
0
<?php 
Model::saveAssociated(array $data = null, array $options = array());

or

Model::saveAll(array $data = null, array $options = array());
?>

欲了解更多信息,请访问:http ://book.cakephp.org/2.0/en/models/saving-your-data.html

于 2013-09-19T11:37:41.247 回答
0

也许我很累,但我猜你忘记在你的视图中创建一个带有客户端 ID 的隐藏输入

echo $this->Form->hidden('Client.id');
于 2013-09-26T14:08:02.520 回答
0

I'll give it a try...

You forgot $this->Client->read(); after $this->Client->id = $id; in the edit() function (the internal of $this->Client are not initialized, so no client_id is present at the moment when save is done). The call "findById" will return only an array, but won't read the data to the object $this->Client.

Just a good educated guess..

于 2013-09-25T19:12:02.223 回答
0

它没有填充中介表,因为在填充了两个模型之后,它没有填充中介表的 ID。因此,用户 beforeSave 和 afterSave 函数将填充您的中介表。在 Client 模型中添加 beforesave 功能

public function beforeSave($options = array()) {
        parent::beforeSave($options = array());
            foreach (array_keys($this->hasAndBelongsToMany) as $model):
                if(isset($this->data[$this->alias][$model])):
                    $this->data[$model][$model] = $this->data[$this->alias][$model];
                    unset($this->data[$this->alias][$model]);
                endif;
            endforeach;
        return true;
    }

在安全用户 AfterSave 功能中,

public $securityIdArray = array();

public function afterSave($created) {
        if($created) {
            $this->securityIdArray[] = $this->getInsertID();
        }
        return true;
    }

首先保存安全性并使用 $securityIdArray 在 $this->Model->save 之后获取安全性 ID 在您的控制器中。

$this->Security->securityIdArray[] = $void['Security']['id'];

是的,正如@Arilia 所说,修改你的论坛输入字段

echo $this->Form->input('Security.Security');

并且不要为两种模型制作单独的表格

于 2013-09-26T21:56:30.913 回答