【问题标题】:Saving model in afterSave() in cakePHP在 cakePHP 的 afterSave() 中保存模型
【发布时间】:2011-05-17 10:28:08
【问题描述】:

我有一个包含文件上传字段的表单,并且我创建了一个模型行为文件来处理文件处理。

我有两个函数,beforeSave和afterSave:

在 beforeSave 中我做了一些事情,然后将 data 中的文件值设置为 null 以便可以保存它。否则它将尝试保存一个数组,而数据库只需要一个字符串(文件名)

在 afterSave 中,我根据表单上的一些文本字段生成一个新文件名,并在其前面添加 lastInsertId。我还将文件从临时移动到所需位置。 这一切都很好,但是当我尝试将新文件名保存到模型时它就不起作用了。

我做了很多测试和调试,也花了几个小时在网上搜索。结论是afterSave不能保存,它会自己触发,会再次运行beforeSave。

所以我的问题是,如何更新新插入的模型?插入的文件名需要在其名称中包含主键,并且在 beforeSave 时是未知的。

感谢您的帮助! 杰森

【问题讨论】:

    标签: php cakephp frameworks


    【解决方案1】:

    如果您想在 afterSave() 本身中绕过所有回调(afterSave/beforeSave),我发现这种语法对我有用:

    $this->save($data, array('callbacks'=>false));
    

    要禁用触发器,手册确实指出:

    save 方法还有另一种语法:

    保存(数组 $data = null,数组 $params = 数组()) $params 数组可以有以下任何可用选项作为键:

    array(
         'validate' => true,
         'fieldList' => array(),
         'callbacks' => true //other possible values are false, 'before', 'after' )
    

    【讨论】:

      【解决方案2】:

      这样就可以了

      // Its your model Image.php
      function afterSave($created) {
          if($created) {
               // its new record
               // do your work here
          }
      }
      

      小调整不推荐

      如果你想在 afterSave() 中绕过数据库操作的 beforeSave ,请使用 $this->Model->query() ,而不是 $this->Model->save();

      // little hack to bypass beforeSave
      $this->Model->query('UPDATE listings SET name="xx" WHERE id="1"');
      

      【讨论】:

      • 这就是我做的地方,但它不起作用。它似乎再次启动 beforeSave ,因为这就是我正在做的事情,正在保存。
      • @jason,如果您再次尝试保存它,它会在 beforeSave 之前触发。后保存内。尝试添加到帖子中,让我知道会发生什么
      • 你是什么意思?如何使用 query() 保存?
      • @Jason 试试这个book.cakephp.org/view/456/query,它不支持 beforeSave 方法。
      【解决方案3】:

      理想情况下,如果您的文件名依赖于数据库中的其他列,则您无需再次重新保存模型数据。实际上,它会在表的架构中引入相互依赖的列,这违背了规范化。

      例如。如果您的文件名格式为“textfield1-textfield2-yourid.ext”,则应将textfield1textfield2ext 的值存储在数据库中。然后,在模型的 afterFind() 方法中,您可以循环遍历结果,将生成的文件名创建为数据数组中的新字段。

      示例表架构:

      id | textfield1 | textfield2 | extension | created | modified
      

      示例查看代码:

      echo $this->Html->image("{$data['Picture']['textfield1']}-{$data['Picture']['textfield2']}-{$data['Picture']['id']}.{$data['Picture']['extension']}");
      

      当然,就像我之前提到的,如果您覆盖模型中的 afterFind() 并创建一个名为“文件名”的新字段,这可以简化。更多关于 here.

      这会将您的代码缩短为:

      echo $this->Html->image($data['Picture']['filename']);
      

      并且还可以更容易地在任何时候进行通用修改。

      【讨论】:

        【解决方案4】:

        就个人而言,保存模型后,所有文件处理都应在控制器(或组件)中完成。我认为模型不应该根据 MVC 设计来管理文件。

        在你的控制器中

        // Save model
        if ($model->save()) {
            // Save your file
            ...
            // Update the model
            $model->updateField();
        } 
        
        $model->save();
        

        希望对您有所帮助。

        【讨论】:

        • 谢谢,我会考虑的。但目前我更愿意走我正在走的路线,即使它可能违反 mvc 设计。无论如何,这段代码只是为了我的眼睛:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多