Search code examples
zend-frameworkzend-db

Zend Framework 1.12, execution of raw SQL inserts the same record twice


I know there´s a similar situation in stack, and I´ve already checked it out and the answers have not guided me to mine.

Here´s the deal:

I need to execute raw SQL, an INSERT to be precise. I have multiple values to insert as well. No problem since Zend let´s you use "query" from Zend_Db_Table (I use my default adapter, initialized in my application.ini file).

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

When doing var_dump($query); this is what I see:

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

I have already tried the following:

  1. I have no "manifesto" attribute on the html page rendered
  2. I have looked at the network both with Chrome and Firefox to see the POSTS/GETS getting sent, and the controller whose actions does this INSERT gets called once with a POST.
  3. It is true that I call a viewscript from another action to be rendered, like so:

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

    I don´t see how that could affect the statement getting executed twice.

I know it gets executed twice:

  1. Before the POST is sent, the data base has nothing, clean as a whistle
  2. POST gets sent, logic happens, from is rendered again
  3. Data base now has the same record twice (with the name that has been inserted from the POST), so it´s not a rendering problem

It has to do with the way I am executing raw SQL, because if I use ->insert($data) method that comes with Zend_Db_Table_Abstract (obviously I declare a class that extends from this abstract one and bind it to the appropriate table) it does not insert the record twice. Thing is, I want to use raw SQL.

I really appreciate your help!

Expanded as requested:

Controller code:

 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');
}

Code from model class (in charge of saving the form from the data in 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
}

I do want to make clear though that I have also used $db->insert($data), where $db is a class that extends from Zend_Db_Table_Abstract (associated to a table). In this case, the record is inserted once and only once. That´s what leads me to believe that the problem lies within the execution of my raw sql, I just don´t know what is wrong with it.


Solution

  • I should have done this from the beginning, thanks for the help everyone, I appreciate your time.

    I knew the problem was with my syntax, but I didn´t know why. After looking at different examples for how people did the raw sql execution, I still didn´t understand why. So I went ahead and opened the class Zend_Db_Adapter_Abstract in Zend library and looked for the 'query()' method I was using to get the statement to execute.

     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;
        }
    

    So the ->query(..) method from the Zend_Db_Adapter already executes said query. So if I call ->execute() on the statement that it returns, I'll be the one causing the second insert.

    Working code:

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