2

我正在努力获取一个基本的 RESTful API 示例。目前我正在使用我在这里找到的示例,但是它有一些错误并且不完整。

如示例所述,我已经在我的 .htaccess 中添加了以下几行。

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

然而,我的问题只是让我的具体类打印“12”。我不知道要访问哪个 URL 才能在屏幕上显示消息“12”。

这是我的抽象类代码:

<?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: *"); //any origin can be processed by this page
        header("Access-Control-Allow-Methods: *"); //any HTTP method can be accepted
        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;
        }
    }

    /**
     * Determine if the concrete class implements a method for the endpoint that the client requested. If it does, then it calls that method, otherwise a 404 
     * response is returned
     */
    public function processAPI() {
        if ((int)method_exists($this->endpoint) > 0) {
            return $this->_response($this->{$this->endpoint}($this->args));
        }
        return $this->_response('', 400);
    }

    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(
            100 => 'Continue',
            101 => 'Switching Protocols',
            200 => 'OK',
            201 => 'Created',
            202 => 'Accepted',
            203 => 'Non-Authoritative Information',
            204 => 'No Content',
            205 => 'Reset Content',
            206 => 'Partial Content',
            300 => 'Multiple Choices',
            301 => 'Moved Permanently',
            302 => 'Found',
            303 => 'See Other',
            304 => 'Not Modified',
            305 => 'Use Proxy',
            306 => '(Unused)',
            307 => 'Temporary Redirect',
            400 => 'Bad Request',
            401 => 'Unauthorized',
            402 => 'Payment Required',
            403 => 'Forbidden',
            404 => 'Not Found',
            405 => 'Method Not Allowed',
            406 => 'Not Acceptable',
            407 => 'Proxy Authentication Required',
            408 => 'Request Timeout',
            409 => 'Conflict',
            410 => 'Gone',
            411 => 'Length Required',
            412 => 'Precondition Failed',
            413 => 'Request Entity Too Large',
            414 => 'Request-URI Too Long',
            415 => 'Unsupported Media Type',
            416 => 'Requested Range Not Satisfiable',
            417 => 'Expectation Failed',
            500 => 'Internal Server Error',
            501 => 'Not Implemented',
            502 => 'Bad Gateway',
            503 => 'Service Unavailable',
            504 => 'Gateway Timeout',
            505 => 'HTTP Version Not Supported');
        return ($status[$code])?$status[$code]:$status[500];
    }
}

这是我的具体类代码(第 8 行的问题):

<?php
require_once 'API.php';
class MyAPI extends API 
{
    protected $User;

    public function __construct($request, $origin)
    {
        echo "12";
        parent::__construct($request);

        // Abstracted out for example
        //$APIKey = new Models\APIKey();
        //$User = new Models\User();

        if (!array_key_exists('apiKey', $this->request)) {
            throw new Exception('No API Key provided');
        } else if (!$APIKey->verifyKey($this->request['apiKey'], $origin)) {
            throw new Exception('Invalid API Key');
        } else if (array_key_exists('token', $this->request) && !$User->get('token', $this->request['token'])){
            throw new Exception('Invalid User Token');
        }

        //$this->User = $User;
    }   

    /** 
     * Example of an Endpoint
     */
    protected function example()
    {
        if ($this->method == 'GET') {
            return "Your name is " . $this->User->name;
        } else {
            return "Only accepts GET requests";
        }
    }   
}

如您所见,具体类(在构造函数中)的第 8 行永远不会被打印出来。目前我正在尝试通过以下方式使我的示例工作:

www.mysite.com/api/myAPI.php?request=get
4

2 回答 2

3

不知道你是否还需要这个问题的答案,但我刚刚开始工作,做了一些调整。您的设置存在一些问题。首先是 .htaccess 文件。你让它指向 MyAPI.php,但如果你阅读教程,他实际上有第三个文件 api.php,它实例化了 MyAPI 类。该行:

RewriteRule api/v1/(.*)$ api/v1/MyAPI.php?request=$1 [QSA,NC,L]

应该:

RewriteRule api/v1/(.*)$ api/v1/api.php?request=$1 [QSA,NC,L]

您不应该尝试直接访问 MyAPI.php 文件。相反,apache 应该指向 api.php,传递请求的详细信息。api.php 文件的内容(每个 CM 的站点)是:

<?php
require_once 'MyAPI.php';
if (!array_key_exists('HTTP_ORIGIN', $_SERVER)) {
    $_SERVER['HTTP_ORIGIN'] = $_SERVER['SERVER_NAME'];
}

try {
    $API = new MyAPI($_REQUEST['request'], $_SERVER['HTTP_ORIGIN']);
    echo $API->processAPI();
} catch (Exception $e) {
    echo json_encode(Array('error' => $e->getMessage()));
}
?>

第二个问题是您的 URL - 您应该按照他的示例传递端点(在他/我的情况下,/api/v1/example)。这将在 MyAPI 构造函数中生成文本(如果您将其保留在您的构造函数中),以及来自示例端点函数的消息。为了它的价值,我去掉了所有的关键和用户的东西,这样我就可以让它运行了。所以我的 MyAPI.php 文件看起来像:

<?php
require_once 'AbstractAPI.php';
class MyAPI extends API 
{
    protected $testmessage;
    public function __construct($request, $origin) {
        parent::__construct($request);
        $this->testmessage = "Test String";
    }
    protected function example()
    {
        return $this->testmessage;  
    }
}
?>

我采取了“从简单开始,以后再打扮”的方法。祝你好运!

于 2014-11-24T05:01:05.320 回答
2

在我看来,这个 URL 违反了 REST 原则

www.mysite.com/api/myAPI.php?request=get

如果在 url 中提到,request=get那么使用 HTTP GET 的目的就消失了。
一个 RESTful url 应该是这样的

 www.mysite.com/api/myAPI.php

并且对这个 url 的 HTTP GET 请求应该可以完成工作。

于 2013-11-23T07:11:41.687 回答