0

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.

Community
  • 1
  • 1
Chayemor
  • 3,577
  • 4
  • 31
  • 54
  • 1
    Do you have any other resources on the page in the HTML that might be loading the same page? For example, I've noted that people sometimes have an expired CSRF token if they have a broken image on the page (this is because the site loads a 404 which completes the 'hops' that the CSRF token is good for). Is it possible that you're loading this page - by accent - through a broken or redirecting resource? – Aaron Saray Jun 16 '13 at 00:02
  • That page does have a small icon but it is always found, there is no 404 error displayed. When viewing the network communication, there is only one POST getting sent, not two. ¿? – Chayemor Jun 16 '13 at 13:50
  • 2
    It sounds like you re-render the form after post. Typically, one would redirect after post (see [Post/Redirect/Get](http://en.wikipedia.org/wiki/Post/Redirect/Get)). Perhaps the after-post form rendering is triggering a second insert? We'd probably need to see the full code of the controller action. – David Weinraub Jun 16 '13 at 15:22
  • I agree with @DavidWeinraub - posting more of the code will help us diagnose better. – Aaron Saray Jun 16 '13 at 16:01
  • On re-reading, this bit caught my eye: "the name added before sending the post appears on the data-base". Is your issue that a second POST does an insert when you really want an update? Or it really that a single POST results in two inserts? – David Weinraub Jun 17 '13 at 02:38
  • @DavidWeinraub I fixed that bit, sorry for that bad explanation, I hope with the edit it´s a bit more clear. It's a single POST that somehow is inserting the same record twice :s I´ve looked at it all, there is no second POST, there is no other HTML element that causes a second rendering and somehow calls the action again with a POST, it´s just..baffling. – Chayemor Jun 17 '13 at 08:51
  • @Joy, I'm pretty sure `saveForm()` is just called once, since you even check if the request is POST... a redirect would result in a GET request. Just to make sure, add `file_put_contents('/tmp/passes.out', "Passed here...\n", FILE_APPEND);` inside your `saveAction` function right before the `saveForm()` call and then check how many strings were echoed to the file. Probably the problem resides in the `saveForm` function, can you paste the code to it? – Rolando Isidoro Jun 17 '13 at 10:03
  • @DavidWeinraub I followed your advice, and while the url can now be bookmarked, it is still doing the double-insert. – Chayemor Jun 17 '13 at 12:24
  • @RolandoIsidoro I did as you suggested, and after running it this is what the file had: "Passed here..." It only appeared once. Like I´ve said, there is only one POST getting sent, I´m very sure of it. I believe the problem is within the syntax itself, but I don´t know why. – Chayemor Jun 17 '13 at 12:26
  • @Joy, from [Zend_Db_Table_Abstract::update() api documentation](http://framework.zend.com/apidoc/1.12/files/Db.Table.Abstract.html#\Zend_Db_Table_Abstract::update()): `Returns - int - The number of rows updated.` What value does your `$db->update` call return? If it returns 1 then the problem must be in the `foreach` and those calls to `_save_` something methods. – Rolando Isidoro Jun 17 '13 at 13:07

1 Answers1

4

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);
Chayemor
  • 3,577
  • 4
  • 31
  • 54