CakePHP: Action runs twice, for no good reason
Asked Answered
H

9

5

I have a strange problem with my cake (cake_1.2.0.7296-rc2). My start()-action runs twice, under certain circumstances, even though only one request is made.

The triggers seem to be : - loading an object like: $this->Questionnaire->read(null, $questionnaire_id); - accessing $this-data

If I disable the call to loadAvertisement() from the start()-action, this does not happen. If I disable the two calls inside loadAdvertisement():

$questionnaire = $this->Questionnaire->read(null, $questionnaire_id);
$question = $this->Questionnaire->Question->read(null, $question_id);

... then it doesn't happen either.

Why?

See my code below, the Controller is "questionnaires_controller".

function checkValidQuestionnaire($id)
{
    $this->layout = 'questionnaire_frontend_layout';

    if (!$id)
    {
        $id = $this->Session->read('Questionnaire.id');        
    }

    if ($id) 
    {
        $this->data = $this->Questionnaire->read(null, $id);

        //echo "from ".$questionnaire['Questionnaire']['validFrom']." ".date("y.m.d");
        //echo " - to ".$questionnaire['Questionnaire']['validTo']." ".date("y.m.d");


        if ($this->data['Questionnaire']['isPublished'] != 1 
            //|| $this->data['Questionnaire']['validTo'] < date("y.m.d")
            //|| $this->data['Questionnaire']['validTo'] < date("y.m.d")
            )
        {
            $id = 0;
            $this->flash(__('Ungültiges Quiz. Weiter zum Archiv...', true), array('action'=>'archive'));
        }
    }
    else
    {
        $this->flash(__('Invalid Questionnaire', true), array('action'=>'intro'));
    }

    return $id;
}



function start($id = null) {
    $this->log("start");

    $id = $this->checkValidQuestionnaire($id);

    //$questionnaire = $this->Questionnaire->read(null, $id);
    $this->set('questionnaire', $this->data);

    // reset flow-controlling session vars
    $this->Session->write('Questionnaire',array('id' => $id));
    $this->Session->write('Questionnaire'.$id.'currQuestion', null);
    $this->Session->write('Questionnaire'.$id.'lastAnsweredQuestion', null);
    $this->Session->write('Questionnaire'.$id.'correctAnswersNum', null);

    $this->loadAdvertisement($id, 0);

    $this->Session->write('Questionnaire'.$id.'previewMode', $this->params['named']['preview_mode']);

    if (!$this->Session->read('Questionnaire'.$id.'previewMode'))
    {
        $questionnaire['Questionnaire']['participiantStartCount']++;
        $this->Questionnaire->save($questionnaire);
    }        

}




function loadAdvertisement($questionnaire_id, $question_id)
{

    //$questionnaire = array();
    $questionnaire = $this->Questionnaire->read(null, $questionnaire_id);

    //$question = array();
    $question = $this->Questionnaire->Question->read(null, $question_id);

    if (isset($question['Question']['advertisement_id']) && $question['Question']['advertisement_id'] > 0)
    {
        $this->set('advertisement', $this->Questionnaire->Question->Advertisement->read(null, $question['Question']['advertisement_id']));
    }
    else if (isset($questionnaire['Questionnaire']['advertisement_id']) && $questionnaire['Questionnaire']['advertisement_id'] > 0)
    {
        $this->set('advertisement', $this->Questionnaire->Question->Advertisement->read(null, $questionnaire['Questionnaire']['advertisement_id']));
    }

}

I really don't understand this... it don't think it's meant to be this way. Any help would be greatly appreciated! :)

Regards, Stu

Hornbook answered 15/9, 2008 at 15:21 Comment(0)
M
11

Check your layout for non-existent links, for example a misconfigured link to favicon.ico will cause the controller action to be triggered for a second time. Make sure favicon.ico points towards the webroot rather than the local directory, or else requests will be generated for /controller/action/favicon.ico rather than /favicon.ico - and thus trigger your action.

This can also happen with images, stylesheets and javascript includes.

To counter check the $id is an int, then check to ensure $id exists as a primary key in the database before progressing on to any functionality.

Marhtamari answered 9/12, 2008 at 17:1 Comment(2)
+1, this happened to me - I had a div tag with a background image url based on a null value from the DB.Meris
Thanks to you i found that a broken resource was the fault, in my case i make a call to a method in app controller where the method has one call to save(), for one table.. but in some video links (src tags) the data where saved twice.. so i found a 404 resource link not found.. that was the problem...Wargo
I
2

For me it was a JS issue.

Take care of wrap function with jQuery that re-execute JS in wrapped content!

Icon answered 14/10, 2009 at 6:32 Comment(1)
Hi can you please expand upon this, I am noticing the same thing - when i include a <script> tag in my view the controller action for the view is called twice. I am including a javascript file in the view using echo($this->Html->script(....)); if i set inline => false this doesnt happen but i need to have the script inline = true. any advice welcome!Blameful
D
1

You might want to try and find out where it comes from using the debug_print_backtrace() function. (http://nl.php.net/manual/en/function.debug-print-backtrace.php

Democritus answered 15/9, 2008 at 15:56 Comment(1)
Hi! Thanks for the answer. However, it did not help, it just display two times exactly the same steps from the backtrace. This is a CakePHP specific problem, not just PHP.Hornbook
S
1

Had the same problem, with a certain action randomly running 2-3 times. I tracked down two causes:

  • Firefox add-on Yslow was set to load automatically from it's Preferences, causing pages to reload when using F5 (not when loading the page from the browser's address bar and pressing Enter).

  • I had a faulty css style declaration within the options of a $html->link(); in some cases it would end up as background-image: url('');, which caused a rerun also. Setting the style for the link to background-image: none; when no image was available fixed things for me.

Hope this helps. I know this is quite an old post, but as it comes up pretty high in Google when searching for this problem, I thought it might help others by still posting.

Good luck

Jeroen den Haan

Subtraction answered 3/6, 2009 at 7:34 Comment(0)
S
1

I had a problem like this last week.

Two possible reasons

  • Faulty routes (DO check your routes configuration)
  • Faulty AppController. I add loads of stuff into AppController, especially to beforeFilter() and beforeRender() so you might want to check those out also.

One more thing, are where are you setting the Questioneer.id in your Session? Perhaps that's the problem?

Salpa answered 3/6, 2009 at 13:9 Comment(0)
J
1

Yes, it occurs when there is a broken link in the web page. Each browser deals with it variously (Firefox calls it 2x). I tested it, there is no difference in CakePHP v1.3 and v2.2.1. To find out who the culprit is, add this line to the code, and then open the second generated file in you www folder:

file_put_contents("log-" . date("Hms") . ".txt", $this->params['pass'] ); // CakePHP v1.3 
file_put_contents("log-" . date("Hms") . ".txt", $this->request['pass'] ); //CakePHP v2.2.1

PS: First I blame jQuery for it. But in the end it was forgotten image for AJAX loading in 3rd part script.

Juxon answered 28/8, 2012 at 18:17 Comment(0)
P
0

I had the same problem in chrome, I disabled my 'HTML Validator' add on. Which was loading the page twice

Psychological answered 9/7, 2013 at 8:46 Comment(0)
S
0

I was having a similar issue, the problem seemed to be isolated to case-insensitivity on the endpoint.

ie:
http://server/Questionnaires/loadAvertisement -vs-
http://server/questionnaires/loadavertisement

When calling the proper-cased endpoint, the method ran once -whereas the lower-cased ran twice. The problem was occurring sporadically -happening on one controller, but not on another (essentially the same logic, no additional components etc.). I couldn't confirm, but believe the fault to be of the browser -not the CakePHP itself.

My workaround was assuring that every endpoint link was proper-cased. To go even further, I added common case-variants to the Route's configuration:

app/config/routes.php

<?php
// other routes..
$instructions = ['controller'=>'Questionnaires','action'=>'loadAvertisement'];
Router::connect('/questionnaires/loadavertisement', $instructions);
Router::connect('/QUESTIONNARIES/LOADADVERTISEMENT', $instructions);
// ..etc
Seymour answered 9/2, 2015 at 18:2 Comment(0)
N
0

If you miss <something>, for example a View, Cake will trigger a missing <something> error and it will try to render its Error View. Therefore, AppController will be called twice. If you resolve the missing issue, AppController is called once.

Narwhal answered 16/3, 2015 at 11:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.