CakePHP 奇怪的 saveAll 问题。返回 true,但在数据库中没有任何内容

Posted

技术标签:

【中文标题】CakePHP 奇怪的 saveAll 问题。返回 true,但在数据库中没有任何内容【英文标题】:CakePHP bizarre saveAll issue. Returns true, but nothing in database 【发布时间】:2010-11-02 16:35:03 【问题描述】:

我有两个模型,Statement -> hasMany -> LineItem

我在Statement 的方法之一中将以下数组传递给$this->saveAll()

$data = array(
    'Statement' => array(
        'employee_id' => 1
    ),
    'LineItem' => array(
        0 => array('job_id' => 1),
        1 => array('job_id' => 9),
        2 => array('job_id' => 12),
    )
);

$this->saveAll($data) == true,但是当我检查数据库中的statements 表时,它是空的。奇怪的一点? id 列的 auto_increment 增加了 1。$this->Statement->id 与表的当前 auto_increment 匹配也反映了这一点。

line_items 表也适用上述所有情况,只是 auto_increment 增加了 3。

更新

当使用$this->save($data) 时,Statement 被正确保存(当然,没有LineItem 记录)。那么,saveAll 是怎么回事?

更新

所以,我想问题出在我的控制器或模型的某个地方。一些愚蠢的doh!时刻我敢肯定。这是来自我的控制器和模型的代码(为简洁起见,删除了 cmets 和不相关的代码)。

一、型号:

class Statement extends AppModel 
    public $belongsTo = array('CompanyStatement', 'Employee');
    public $hasMany = array('LineItem');
    public $name = 'Statement';

    public function build_statement($data = NULL) 
        if (!empty($data)) 
            if ($this->saveAll($data)) 
                $result = array(
                    'message' => 'Statement was saved.',
                    'element' => 'flash_success',
                    'success' => TRUE
                );
             else 
                $result = array(
                    'message' => 'There was a problem saving.',
                    'element' => 'flash_error',
                    'success' => FALSE
                );
            
         else 
            $result = array(
                'message' => 'No data was received.',
                'element' => 'flash_error',
                'success' => FALSE
            );
        
        return $result;
    

和控制器:

 class StatementsController extends AppController 
    public $name = 'Statements';

    public function create_new_statement() 
        $result = $this->Statement->build_statement($this->data);
        $this->Session->setFlash($result['message'], $result['element']);
        $this->redirect(array(
            'controller' => 'statements',
            'action' => 'edit',
            $this->Statement->id
        ));
    
    public function edit($id = NULL) 
        $this->set('statement' => $this->Statement->findById($id));
    
 

LineItem 模型非常简洁:

class LineItem extends AppModel 
    public $name = 'LineItem';
    public $belongsTo = array('Statement', 'Job');

到达目的地

我在控制器方法中关闭了重定向,并查看了SQL转储:

Warning (512): SQL Error: 1452: Cannot add or update a child row:
a foreign key constraint fails (`database`.`line_items`,
CONSTRAINT `line_items_ibfk_1`
FOREIGN KEY (`statement_id`) REFERENCES `statements` (`id`)
ON DELETE CASCADE ON UPDATE NO ACTION)

[CORE\cake\libs\model\datasources\dbo_source.php, line 681]

Query: INSERT INTO `line_items` (`job_id`, `modified`, `created`) VALUES (1, '2010-11-02 15:22:39', '2010-11-02 15:22:39') 
Query: INSERT INTO `line_items` (`job_id`, `modified`, `created`) VALUES (9, '2010-11-02 15:22:39', '2010-11-02 15:22:39') 
Query: INSERT INTO `line_items` (`job_id`, `modified`, `created`) VALUES (10, '2010-11-02 15:22:39', '2010-11-02 15:22:39')  

事务正在回滚。

那么为什么在使用 saveAll 时没有将statement_id 添加到事务中的查询中?

【问题讨论】:

当您尝试在没有关联数据的情况下保存它时会发生什么? 我会尽力在 5 分钟内通知您。 框架是可靠的 - 怀疑是用户错误:P @f00: 同意...另外,我在应用程序的另一部分使用 saveAll 没有失败。 【参考方案1】:

当我忘记提交事务时,每隔一段时间就会发生这种情况。您是否禁用了自动提交?你在使用交易吗?您是否忘记提交或告诉 cakePHP 您需要提交?

【讨论】:

我想相信它与交易有关。但是当在 InnoDB 表上使用 saveAll 方法时,CakePHP 应该自动为我处理事务。我以前用过它而不必“提交”任何东西。 仅供参考 - 我不使用或不知道 CakePHP,当我开发其他应用程序时,这只是偶尔会咬我。即使 CakePHP 正在管理您的事务,也可能值得检查一下。神秘的递增列是回滚的好兆头。 感谢 bot403。我越来越确定你是对的。让我们假设问题不在于 CakePHP。这两个表目前都是空的。什么会导致交易失败? 不调用 commit() for one ;) 在不调用 commit 的情况下退出将导致自动回滚。未捕获的外键错误也会导致它。你查看过你的 InnoDB 日志吗? mysql 中的“show engine status innodb”可以让你更好地了解失败的事务。 好吧..我已经将问题归结为 CakePHP 没有正确构建我的查询。【参考方案2】:

默认情况下,Cake 会期望 line_items 上的外键是 statement_id。您还没有显示表结构。 line_items 上是否真的有一列 statement_id?

【讨论】:

是的。 line_items 具有以下列:id int(10)statement_id int(10)job_id int(10)created datetimemodified datetime 获胜者是.... Leo!我的专栏中有错字。在 line_items 表中,列 statement_id 被错误地命名为 statment_id。我知道这是一个Doh!的时刻。谢谢! 没问题。这是我一生的故事!【参考方案3】:
$this->saveAll();

不行,试试吧:

$this->Statement->saveAll();
/* or */
$this->LineItem->saveAll();

【讨论】:

什么?我在Statement 模型中。 在控制器中使用保存方法更为常见,实际上书中的示例都在控制器中。由于您没有声明您在模型中执行此操作,因此 PawelMysior 的评论是完全有效的。您是否尝试过在控制器中执行此操作?这似乎不太可能,但无论如何,编写方法的方式可能是期望的。 +1 更正。 @Leo:你的评论没有任何意义。控制器中不存在保存方法。当您在控制器中执行$this->Model->saveAll() 之类的操作时,您仍在从模型中保存。食谱示例是为初学者理解而编写的。试图强制使用瘦控制器的概念将超出文档的范围。我的第二句话表明我在Statement 模型中。这很明显,因为控制器将被命名为StatementsController。此外,Pawel 的声明“$this->saveAll(); 将不起作用”是 100% 错误的。 如果这个问题被重新措辞表明我应该尝试在控制器方法中使用模型链而不是直接在模型方法中保存数据,它将包含更少的不准确性,但仍然不正确. @stephen:Pawel 的声明“$this->saveAll(); 不起作用” - 这是因为大多数人在控制器中执行此操作。我的评论很有道理。如果在本论坛中严格应用命名约定,您对第二句话的评论将是正确的 - 但事实并非如此。

以上是关于CakePHP 奇怪的 saveAll 问题。返回 true,但在数据库中没有任何内容的主要内容,如果未能解决你的问题,请参考以下文章

避免 CakePHP 的 saveAll 并使用手动查询

CakePHP:用户数据 saveAll 静默失败?

cakephp:使用 saveAll(),导入的(非表单相关的)关联数据不保存

CakePHP saveAll 方法

CakePHP 使用 saveAll:如何使用 HABTM 链接记录保存额外数据?

CakePHP 使用 3 个带有 saveAll 的模型