Ответ 1
Проблема в формате security_id
и Security.id
: char не поддерживается.
Я нашел этот ticket (но я не нашел ссылки в документации)
вы должны создать другой столбец с числовым id
для использования в ассоциации HABTM
У меня есть 2 модели, Client
и Security
. Они связаны с отношением HATBTM.
Я сделал таблицу соединений под названием clients_securities
. Таким образом, Client
может иметь много ценных бумаг, а Security
может принадлежать многим Client
s.
Вот мои определения отношений:
//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), если это имеет какой-либо эффект. Это не поле автоматического инкремента, оно содержит тикер безопасности, и каждый из них уникален.
Проблема в формате security_id
и Security.id
: char не поддерживается.
Я нашел этот ticket (но я не нашел ссылки в документации)
вы должны создать другой столбец с числовым id
для использования в ассоциации HABTM
измените ввод формы следующим образом:
echo $this->Form->input('Security.Security');
<?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
Я попробую...
Вы забыли $this- > Client- > read(); после $this- > Client- > id = $id; в функции edit() (внутренняя часть $this- > Client не инициализируется, поэтому клиентский_ид не присутствует в момент сохранения). Вызов "findById" возвращает только массив, но не будет считывать данные объекту $this- > Client.
Просто хорошая образованная догадка..
Возможно, я worng, но, я думаю, вы забыли создать скрытый ввод с идентификатором клиента в своем представлении
echo $this->Form->hidden('Client.id');
Его не заполняющая таблица медиаторов, поскольку после заполнения обеих моделей у нее нет своего идентификатора для заполнения таблицы медиатора. Таким образом, функция 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');
и не создавать шаблоны для обеих моделей