为什么我的$ _REQUEST ['请求']变量未定义(访问API的端点时)

时间:2017-09-26 11:34:16

标签: php .htaccess rest

我按照教程here使用PHP创建RESTful API。

我在localhost上运行项目但是在尝试查看教程中建议的端点时我遇到以下错误(api / v1 / example):

Notice: Undefined index: request in C:\wamp64\www\API\api.php on line 8

(注意:请参阅下面的api.php文件。)

这个请求索引应该在htaccess文件中设置,所以我认为这就是问题所在。 (我很抱歉,如果这很简单,但我试图找到自己没有运气。)你能帮忙吗?

在教程中我们创建:

  1. 一个htaccess文件,用于配置Web服务器应如何处理项目目录中文件的请求。
  2. 一个Abstract类,用于处理URI的解析并返回     响应。
  3. 一个由类的端点组成的具体类 API。
  4. htaccess文件

    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule api/v1/(.*)$ api/v1/api.php?request=$1 [QSA,NC,L]
    </IfModule>
    

    抽象类

    <?php
        abstract class API
        {
            /**
             * Property: method
             * The HTTP method this request was made in, either GET, POST, PUT or DELETE
             */
            protected $method = '';
            /**
             * Property: endpoint
             * The Model requested in the URI. eg: /files
             */
            protected $endpoint = '';
            /**
             * Property: verb
             * An optional additional descriptor about the endpoint, used for things that can
             * not be handled by the basic methods. eg: /files/process
             */
            protected $verb = '';
            /**
             * Property: args
             * Any additional URI components after the endpoint and verb have been removed, in our
             * case, an integer ID for the resource. eg: /<endpoint>/<verb>/<arg0>/<arg1>
             * or /<endpoint>/<arg0>
             */
            protected $args = Array();
            /**
             * Property: file
             * Stores the input of the PUT request
             */
             protected $file = Null;
    
            /**
             * Constructor: __construct
             * Allow for CORS, assemble and pre-process the data
             */
            public function __construct($request) {
                header("Access-Control-Allow-Orgin: *");
                header("Access-Control-Allow-Methods: *");
                header("Content-Type: application/json");
    
                $this->args = explode('/', rtrim($request, '/'));
                $this->endpoint = array_shift($this->args);
                if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                    $this->verb = array_shift($this->args);
                }
    
                $this->method = $_SERVER['REQUEST_METHOD'];
                if ($this->method == 'POST' && array_key_exists('HTTP_X_HTTP_METHOD', $_SERVER)) {
                    if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'DELETE') {
                        $this->method = 'DELETE';
                    } else if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'PUT') {
                        $this->method = 'PUT';
                    } else {
                        throw new Exception("Unexpected Header");
                    }
                }
    
                switch($this->method) {
                case 'DELETE':
                case 'POST':
                    $this->request = $this->_cleanInputs($_POST);
                    break;
                case 'GET':
                    $this->request = $this->_cleanInputs($_GET);
                    break;
                case 'PUT':
                    $this->request = $this->_cleanInputs($_GET);
                    $this->file = file_get_contents("php://input");
                    break;
                default:
                    $this->_response('Invalid Method', 405);
                    break;
                }
            }
            public function processAPI() {
                if (method_exists($this, $this->endpoint)) {
                    return $this->_response($this->{$this->endpoint}($this->args));
                }
                return $this->_response("No Endpoint: $this->endpoint", 404);
            }
    
            private function _response($data, $status = 200) {
                header("HTTP/1.1 " . $status . " " . $this->_requestStatus($status));
                return json_encode($data);
            }
    
            private function _cleanInputs($data) {
                $clean_input = Array();
                if (is_array($data)) {
                    foreach ($data as $k => $v) {
                        $clean_input[$k] = $this->_cleanInputs($v);
                    }
                } else {
                    $clean_input = trim(strip_tags($data));
                }
                return $clean_input;
            }
    
            private function _requestStatus($code) {
                $status = array(  
                    200 => 'OK',
                    404 => 'Not Found',   
                    405 => 'Method Not Allowed',
                    500 => 'Internal Server Error',
                ); 
                return ($status[$code])?$status[$code]:$status[500]; 
            }
    
    
    
        }
        ?>
    

    具体类

    <?php
    require_once 'API.class.php';
    
    class MyAPI extends API
    {
        protected $FacebookUser;
    
        public function __construct($request, $origin) {
            parent::__construct($request);
            //I removed the User and API key code here until they are set up properly
        }
    
        /**
         * Example of an Endpoint
         */
         protected function example() {
            if ($this->method == 'GET') {
               return "Endpoint is working"; 
            } else {
                return "Only accepts GET requests";
            }
         }
     }
    ?>
    

    api.php

    <?php
    require_once 'MyAPI.class.php';
    // Requests from the same server don't have a HTTP_ORIGIN header
    if (!array_key_exists('HTTP_ORIGIN', $_SERVER)) {
        $_SERVER['HTTP_ORIGIN'] = $_SERVER['SERVER_NAME'];
    }
    try {
        //the following $_REQUEST['request'] variable is not set.
        $API = new MyAPI($_REQUEST['request'], $_SERVER['HTTP_ORIGIN']);
        echo $API->processAPI();
    } catch (Exception $e) {
        echo json_encode(Array('error' => $e->getMessage()));
    }
    ?>
    

2 个答案:

答案 0 :(得分:1)

$_REQUEST是客户端发送的请求变量数组。密钥request不保证存在于此数组中。尝试使用调试器或var_dump来显示数组的内容。

也许如果您根据发送请求更新您的问题,有人可以为您提供更多指导。

答案 1 :(得分:1)

读取你的.htaccess文件,你需要一个更像这样的层次结构:

API
├── api
│   └── v1
│       └── api.php
└── .htaccess

API当前是文档根目录的子文件夹(将来您可能会将API作为文档根目录或相应地移动文件)。

API/.htaccess的内容:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule api/v1/(.*)$ api/v1/api.php?request=$1 [QSA,NC,L]

API/api/v1/api.php的内容(检查重写是否有效):

<?php
var_dump($_REQUEST);

然后请求:

example.com/API/api/v1/foo

应该重写到你的api.php文件(通过重写规则),api.php应该输出:

array(1) { ["request"]=> string(3) "foo" }