CakePhp ::创建/插入查询时缺少字段

时间:2014-02-05 21:29:06

标签: php cakephp constraints cakephp-2.3

我是CakePhp的新手,目前正在尝试使用故障单,事件,任务,用户等实现简单的故障单系统。在基本CRUD功能下,通过ajax调用已标记状态的故障单应生成新故障单(表示工作流中的下一步)。

然而,Ticket::afterSave()中通过ajax回调$this->saveField()时创建的下一张故障单最终会因完整性约束违规而失败,而'正常烘焙'{{1调用工作。 Cake似乎忽略了生成的edit()上的一些待保存字段 MySQL INSERT INTO声明,我无法提出解释。

这里是故障单的模型......

$this->save()

<? class Ticket extends AppModel { // [...] public function update($status) { return $this->saveField('status', $status); } public function afterSave($created, $options = array()) { //[...] if ticket state was changed to done: // generate data for Ticket with next Task in Workflow $this->Event->id = $this->field('event_id'); $ticketData = $this->Event->generateNext(); // check if data is correct debug($ticketData); // create new ticket $this->create(); return $this->save($ticketData); } } Ticket belongs_toUserTask已完成故障单的事件会生成下一张故障单的数据{ {1}}(在LinkableBehavior的帮助下,因为containsable似乎不支持深层条件)。数据是正确的,总是上面的调试打印如下:

Event

但是当ajax调用Event->generateNext()函数时,创建失败并显示:

array(

    'Ticket' => array(
        'event_id' => '11720',
        'task_id' => '9',
        'user_id' => '1',
        'status' => 'Requested')
    )

...显示SQL查询:

update

正如您所看到的,生成的查询完全错过了Error: [...] Integrity constraint violation: Cannot add or update a child row: a foreign key constraint fails (`table`.`tickets`, CONSTRAINT `fk_tickets_users1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) [...]) 的字段,这当然会导致创建失败。但调试证明了它们的存在?!混乱。 在烘焙的'INSERT INTO `table`.`tickets` (`status`, `modified`, `created`) VALUES ('Requested', '2014-02-05 22:00:32', '2014-02-05 22:00:32')' 函数中调用user_id时,查询结果很好:

Ticket::save()

我想我可以使用像edit这样的自定义查询来避免这种行为吗?但我更愿意了解不同的结果并将其作为“蛋糕方式”。 我希望这在某种程度上是可以理解的,并且非常感谢任何帮助。

很多,非常感谢提前!

1 个答案:

答案 0 :(得分:0)

由于您是在初始更新状态字段后从Ticket本身的afterSave()方法中创建新故障单,因此模型的白名单将设置为您最初保存的唯一字段(状态)。

将丢弃所有其他字段
$this->save($ticketData);

将其更改为:

$this->save($ticketData, false, array(
    'event_id',
    'task_id',
    'user_id',
    'status'
);

注意对afterSave()的递归调用。上面调用$ this-&gt; afterSave()将在afterSave()之后再次调用。