2017-09-26 47 views
0

我按照教程here創建了一個使用PHP的RESTful API。

我運行在本地主機上的項目但是我越來越想查看端點時出現以下錯誤提示在本教程(API/V1 /例):

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

(注:見下面的api.php文件。)

這個請求索引應該在htaccess文件中設置,所以我認爲這就是問題所在。 (我很抱歉,如果這是簡單的,但我試圖找到自己沒有運氣。)你能幫忙嗎?

在本教程中,我們創建:

  1. 一個htaccess文件如何配置Web服務器應在項目的目錄內處理請求的文件。
  2. 一個抽象類,用於處理URI的解析並返回 響應。
  3. 一個由 API的端點組成的具體類。

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())); 
} 
?> 
+0

你發送請求變量發送請求? –

+0

如果您訪問'api/v1/foo',它是否有效? – Progrock

+0

@Progrock我只是試過。它給出了同樣的錯誤。 – Sarah

回答

1

讀你的.htaccess文件,你需要一個層次更多這樣的:

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

其中API是目前你的文檔根目錄的子文件夾(在未來,你將可能使API文檔根目錄或移動文件相應)。

內容的API/.htaccessAPI/api/v1/api.php(查詢重寫工作)的

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

內容:

<?php 
var_dump($_REQUEST); 

然後請求爲:

example.com/API/api/v1/foo 

應該重寫你的API 。php文件(通過重寫規則)和api.php應該輸出:

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

謝謝。從你的答案中得到靈感,我沒有改變文件結構。我只是改變了.htaccess文件如下: RewriteEngine敘述在 重寫規則(。*)$ api.php請求= $ 1 [QSA,NC,L] 並且這被現在的工作(該當訪問http:// localhost/API/example或http:// localhost/API/api/v1/example時,正在設置request變量。正如你所看到的,我也拿出了兩個RewriteCond行,因爲這些行不允許RewriteRule繼續。感謝你的幫助。 – Sarah

+1

是的,你可以這樣做。我會保留其他兩行,對我來說工作正常。 – Progrock

+0

好的非常感謝:) – Sarah

1

$_REQUEST是客戶端發送的請求變量數組。不保證該數組內部存在密鑰request。嘗試使用調試器或var_dump來顯示數組的內容。

也許如果你更新你的問題與你發送的請求有人可以引導你進一步。

+0

謝謝。我對這個過程的理解是請求變量在這裏設置在htaccess文件中:(RewriteRule api/v1 /(.*)$ api/v1/api.php?request = $ 1 [QSA,NC,L])並且應該包含完整的URL,然後將在Abstract API.class的構造函數中解析,如您在構造函數中的這一行中所看到的:$ this-> args = explode('/',rtrim($ request,'/') ); ...這個想法是從那裏的URI字符串中檢索端點。我輸出$ _REQUEST變量,它是空的...你認爲這是我的htaccess沒有正確執行重寫? – Sarah