【问题标题】:Cakephp's beforeSave not retaining new data when using saveAll?Cakephp的beforeSave在使用saveAll时不保留新数据?
【发布时间】:2011-06-14 19:56:53
【问题描述】:

我有一个相对简单的条目模型,只有五个字段:

  1. 身份证
  2. 类型(此条目是什么数据类型)
  3. 数量(无论是多少)
  4. unit(类型的单位)
  5. 日期(输入此条目的日期时间)
  6. user_id(进入用户的id

所以,没什么特别的。现在一个表单可以有多个条目(现有的和刚刚创建的新条目),表单通过 ajax 调用进行扩展。

当我提交表单时$this->data 看起来像这样:

Array
(
    [Entry] => Array
        (
            [date] => 2011-01-07
            [0] => Array
                (
                    [id] => 1
                    [type] => Eat
                    [amount] => 1 Steak, one baked potatoe
                    [unit] => lunch
                    [time] => Array
                        (
                            [hour] => 13
                            [min] => 31
                        )

                )

            [1] => Array
                (
                    [type] => weight
                    [amount] => 78.5
                    [unit] => KG
                    [time] => Array
                        (
                            [hour] => 22
                            [min] => 22
                        )

                )

        )

)

$this->data['Entry']['date'] 中的第一个条目是所有条目应使用的日期。由于还缺少 user_id,我在入口模型中创建了一个“beforeSave”函数。它看起来像这样:

function beforeSave() {
    App::import('Component','Session');
    $this->Session = new SessionComponent();

    if (isset($this->data) && isset($this->data['Entry'])) {
        $date = $this->data['Entry']['date'];
        unset($this->data['Entry']['date']);

        foreach ($this->data['Entry'] as $n => $entry) {
            if (is_array($entry)) {
             $this->data['Entry'][$n]['date'] = $date . ' ' . $entry['time']['hour'] . ':' . $entry['time']['min'] . ':00';
                $this->data['Entry'][$n]['user_id'] = $this->Session->read('Auth.User.id');
            }
        }
        debug($this->data);

    }
    return true;
}

我删除日期,将它与用户的时间条目一起添加,从而创建一个mysql日期时间条目并添加登录用户的user_id。直截了当,真的。结果数组(作为最后一个 debug() 的输出)如下所示:

Array
(
    [Entry] => Array
    (
        [0] => Array
            (
                [id] => 1
                [type] => Eat
                [amount] => 1 Steak, 1 baked potatoe
                [unit] => lunch
                [time] => Array
                    (
                        [hour] => 09
                        [min] => 31
                    )

                [date] => 2011-01-07 09:31:00
                [user_id] => 2
            )

        [1] => Array
            (
                [type] => Weight
                [amount] => 78.5
                [unit] => KG
                [time] => Array
                    (
                        [hour] => 22
                        [min] => 22
                    )

                [date] => 2011-01-07 22:22:00
                [user_id] => 2
            )

    )

)

所以它看起来和我想要的完全一样,而且应该很容易保存。但是当我使用$this->Entry->saveAll($this->data['Entry']) 保存所有条目时,它不仅不起作用,而且当我在saveAll 之后直接调试$this->data 时,它看起来就像在saveAll 函数之前一样——日期又回到了数组中,这些条目没有日期或 user_id 条目。

我可以看到调用了 beforeSave,我可以看到它更改了 $this->data,但是在 beforeSave 结束和使用“saveAll”之间的某个地方,我的所有更改都丢失了,$this->data 恢复到原来的状态.因此不会进行任何保存。

【问题讨论】:

    标签: php cakephp callback save


    【解决方案1】:

    据我所知 saveAll() updateAll() 和 deleteAll() 默认不会触发任何回调

    您需要手动启用它们(方法的最后一个参数)

    【讨论】:

    • 不,回调触发得很好,因为 beforeSave 函数中的调试显示新的数据结构没有问题。
    【解决方案2】:

    你不会被验证绊倒吧?

    试试

    $this->Entry->saveAll($data,array('validate'=>false));
    

    如果它有效,那么问题在于验证

    但是不要忘记,如果没有指定主键,您需要在保存单个模型之前使用 create()。也许在 saveAll() 中混合新数据和现有数据是问题所在。

    【讨论】:

    • 不。该模型没有经过验证。另外,由于我将 beforeSave 函数移到了控制器中,所以它工作得很好。我没有改变功能,但是当它在控制器中被调用时,数据结构被保留,当它在 beforeSave 中被调用时,它不是。
    【解决方案3】:

    我在尝试使用 hasMany 进行一些清理时遇到了类似的问题。事实证明,问题在于 saveAll() 的工作原理。控制器中的 $this->data 与 Model::beforeSave() 回调中的 $this->data 不同,两者不同步。当您调用 Model::saveAll() 从控制器传递 $this->data 您明确地为模型提供数据数组的“旧版本”。当您查看 cake/libs/model/model.php 中的 saveAll 定义时,它会执行以下操作:

    if (empty($data)) {
       $data = $this->data
    }
    

    仅此而已,以同步模型中修改后的 $data 数组并通过参数 $data 从控制器传递。解决方案是不将数据传递给 saveAll(),而是先使用 Model::set() 在模型上设置数据,然后调用 Model::saveAll()(不带 $data 参数)。

    【讨论】:

      【解决方案4】:

      当我们调用 SaveAll 时,不会将更新/提交的数据传递给模型的 beforeSave。从这个问题中走出来,

      在模型中创建 tmp_data 数组

      var $tmp_data = array();
      

      在调用 saveall 之前,设置这个变量, 即

      $this->model->tmp_data = $this->data;
      $this->model->saveAll();
      

      然后,修改model->beforeSaveBefore的代码 而不是$this->data use $this->tmp_data

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-29
        • 1970-01-01
        相关资源
        最近更新 更多