【问题标题】:How to build a RESTful API?如何构建 RESTful API?
【发布时间】:2011-06-08 17:13:10
【问题描述】:

问题是这样的: 我有一个在 PHP 服务器上运行的 Web 应用程序。我想为它构建一个 REST api。
我做了一些研究,我发现 REST api 使用 HTTP 方法(GET,POST ...)用于某些带有身份验证密钥(不一定)的 URI,并且信息以 HTTP 响应的形式返回,信息为 XML 或 JSON (我更喜欢 JSON)。

我的问题是:

  1. 作为应用程序的开发人员,我如何构建这些 URI?我需要在那个 URI 上编写 PHP 代码吗?
  2. 如何构建 JSON 对象以作为响应返回?

【问题讨论】:

标签: php authentication rest


【解决方案1】:

这是一个非常简单的简单 php 示例。

有 2 个文件 client.phpapi.php。我将这两个文件放在同一个 url 上:http://localhost:8888/,因此您必须将链接更改为您自己的 url。 (文件可以在两个不同的服务器上)。

这只是一个例子,它非常快速和肮脏,而且我已经很久没有做php了。但这是一个 api 的想法。

client.php

<?php

/*** this is the client ***/


if (isset($_GET["action"]) && isset($_GET["id"]) && $_GET["action"] == "get_user") // if the get parameter action is get_user and if the id is set, call the api to get the user information
{
  $user_info = file_get_contents('http://localhost:8888/api.php?action=get_user&id=' . $_GET["id"]);
  $user_info = json_decode($user_info, true);

  // THAT IS VERY QUICK AND DIRTY !!!!!
  ?>
    <table>
      <tr>
        <td>Name: </td><td> <?php echo $user_info["last_name"] ?></td>
      </tr>
      <tr>
        <td>First Name: </td><td> <?php echo $user_info["first_name"] ?></td>
      </tr>
      <tr>
        <td>Age: </td><td> <?php echo $user_info["age"] ?></td>
      </tr>
    </table>
    <a href="http://localhost:8888/client.php?action=get_userlist" alt="user list">Return to the user list</a>
  <?php
}
else // else take the user list
{
  $user_list = file_get_contents('http://localhost:8888/api.php?action=get_user_list');
  $user_list = json_decode($user_list, true);
  // THAT IS VERY QUICK AND DIRTY !!!!!
  ?>
    <ul>
    <?php foreach ($user_list as $user): ?>
      <li>
        <a href=<?php echo "http://localhost:8888/client.php?action=get_user&id=" . $user["id"]  ?> alt=<?php echo "user_" . $user_["id"] ?>><?php echo $user["name"] ?></a>
    </li>
    <?php endforeach; ?>
    </ul>
  <?php
}

?>

api.php

<?php

// This is the API to possibility show the user list, and show a specific user by action.

function get_user_by_id($id)
{
  $user_info = array();

  // make a call in db.
  switch ($id){
    case 1:
      $user_info = array("first_name" => "Marc", "last_name" => "Simon", "age" => 21); // let's say first_name, last_name, age
      break;
    case 2:
      $user_info = array("first_name" => "Frederic", "last_name" => "Zannetie", "age" => 24);
      break;
    case 3:
      $user_info = array("first_name" => "Laure", "last_name" => "Carbonnel", "age" => 45);
      break;
  }

  return $user_info;
}

function get_user_list()
{
  $user_list = array(array("id" => 1, "name" => "Simon"), array("id" => 2, "name" => "Zannetie"), array("id" => 3, "name" => "Carbonnel")); // call in db, here I make a list of 3 users.

  return $user_list;
}

$possible_url = array("get_user_list", "get_user");

$value = "An error has occurred";

if (isset($_GET["action"]) && in_array($_GET["action"], $possible_url))
{
  switch ($_GET["action"])
    {
      case "get_user_list":
        $value = get_user_list();
        break;
      case "get_user":
        if (isset($_GET["id"]))
          $value = get_user_by_id($_GET["id"]);
        else
          $value = "Missing argument";
        break;
    }
}

exit(json_encode($value));

?>

对于这个例子,我没有对数据库进行任何调用,但通常这是你应该做的。您还应该将“file_get_contents”函数替换为“curl”。

【讨论】:

  • 西蒙,非常感谢你的榜样。我只是想确定一下:假设我有一个名为 User 的资源,那么我需要将 API 文件放入:mydomain.com/api/user 正确吗?
  • 您可以随意命名文件。但是,是的,使用明确的名称调用文件会更好。查看我的 api 文件,我检查了 get 参数并调用了一个函数,这要归功于这个值。您可以包含 user.php 并调用此文件中的函数,或者您可以将文件放在 api/user 并从此处处理参数。
  • 所以基本上,我需要更新服务器路由表以将某些 URL 映射到服务器上的某些 PHP 文件。对吗?
  • 是的,但这与创建普通网站一样,只是您要发回的信息类型会改变。
  • 这里只使用“GET”,从不看请求方法,所以不是RESTful。参见stackoverflow.com/a/897311/1766230 示例,en.wikipedia.org/wiki/…
【解决方案2】:

在 2013 年,您应该使用 SilexSlim 之类的东西

Silex 示例:

require_once __DIR__.'/../vendor/autoload.php'; 

$app = new Silex\Application(); 

$app->get('/hello/{name}', function($name) use($app) { 
    return 'Hello '.$app->escape($name); 
}); 

$app->run(); 

苗条的例子:

$app = new \Slim\Slim();
$app->get('/hello/:name', function ($name) {
    echo "Hello, $name";
});
$app->run();

【讨论】:

  • 谢谢。我使用了 Slim,我在几分钟内就运行了一个裸 api。
  • 对于更复杂(详细)的 api,您会推荐什么?Slim 很方便,但所有功能都在一个文件中,因此可读性非常困难。
  • @IlkerBaltaci 使用 Silex,您可以将控制器提取到类中。这是一篇很好的文章,以及使用微框架与全栈框架igor.io/2012/11/09/scaling-silex.html 的一些优缺点。我个人更喜欢 Silex,因为它给了我最重要的东西,让我可以选择余下的东西。
【解决方案3】:

这与创建普通网站几乎相同。

php 网站的正常模式是:

  1. 用户输入网址
  2. 服务器获取url,解析并执行动作
  3. 在此操作中,您获取/生成页面所需的所有信息
  4. 您使用来自操作的信息创建 html/php 页面
  5. 服务器生成一个完整的 html 页面并发回给用户

使用 api,您只需在 3 和 4 之间添加一个新步骤。在 3 之后,创建一个包含您需要的所有信息的数组。将此数组编码为 json 并退出或返回此值。

$info = array("info_1" => 1; "info_2" => "info_2" ... "info_n" => array(1,2,3));
exit(json_encode($info));

这一切都是为了 api。 对于客户端,您可以通过 url 调用 api。如果 api 仅与 get 调用一起工作,我认为可以简单地做一个(检查,我通常使用 curl)。

$info = file_get_contents(url);
$info = json_decode($info);

但更常见的是使用 curl 库来执行 get 和 post 调用。 如果需要 curl 方面的帮助,可以问我。

从 api 获取信息后,您可以执行 4 和 5 步骤。

查看 json 函数和 file_get_contents 的 php 文档。

卷曲:http://fr.php.net/manual/fr/ref.curl.php


编辑

不,等等,我不明白。 “php API 页面”是什么意思?

api 只是您项目的创建/恢复。你永远不会直接发送 html 结果(如果你正在制作一个网站)抛出一个 api。您使用 url 调用 api,api 返回信息,您使用此信息创建最终结果。

ex:你想写一个 html 页面谁打招呼 xxx。但是要获取用户的名称,您必须从 api 获取信息。

假设您的 api 有一个函数,该函数以 user_id 作为参数并返回该用户的名称(例如 getUserNameById(user_id)),并且您仅在您的 /api/ulr/getUser/ 之类的 url 上调用此函数身份证。

Function getUserNameById(user_id)
{
  $userName = // call in db to get the user
  exit(json_encode($userName)); // maybe return work as well.
}

客户端你做的

    $username = file_get_contents(your/api/url/getUser/15); // You should normally use curl, but it simpler for the example
// So this function to this specifique url will call the api, and trigger the getUserNameById(user_id), whom give you the user name.
    <html>
    <body>
    <p>hello <?php echo $username ?> </p>
    </body>
    </html>

因此客户端永远不会直接访问数据库,即 api 的角色。

这样更清楚吗?

【讨论】:

  • +1。另请注意,API 应为响应设置正确的内容类型。 json 见stackoverflow.com/questions/477816/the-right-json-content-type
  • 所以我应该在服务器上拥有一个管理所有请求的 php API 页面?
  • 不,等等,我不明白。 “php API 页面”是什么意思?
  • 我的问题是API请求应该指向哪里?到服务器上的哪个文件?
  • 你想要哪些文件,和创建网站完全一样,只是你从客户端调用api,而不是从浏览器调用。但是对于 api 没有任何改变。当您在服务器上收到 url 时,您可以决定如何处理它,这要归功于 get 和 post 参数。你已经做网站了吗?你用过 cake、symfony 或 zend 之类的框架吗?
【解决方案4】:

(1) 我如何...构建这些 URI?我需要在那个 URI 上编写 PHP 代码吗?

对于如何设置 API URI 方案没有标准,但通常使用斜线分隔的值。为此,您可以使用...

$apiArgArray = explode("/", substr(@$_SERVER['PATH_INFO'], 1));

...在文件名之后获取URI中斜线分隔值的数组。

示例:假设您的应用程序中有一个 API 文件 api.php,并且您请求 api.php/members/3,那么 $apiArgArray 将是一个包含 ['members', '3'] 的数组。然后,您可以使用这些值来查询您的数据库或进行其他处理。

(2) 如何构建 JSON 对象以作为响应返回?

您可以使用json_encode 将任何 PHP 对象转换为 JSON。您还需要设置适当的标题。

header('Content-Type: application/json');
$myObject = (object) array( 'property' => 'value' ); // example
echo json_encode($myObject); // outputs JSON text

这对于返回 JSON 的 API 来说是件好事,但您应该问的下一个问题是:

(3) 如何使我的 API 成为 RESTful?

为此,我们将使用$_SERVER['REQUEST_METHOD'] 来获取正在使用的方法,然后在此基础上做不同的事情。所以最终的结果是......

header('Content-Type: application/json');
$apiArgArray = explode("/", substr(@$_SERVER['PATH_INFO'], 1));
$returnObject = (object) array();
/* Based on the method, use the arguments to figure out
   whether you're working with an individual or a collection, 
   then do your processing, and ultimately set $returnObject */
switch ($_SERVER['REQUEST_METHOD']) {
  case 'GET':
    // List entire collection or retrieve individual member
    break;
  case 'PUT':       
    // Replace entire collection or member
    break;  
  case 'POST':      
    // Create new member
    break;
  case 'DELETE':    
    // Delete collection or member
    break;
}
echo json_encode($returnObject);

来源:https://stackoverflow.com/a/897311/1766230http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services

【讨论】:

    【解决方案5】:

    到目前为止还没有提到的另一个框架是Laravel。一般而言,它非常适合构建 PHP 应用程序,但多亏了出色的路由器,构建丰富的 API 非常舒适和简单。它可能不像 Slim 或 Sliex 那样纤薄,但它为您提供了坚实的结构。

    在 YouTube 上查看 Aaron Kuzemchak - Simple API Development With Laravel

    Laravel 4: A Start at a RESTful API 在 NetTuts+ 上

    【讨论】:

      【解决方案6】:

      我知道这个问题已被接受并且有点老,但这可能对一些仍然认为它相关的人有所帮助。虽然结果不是完整的 RESTful API,但 PHP 的 API Builder mini lib 允许您轻松地将 MySQL 数据库转换为 Web 可访问的 JSON API。

      【讨论】:

        【解决方案7】:

        正如 simon marc 所说,该过程与您或我浏览网站的过程大致相同。如果您对使用 Zend 框架感到满意,那么有一些易于遵循的教程可以让您轻松设置。构建一个 restful api 最困难的部分是它的设计,并使其真正成为 restful,想想数据库术语中的 CRUD。

        这可能是你真的想要一个 xmlrpc 接口或其他类似的东西。你希望这个界面允许你做什么?

        --编辑

        这里是我开始使用 restful api 和 Zend 框架的地方。 Zend Framework Example

        简而言之,不要使用 Zend REST 服务器,它已经过时了。

        【讨论】:

        • 如果您有兴趣,我将在我的博客上发布一些关于开始使用 ZF 和 RESTful Web 服务的内容以及一个完整的工作示例。
        猜你喜欢
        • 1970-01-01
        • 2014-09-13
        • 2018-11-18
        • 2017-11-15
        • 1970-01-01
        • 2015-12-19
        • 1970-01-01
        相关资源
        最近更新 更多