CakePHP сохраняет данные HABTM

У меня есть 2 модели, Client и Security. Они связаны с отношением HATBTM. Я сделал таблицу соединений под названием clients_securities. Таким образом, Client может иметь много ценных бумаг, а Security может принадлежать многим Client s.

enter image description here

Вот мои определения отношений:

 //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 из мульти-select.

Когда я отправляю форму, таблица clients_securities не заполняется идентификаторами присоединения.

Что мне нужно сделать, чтобы сохранить его правильно и затем сохранить сохраненные ценные бумаги, когда я перезагружу "редактирование".


Изменить: Чтобы прояснить ситуацию, вот pr() of $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
                )

        )

)

Итак, по существу, скажем, мой идентификатор клиента был 12345, Cake должен вставить 2 записи в таблицу clients_securities, например:

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

Если я вручную добавлю некоторые записи объединений в clients_securities, когда я перехожу к редактированию клиента, ценные бумаги в мульти-select правильно выбираются правильно, показывая, что данные считываются из таблицы соединений. Когда я сохраняю форму, она фактически удаляет записи соединения, но не сохраняет новые.

Примечание: Мои идентификаторы безопасности хранятся как CHAR (36), если это имеет какой-либо эффект. Это не поле автоматического инкремента, оно содержит тикер безопасности, и каждый из них уникален.

Ответ 1

Проблема в формате security_id и Security.id: char не поддерживается.

Я нашел этот ticket (но я не нашел ссылки в документации)

вы должны создать другой столбец с числовым id для использования в ассоциации HABTM

Ответ 2

измените ввод формы следующим образом:

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

Ответ 3

<?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

Ответ 4

Я попробую...

Вы забыли $this- > Client- > read(); после $this- > Client- > id = $id; в функции edit() (внутренняя часть $this- > Client не инициализируется, поэтому клиентский_ид не присутствует в момент сохранения). Вызов "findById" возвращает только массив, но не будет считывать данные объекту $this- > Client.

Просто хорошая образованная догадка..

Ответ 5

Возможно, я worng, но, я думаю, вы забыли создать скрытый ввод с идентификатором клиента в своем представлении

echo $this->Form->hidden('Client.id');

Ответ 6

Его не заполняющая таблица медиаторов, поскольку после заполнения обеих моделей у нее нет своего идентификатора для заполнения таблицы медиатора. Таким образом, функция beforeSave и afterSave пользователя заполняет вашу таблицу посредников. Добавить функцию 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- > сохранения в вашем контроллере.

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

И yah As @Arilia сказал, что изменил ваше поле ввода форума

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

и не создавать шаблоны для обеих моделей