使用PHP的基本RESTful API示例 [英] Basic RESTful API example using PHP

查看:162
本文介绍了使用PHP的基本RESTful API示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working on getting a basic RESTful API example. Currently I'm using the example I found here however it has some bugs and is incomplete.

作为示例,我已经在.htaccess中添加了以下几行.

I've already added the following lines to my .htaccess as the example stated.

<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".

My problem however is simply getting the concrete class of mine to print "12". I don't know which URL to visit to get the message "12" to be shown on the screen.

这是我的抽象类代码:

<?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行出现问题):

And here is my concrete class code (trouble on line 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行永远不会被打印.目前,我正在尝试通过以下方法使示例工作正常:

As you can see line 8 on the concrete class (in the constructor) never gets printed. Currently I'm trying to make my example work by going to:

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

推荐答案

不确定您是否仍然需要这个答案,但是我只是做了一些调整,使我的工作得以完成.您的设置存在一些问题.首先是.htaccess文件.您可以将其指向MyAPI.php,但是如果您阅读了本教程,他实际上有第三个文件api.php,该文件实例化了MyAPI类.该行:

Not sure if you still need an answer on this, but I just got mine working, with a few tweaks. There are a few problems with your setup. First is the .htaccess file. You have it pointing to MyAPI.php, but if you read the tutorial, he actually has a third file, api.php, that instantiates the MyAPI class. The line:

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的站点)为:

You shouldn't be trying to access the MyAPI.php file directly. Rather, apache should point to api.php, passing the request details along. The contents of the api.php file (per CM's site) are:

<?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文件看起来像:

The second problem is with your URL - you should follow his example of passing an endpoint (in his/my case, /api/v1/example). This will produce both the text inside the MyAPI constructor (if you leave that in yours), and the message from the example endpoint function. For what it's worth, I stripped out all of the key and user stuff just so I could get it running. So my MyAPI.php file looks like:

<?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;  
    }
}
?>

我采用了从简单开始,以后再打扮"的方法.祝你好运!

I took the "start simple, dress it up later" approach. Good luck!

这篇关于使用PHP的基本RESTful API示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆