Question

UPDATE: Solved Checking to see if the current request was a post wasn't enough. The forms were still passed to the helper in order of creation. If the first form passed to the helper wasn't the posted form, there wasn't enough validation to prevent its details from being used instead of the expected posted form.

Added if additional clause in helper...

if ($postId)

should have been

if ($postId === $formId)

Pretty straight forward really... only took me 2 days to find the answer.

--- Original Post Below ---

I have tried to implement my own PRG (Post/Redirect/Get) pattern in ZF1.

I use a custom form class that extends Zend_Form to add a setUniqueFormId method which is basically a hidden element with the form name. The forms are passed to the action helper along with 2 variables ($persistData and $redirectUrl). The problem is that the when I have multiple forms, the first $persistData and $redirectUrl values are always used for any subsequent forms even though these have been changed. the values passed from the last call to the helper are used.

Any thoughts on why this would be the case? Any help much appreciated.

Update: I think this is an issue with using an action helper. Each time it is called and new values are passed, all previous values are changed. I'm not that familiar with the internals of the action helper broker. Can anyone shed any light or make a suggestion?

--- Controller Action ---

// Create 2 new forms 
$testForm1 = new Application_Form_Test;
$testForm2 = new Application_Form_Test;

// Call a custom function on each form tp create a hidden field called 
// "unique_form_id" to help identify the form that has posted the data
$testForm1->setUniqueFormId('test_form_1');
$testForm2->setUniqueFormId('test_form_2');

// Call "Post Redirect Get" Helper and pass a boolean variable for $persistData
$formData1 = $this->_helper->postRedirectGet($testForm1, true);
$formData2 = $this->_helper->postRedirectGet($testForm2, false);

--- Controller Action Helper ---

public function direct($form, $persistData = false, $redirectUrl = null)
    {
    $formId = $form->getElement('unique_form_id')->getValue();

    $currentUrl = implode   (
                            '/',
                            array   (
                                    $this->getRequest()->getModuleName(),
                                    $this->getRequest()->getControllerName(),
                                    $this->getRequest()->getActionName()
                                    )
                            );

    $session = new Zend_Session_Namespace('prg');

    $redirectUrl = $redirectUrl ? $redirectUrl : $currentUrl;

    if ($this->getRequest()->isPost())
        {
        $postId = $this->getRequest()->getPost('unique_form_id');

        if ($postId)
            {
            $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');

            $postUrl = $currentUrl;

            $session->$postUrl->$postId = array (
                                                'url'       => (string) $redirectUrl,
                                                'id'        => (string) $postId,
                                                'post'      => (array) $this->getRequest()->getPost(),
                                                'persist'   => (bool) $persistData
                                                );

            Zend_Session::writeClose(true);

            $response = $redirector ->setCode(303)
                                    ->setExit(true)
                                    ->gotoUrl($redirectUrl);

            return  $response;
            }
            else    {
                    return false;
                    }
        }
        else    {
                $urlSessionData = $session->$currentUrl;

                // Results shown below
                Zend_Debug::dump($urlSessionData);

                if ($urlSessionData->$formId != null)
                    {
                    $formSessionData = $urlSessionData->$formId;
                    $formPersist = $formSessionData['persist'];
                    $formPostData = $formSessionData['post'];

                    if (!$formPersist)
                        {
                        unset($urlSessionData->$formId);
                        }

                    if(!empty($formPostData))
                        {
                        $form->isValid($formPostData);
                        }

                    return $formPostData;
                    }
                    else    {
                            return false;
                            }
                }
    }

--- Front Controller Plugin ---

function preDispatch()
    {
    $session = new Zend_Session_Namespace('prg');

    $currentUrl = implode   (
                            '/',
                            array   (
                                    $this->getRequest()->getModuleName(),
                                    $this->getRequest()->getControllerName(),
                                    $this->getRequest()->getActionName()
                                    )
                            );

    // Check if current url is in prg sesison
    // If not, we have moved to another URL or its our first visit to the $currentUrl
    if ($session->$currentUrl === null)
        {
        // Remove all prg sessions
        Zend_Session::namespaceUnset('prg');
        }           

    return;
    }

--- Dump Result ---

object(stdClass)#54 (2) 
    {
    ["test_form_1"] => array(4)
        {
        ["url"] => string(21) "admin/timeclock/index"
        ["id"] => string(11) "test_form_1"
        ["post"] => array(4)
            {
            ["test_element"] => string(0) ""
            ["submit"] => string(5) "Submit"
            ["unique_form_id"] => string(11) "test_form_1"
            }
        ["persist"] => bool(false) <-- Expected to be 'true'
        }

    ["test_form_2"] => array(4)
        {
        ["url"] => string(21) "admin/timeclock/index"
        ["id"] => string(11) "test_form_2"
        ["post"] => array(4)
            {
            ["test_element"] => string(0) ""
            ["submit"] => string(5) "Submit"
            ["unique_form_id"] => string(11) "test_form_2"
            }
        ["persist"] => bool(false) <-- Expected to be 'false'
        }
    }
Was it helpful?

Solution

I (stupidly) didn't check if the form passed to the helper after a form submit was the form that was posted. This meant that if the posted form wasn't the first form that was posted, the values passed along with the first form were the values stored in the session.

if ($postId) should have been if ($postId === $formId)

public function direct($form, $persistData = false, $redirectUrl = null)
    {
    $formId = $form->getElement('unique_form_id')->getValue();

    $currentUrl = implode   (
                            '/',
                             array   (
                                     $this->getRequest()->getModuleName(),
                                     $this->getRequest()->getControllerName(),
                                     $this->getRequest()->getActionName()
                                     )
                            );

$session = new Zend_Session_Namespace('prg');

$redirectUrl = $redirectUrl ? $redirectUrl : $currentUrl;

if ($this->getRequest()->isPost())
    {
    $postId = $this->getRequest()->getPost('unique_form_id');

    if ($postId === $formId)
        {
        $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');

        $postUrl = $currentUrl;

        $session->$postUrl->$postId = array (
                                            'url'       => (string) $redirectUrl,
                                            'id'        => (string) $postId,
                                            'post'      => (array) $this->getRequest()->getPost(),
                                            'persist'   => (bool) $persistData
                                            );

        Zend_Session::writeClose(true);

        $response = $redirector ->setCode(303)
                                ->setExit(true)
                                ->gotoUrl($redirectUrl);

        return  $response;
        }
        else    {
                return false;
                }
    }
    else    {
            $urlSessionData = $session->$currentUrl;

            // Results shown below
            Zend_Debug::dump($urlSessionData);

            if ($urlSessionData->$formId != null)
                {
                $formSessionData = $urlSessionData->$formId;
                $formPersist = $formSessionData['persist'];
                $formPostData = $formSessionData['post'];

                if (!$formPersist)
                    {
                    unset($urlSessionData->$formId);
                    }

                if(!empty($formPostData))
                    {
                    $form->isValid($formPostData);
                    }

                return $formPostData;
                }
                else    {
                        return false;
                        }
            }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top