【问题标题】:Zend Framework 1.12, execution of raw SQL inserts the same record twiceZend Framework 1.12,执行原始 SQL 两次插入相同的记录
【发布时间】:2013-06-15 16:25:37
【问题描述】:

我知道堆栈中有一个类似的situation,我已经检查过了,答案并没有引导我找到我的。

这是交易:

我需要执行原始 SQL,准确地说是 INSERT。我也有多个值要插入。没问题,因为 Zend 让您使用 Zend_Db_Table 中的“查询”(我使用默认适配器,在 application.ini 文件中初始化)。

 $db_adapter = Zend_Db_Table::getDefaultAdapter();
 ....query gets built...
 $stmt = $db_adapter->query($query);
 $stmt->execute();

var_dump($query); 时,我看到的是:

INSERT INTO tableName (col1,col2,col3) VALUES ('value1', 'value2', 'value3')

我已经尝试了以下方法:

  1. 我在渲染的 html 页面上没有“manifesto”属性
  2. 我已经使用 Chrome 和 Firefox 查看了网络以查看发送的 POSTS/GETS,以及执行操作的控制器 此 INSERT 会通过 POST 调用一次
  3. 确实,我从另一个要渲染的动作中调用视图脚本,如下所示:

    $this->renderScript('rough-draft/edit.phtml');

    我不明白这会如何影响语句被执行两次。

我知道它被执行了两次:

  1. POST 发送前,数据库什么都没有,干净利落
  2. POST 被发送,逻辑发生,from 再次呈现
  3. 数据库现在有两次相同的记录(名称是从 POST 中插入的),所以这不是渲染问题

这与我执行原始 SQL 的方式有关,因为如果我使用 Zend_Db_Table_Abstract 附带的 ->insert($data) 方法(显然我声明了一个从这个抽象类扩展的类并将其绑定到适当的表)它确实不插入记录两次。问题是,我想使用原始 SQL。

非常感谢您的帮助!

按要求展开:

控制器代码:

 public function saveAction()
{
    $request = $this->getRequest();

    if (!$request->isPost())
        $this->_sendToErrorPage();


    $this->_edit_roughdraft->saveForm($request->getPost());
    $this->view->form = $this->_edit_roughdraft->getForm();
    $this->renderScript('rough-draft/edit.phtml');
}

来自模型类的代码(负责从 POST 中的数据中保存表单):

public function saveForm($form_data) {           
     $db = new Application_Model_DbTable_RoughDrafts();
     $id = $form_data['id'];

     $db->update($this->_get_main_data($form_data), array('id=?' => $id));
     /* Main data pertains to getting an array with the data that belongs to yes/no buttons
     *  and text input. I need to do it as so because the other data belongs to a dynamically 
     * built (by the user) multi_select where the options need to be deleted or inserted, that
     *  happens below
     */

     $multi_selects = array('responsables', 'tareas', 'idiomas', 'habilidades', 'perfiles');
     foreach($multi_selects as $multi_select){
         if(isset($form_data[$multi_select]) && !empty($form_data[$multi_select])){
             $function_name = '_save_'.$multi_select;
             $this->$function_name($form_data[$multi_select], $id);
         }
     }

     $this->_form = $this->createNewForm($id, true);
     //The createNewForm(..) simply loads data from data_base and populates form
}

虽然我也使用了$db->insert($data),但我确实想澄清一下,其中 $db 是从 Zend_Db_Table_Abstract 扩展而来的一个类(关联到一个表)。在这种情况下,记录只插入一次。这就是让我相信问题出在我的原始 sql 执行中的原因,我只是不知道它有什么问题。

【问题讨论】:

  • HTML 中的页面上是否还有其他资源可能正在加载同一页面?例如,我注意到如果页面上有损坏的图像,人们有时会有一个过期的 CSRF 令牌(这是因为该站点加载了一个 404,它完成了 CSRF 令牌适用的“跳跃”)。您是否有可能通过损坏或重定向的资源加载此页面?
  • 该页面确实有一个小图标,但总是可以找到,没有显示 404 错误。查看网络通信时,只有一个 POST 被发送,而不是两个。 ¿?
  • 听起来您在发布后重新渲染表单。通常,发布后会重定向(请参阅Post/Redirect/Get)。也许后期表单渲染正在触发第二次插入?我们可能需要查看控制器操作的完整代码。
  • 我同意@DavidWeinraub - 发布更多代码将帮助我们更好地诊断。
  • 重读时,这一点引起了我的注意:“在发送帖子之前添加的名称出现在数据库中”。当您真的想要更新时,您的问题是第二个 POST 会插入吗?或者真的是一个 POST 会导致两个插入?

标签: zend-framework zend-db


【解决方案1】:

我应该从一开始就这样做,感谢大家的帮助,感谢您的时间。

我知道问题出在我的语法上,但我不知道为什么。在查看了人们如何执行原始 sql 的不同示例之后,我仍然不明白为什么。所以我继续在 Zend 库 中打开类 Zend_Db_Adapter_Abstract 并寻找我用来执行语句的 'query()' 方法。

 public function query($sql, $bind = array())
    {
       ...some logic...

        // prepare and execute the statement with profiling
        $stmt = $this->prepare($sql);
        **$stmt->execute($bind);**

        // return the results embedded in the prepared statement object
        $stmt->setFetchMode($this->_fetchMode);
        return $stmt;
    }

所以 Zend_Db_Adapter 中的 ->query(..) 方法已经执行了上述查询。所以如果我打电话 ->execute() 在它返回的语句中,我将是那个导致第二次插入的人。

工作代码:

$db_adapter = Zend_Db_Table::getDefaultAdapter();
 ....query gets built...
$db_adapter->query($query);

【讨论】:

    猜你喜欢
    • 2018-02-28
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 2017-02-11
    相关资源
    最近更新 更多