Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwriting $_POST for PUT or DELETE requests

Tags:

rest

php

In PHP I would like to be able to access PUT and DELETE vars globally similar to how GET and POST vars are accessed globally. I originally considered adding the data to $_PUT and $_DELETE respectively in the global namespace, but then I realized that the data for each request is stored in the message body so there's no way for there to be more than one dataset from a POST, PUT, or DELETE request.

Are there any side-effects of overwriting the $_POST variable?

i.e. str_parse( file_get_contents( 'php://input' ), $_POST );

Am I being silly, or is there a better way to access PUT and DELETE data?


Edit to clarify my thinking:

I am very well aware of the source of the data in $_POST, in fact i mentioned it earlier in my question. If a HTTP POST request is sent to the server the data is stored in php://input. If a HTTP PUT or DELETE request is sent to the server, the data is stored in the exact same place, meaning that $_POST will be empty (as no data was POSTed despite data being available.

A GET request, on the other hand, is passed via the query string. This allows simultaneous passing of $_POST and $_GET variables. It is not possible to simultaneously pass POST and PUT or DELETE variables.

If I overwrite $_POST from php://input on PUT and or DELETE requests, there is no data loss.

The alternative of adding:

global $_PUT;
global $_DELETE;

to the beginning of functions seems silly, as I'll only be able to use one at a time anyway.

My first question, which is the one I really want answered, is about what side-effects or issues exist in overwriting $_POST. I can't possibly be the first person to try something as silly as:

$_POST['foo'] = 'bar';

I'm just concerned that if I do anything similar that it might not be preserved across scopes.

like image 470
zzzzBov Avatar asked Jun 07 '11 18:06

zzzzBov


1 Answers

You'll see this called "bad practice" all over the internet, but if you really get in to why it is "bad practice", well, the answers get fuzzy. The most concrete reason is the "hit by a bus" scenario so often bandied about - what if the project gets handed off to a new developer?

Hand wringing aside (you can leave comments, after all), there really isn't a compelling reason not to do it like this, but again, there isn't a compelling reason to do it, either. Why not put the values in a $_SESSION key if you want them global? Or make a global variable? Or make a static class to access the PUT/DELETE values through? With all the other optional approaches, I think that overwriting $_POST, while it won't make your server explode, is the most likely to cause you a headache down the road.

I threw this little static class together, you'll want to test this out before relying on it. Use:

//To check if this is a rest request:
Rest::isRest();

//To get a parameter from PUT
$put_var = Rest::put('keyname', false);

//To get a parameter from DELETE
$dele_var = Rest::delete('keyname', false);

 class Rest {
    static private $put = false;
    static private $delete = false;
    static private $is_rest = false;
    function __construct() {
        self::$is_rest = true;
        switch ($_SERVER['REQUEST_METHOD']) {
            case 'PUT':
                parse_str(self::getVars(), self::$put);
                break;
            case 'DELETE':
                parse_str(self::getVars(), self::$delete);
                break;
            default:
                self::$is_rest = false;
        }
    }
    private static function getVars() {
        if (strlen(trim($vars = file_get_contents('php://input'))) === 0)
            $vars = false;
        return $vars;
    }
    public static function delete($key=false, $default=false) {
        if (self::$is_rest !== true)
            return $default;
        if (is_array(self::$delete) && array_key_exists($key, self::$delete))
            return self::$delete[$key];
        return $default;
    }
    public static function put($key=false, $default=false) {
        if (self::$is_rest !== true)
            return $default;
        if (is_array(self::$put) && array_key_exists($key, self::$put))
            return self::$put[$key];
        return $default;
    }
    public static function isRest() {
        return self::$is_rest;
    }
}
like image 142
Chris Baker Avatar answered Oct 20 '22 04:10

Chris Baker