SitePoint Sponsor

User Tag List

Results 1 to 5 of 5

Hybrid View

  1. #1
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,026
    Mentioned
    64 Post(s)
    Tagged
    0 Thread(s)

    Of $_POST, $_GET and $_REQUEST

    Some time ago someone here advised me to move my script's action parsing away from using $_REQUEST for security reasons. I initially chaffed at the idea. I did however study the reasoning and came across reasons to make the switch. Along the way I picked up an interesting trick.

    My controllers are now structured such that post actions are implicitly write oriented actions, and get actions are reads. I'm trying to avoid having an exception. This sorting does however help with form organization. Take a basic login form. Now that I've separated POST and GET out I use the source array as part of the actions name. For example

    $_GET['action'] = 'login' sets the system to fetch the login form while
    $_POST['action'] = 'login' actually executes the login.

    These pairs come up quite a bit and there is an elegance to this that having an actions named 'login' and 'doLogin' respectively lack.

    Here's the code block for the curious.

    PHP Code:
        /**
         * Search the $_POST array, then the $_GET array for an action to take.
         * If neither is set fall to the default (which must be a $_GET action).
         * $_POST actions require a table to be specified, $_GET actions can
         * set a table if desired, else the system will default to the first table
         * listed for the controller.
         * 
         * @throws RequestException
         */
        
    protected function parseAction() {

            
    /**
             * $_POST actions. These actions write to the database.
             */
            
    if (isset($_POST['action'])) {
                if ( 
    array_key_exists($_POST['action'], $this->postActions) && 
                    
    $this->parseTable($_POST$this->postActions[$_POST['action']]) &&
                    
    $this->table // POST actions require a table.
                
    ) {
                    
    $this->actionType 'post';
                    
    $this->action $this->postActions[$_POST['action']]['method'];
                } else {
                    throw new 
    PAMWF_RequestException();
                }
            }
            
    /**
             * $_GET actions. These actions read from the database.
             */
            
    else if (isset($_GET['action'])) {
                if ( 
    array_key_exists($_GET['action'], $this->getActions) && 
                    
    $this->parseTable($_GET$this->postActions[$_GET['action']])
                ) {
                    
    $this->actionType 'get';
                    
    $this->action $this->getActions[$_GET['action']]['method'];    
                } else {
                    throw new 
    PAMWF_RequestException();
                }
            } 
            
    /**
             * The default action - which MUST be one of the $_GET actions.
             */
            
    else {
                
    $this->action $this->getActions[$this->defaultAction]['method'];
            }
        }
        
        
    /**
         * Parse the table for the action. Return true on success or false on fail.
         *
         * @param array $input Get or Post (process same for both)
         * @param array $action The action we are checking for.
         * 
         * @return boolean
         */
        
    protected function parseTable$request$action ) {
            
            
    /**
             * If neither the action nor the request specifies a table
             * return true but don't set a table. This is the reason
             * the $_POST actions check for a table after calling this
             * function in the code below.
             */
            
    if ((!isset($action['tables']) || empty($action['tables'])) && !isset($request['table'])) {
                return 
    true;
            } else if (isset(
    $action['tables'])) {
                
    $actionTables explode(','$action['tables']);            
            } else {
                
    $actionTables = array();
            }
        
            
    /**
             * If no table was specified but the action only has one table
             * we set that table.
             */
            
    if (!isset($request['table']) && count($actionTables) == ) {
                
    $this->table array_pop($actionTables);    
            } 
            
    /**
             * If a table was specified and is allowed for the action set
             * that table.
             */
            
    else if (isset($request['table']) && in_array($request['table'], $actionTables)) {
                
    $this->table $request['table'];
            }
            
    /**
             * All other situations are invalid.
             */
            
    else {
                return 
    false;
            }
            
            
    /**
             * Now a sanity check to make sure the action is valid for the controller.
             * This error should only happen during coding so we'll use assert.
             */
            
    assert(isset($this->tables[$this->table]));
                
            return 
    true;
        } 

  2. #2
    Follow Me On Twitter: @djg gold trophysilver trophybronze trophy Dan Grossman's Avatar
    Join Date
    Aug 2000
    Location
    Philadephia, PA
    Posts
    20,580
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    This is called being RESTful. This is what the HTTP verbs (GET/POST/PUT/DELETE) were meant to mean.

  3. #3
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's a bit of a simplification to equal this to REST. REST is much more than just using http methods as intended.

  4. #4
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    i tend to have a router object, which when passed a request object, returns a route. This route contains the controller and method to be called for this route, I found it really quite flexible.

    For instance, a RESTful route, would return the Controller but the action would be determined by the HTTP method.

    PHP Code:
    <?php
    $router
    ->getRouteFor($request)->getController();
    $router->getRouteFor($request)->getMethod();
    $router->getRouteFor($request)->getParameters();
    ?>
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  5. #5
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Michael Morris View Post
    Now that I've separated POST and GET out I use the source array as part of the actions name. For example

    $_GET['action'] = 'login' sets the system to fetch the login form while
    $_POST['action'] = 'login' actually executes the login.

    These pairs come up quite a bit and there is an elegance to this that having an actions named 'login' and 'doLogin' respectively lack.
    I do something similar, but the text I use for a submit button isn't always the best candidate for a method name. I've been doing this for a while though:

    HTML Code:
    <input type="submit" name="action[login]" value="Log In" />
    Which returns:
    PHP Code:
    $_POST['action'] = array('login' => 'Log In'); 
    Which it's easy enough to grab the method name from.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •