Overwriting $_POST for PUT or DELETE requests

前端 未结 4 905
伪装坚强ぢ
伪装坚强ぢ 2020-12-15 23:11

In PHP I would like to be able to access PUT and DELETE vars globally similar to how GET and POST vars are accessed globa

相关标签:
4条回答
  • 2020-12-15 23:31

    You shouldn't modify $_POST directly as this represents values coming from the client. Consider it read-only, and do any modifications in user-defined variable.

    As a follow up regarding accessing PUT and DELETE data, currently there is no superglobal built in to PHP to access this data directly. As the data is file data, which can be rather large, the usefulness and efficiency of reading the entire file contents in a typical assignment statement $variable = $_PUT['file']; is questionable. Instead, it should be read in chunks. As such, the usage is consistent with reading from any other file input resource.

    More on PUT here:

    http://php.net/manual/en/features.file-upload.put-method.php

    0 讨论(0)
  • 2020-12-15 23:32

    Leave Post and Get as it is. it shouldn't be modified as it's for reading purposes only. Create $_PUT and $_DELETE globals:

    //  globals
    $_DELETE = array ();
    $_PUT = array ();
    
    switch ( $_SERVER['REQUEST_METHOD'] ) {
        case !strcasecmp($_SERVER['REQUEST_METHOD'],'DELETE'):
            parse_str( file_get_contents( 'php://input' ), $_DELETE );
            break;
    
        case !strcasecmp($_SERVER['REQUEST_METHOD'],'PUT'):
            parse_str( file_get_contents( 'php://input' ), $_PUT );
            break;
    }
    

    Not tested but you should get the idea. I was in the search for a rest framework myself some weeks ago and decided to go with python. Recess (http://www.recessframework.org/) sounds promising though

    0 讨论(0)
  • 2020-12-15 23:40

    If you create a "request" object, then regardless whether the request comes over HTTP, command line, or through an HTML5 web socket, you will have a uniform way to access request data. You can then make the request object accessible in the global scope, or pass it as an argument to the required functions or methods.

    Ideally you would store data that is independent of the request in static or global variables, e.g. settings that are "static" regardless of the request, and data specific to the request in a local variable or object, that could be used by your business logic. If you had a web socket server, for example, it would be easier to handle multiple request objects in a single PHP process. Here is an example that might help:

     $headers = getallheaders();
     $query = parse_str($_SERVER['QUERY_STRING']);
     $data = file_get_contents('php://input');
    
     if(strpos($headers['Content-Type'],'application/x-www-form-urlencoded') !== false)
     {
          $data = parse_str($data);
     }
     elseif(strpos($headers['Content-Type'],'application/json') !== false)
     {
          $data = json_decode($data);
     }
     elseif(strpos($headers['Content-Type'],'application/soap+xml') !== false)
     {
          $data = // parse soap
     }
     elseif(strpos($headers['Content-Type'],'application/xml') !== false)
     {
          $data = // parse xml
     }
     // else ...
    
    
     $request = new Request($_SERVER['REQUEST_METHOD'],$data,$query);
    
     // example business logic
    
        $method = $request->get_request_method();
    
        $obj = new BlogPost();
        if($method == 'GET')
        {
            $obj->id($request->get_query('id'));
            $obj->load();
        }
        elseif($method == 'PUT')
        {
            $obj->id($request->get_query('id'));
            $obj->title($request->get_data('title'));
            $obj->body($request->get_data('body'));
            $obj->save();
        }
        elseif($method == 'POST')
        {
            $obj->title($request->get_data('title'));
            $obj->body($request->get_data('body'));
            $obj->save();
        }
        elseif($method == 'DELETE')
        {
            $obj->id($request->get_query('id'));
            $obj->wipe();
        }
    

    Regardless of whether it is a PUT, POST, PATCH, or DELETE, there is only one body of data in the HTTP request, so your application does not need a complex $request object. The request object can make your controller (if you are using MVC) very simple.

    0 讨论(0)
  • 2020-12-15 23:47

    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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题