1

This is my first PhP-MySQL project and my first (ever) question. Am trying to make a small portal and in order to learn the basics I am trying to use the front controller pattern as I am not confident using the Observer pattern at present.

The front controller basically looks something like below and calls the appropriate method of the correct class:

$controller =''; $action =''; $queryString ='';
parseURL($controller, $action, $queryString);
$objView = new View;
if ($controller == 'adminlogin' && $action == 'authenticate') {
    AdminLogin::getInstance()->authenticate();
} else if ($controller && $action) {
    SessionFactory::getSession();
    if (isset($_SESSION['userName'])) { // and some more validations
        callHook($controller, $action, $queryString);
    } else {
        $objView->assign('message', SESSION_INVALID);
        $objView->display('index');
    } 
} else {
    $objView->display('index');
}

The view is also simple:

public function assign ($variable, $value)
{
    $this->passArray[$variable] = $value;
}

public function display ($view)
{
    $mapper = ViewmapSingleton::getinstance();
    if (1 == preg_match("/\/|\.|\\\\/", $view)) {
        echo 'View name should not contain . / or \ ';
    }
    $template = $mapper->getViewPath($view);
    if (!$template || is_dir($template)) {
        echo 'The requested view file does not exist';
    } else {
        extract ($this->passArray);
        include_once($template);
    }
}

My Problem is the Browser's BACK button when submitting $_POST forms. I am trying to make an Admin page that shows article listings and allows pagination, bulk actions, and 'search articles by title / category' etc.

From what I have read on this (most useful) website, there exist two solutions to prevent the Browser's back button from re-submitting a form:

Solution 1. Pass the search parameters to the action (method) by appending them to the URL using Javascript on the Search button.

<input id="btn1" type="submit" onclick="SubmitForm('index.php?   controller=articles&action=showList&articleTitle='+document.getElementById('articleTitle').value)" value="Search" name="btn1"></input>

=> Not the best way because there could be many many parameters like article-category etc.

Solution 2. Do not pass the parameters and instead use $_POST data in the called method. Save everything in $_SESSION and then redirect using header() to a separate display method in the same class. Extract everything from $_SESSION in the display function and generate the view.

=>Not the best way because there can be many many parameters that will have to be stored in the Session and then extracted.

Is there a more elegant way to prevent the browser's back button re-submitting a form when using a front controller? I ask because when using the front controller pattern, $_GET may not be of much use especially where some bulk actions require DB changes and are of the type "Unpublish".

Please ignore my ignorance and help!

Thanks

aarkay777
  • 11
  • 2

2 Answers2

0

Other way you could do this is by using redirection.

Updated: refer this solution. Back button re-submit form data ($_POST)

Community
  • 1
  • 1
Mike Ed
  • 1
  • 1
  • The reference discussion would not help much when all requests are directed to one single file (like in the front controller pattern) – aarkay777 Oct 19 '13 at 13:33
0

Welcome to SO!

First, unless GET is absolutely necessary always use POST for form submission. (see details below)

Your PHP code should the exclusively rely on $_POST to retrieve submitted data ($_GET would be probably empty, and $_REQUEST combines both $_GET and $_POST).

After your application receives the form data, and probably processed it, redirect the browser. Do not send an HTML response, but rather a 302 Moved directing the browser to the next page:

A really very basic example:

session_start();                                       // make sure a session is available
if (is_array($_POST) && array_key_exists('submitbutton_name', $_POST)) {
    // user has submitted the form
    $inputdata = $_POST;                               // retrieve input data
    $next_page_html = determine_next_page($inputdata); // process and construct next page
    $_SESSION['page_to_show'] = $next_page_html;       // keep the HTML response

    // redirect the browser to the very same location, but using GET
    header('Location: ' + $_SERVER['REQUEST_URI']);
    exit;
}

// the redirect will end up here
if (array_key_exists('page_to_show', $_SESSION)) {
    // we have a next page to show
    echo $_SESSION['next_page_to_show'];
    // don't forget to remove the session entry
    unset($_SESSION['next_page_to_show']);
}
else {
    // output the starting page, probably the form that the user should submit
}

HTH

ErnestV
  • 117
  • 1
  • 6
  • Excellent! I am not fond of $_GET either and your solution works like a charm. Just one small thing: header('Location: ' + $_SERVER['REQUEST_URI']);exit; was showing a blank page for some reason, however, it worked with a minor change =>$uri = $_SERVER['REQUEST_URI']; header("Location: $uri");exit; – aarkay777 Oct 19 '13 at 13:26
  • Since this is my first post, I am not sure if I should write this as an independent response or as a comment. Ernest, with less parameters in Admin, above will work OK. However, the front-end too uses a front controller pattern too and directs all requests to index.php which calls an appropriate method in an appropriate class. Two minor queries: (1) If I use the above method on the front-end as well, should I start the Session right at the start even if its is not necessary? – aarkay777 Oct 19 '13 at 13:38
  • (2) When building a shopping cart type site the front-end could have huge number of parameters. Should $_GET be used in such cases or can $_POST handle that too? (3) $_GET does not put $controller='something'&$action='something' in the URL so can it even be used in a Front Controller that requires a controller and action name? – aarkay777 Oct 19 '13 at 13:43
  • Generally, use POST when you're changing/uploading data, and GET when retrieving data. POST does not have limits as GET doeas which is limited in length (check RFC for that). – ErnestV Oct 19 '13 at 15:23
  • As your shopping cart requires a session anyway you can just go ahead and start it upfront, and use it to store the current redirection state. OTOH, you could redirect to something like a SmartURL which would actually be handled by your index.php. The SmartURL will be available in $_SERVER['PATH_INFO']. – ErnestV Oct 19 '13 at 15:25