PHP 实现 RESTful 风格的 API

PHP实现 RESTful 风格的 API

目录详情

restful/
    - Request.php 数据操作类
    - Response.php 输出类
    - index.php 入口文件
    - .htaccess 重写url

Request.php

  • 包含一个Request类,即数据操作类。

  • 接收到URL的数据后,根据请求URL的方式(GET|POST|PUT|PATCH|DELETE)对数据进行相应的增删改查操作,并返回操作后的结果

      <?php
      /**
      * Request类,
      * 接收到URL的数据后,根据请求URL的方式(GET|POST|PUT|PATCH|DELETE)对数据进行相应的增删改查操作,并返回操作后的结果
      */
      class Request
      {
          // 允许的请求方式
          private static $method_type = array('get', 'post', 'put', 'patch', 'delete');
    
          // 测试数据
          private static $test_class = array(
              1 => array('name'=>'测试一班','count'=>18), 
              2 => array('name'=>'测试二班','count'=>15)
          );
    
          public static function getRequest()
          {
              // 请求方法
              $method = strtolower($_SERVER['REQUEST_METHOD']);
              if (in_array($method, self::$method_type)) {
                  // 调用请求方法对应的方法
                  $data_name = $method . "Data";
                  return self::$data_name($_REQUEST);
              }
              return false;
          }
    
          // GET 获取信息
          private static function getData($request_data)
          {
              $class_id = (int)$request_data['class'];
              if ($class_id > 0) {
                  // GET /class/ID: 获取某个指定班的信息
                  return self::$test_class[$class_id];
              }else{ 
                  // GET /class: 列出所有班级
                  return self::$test_class;
              }
          }
    
          // POST /class 新建一个班级
          private static function postData($request_data)
          {
              $class_id = (int)$request_data['class'];
              if ($class_id == 0) {
                  return false;
              }
              $data = array();
              if (!empty($request_data['name']) && isset($request_data['count'])) {
                  $data['name'] = $request_data['name'];
                  $data['count'] = $request_data['count'];
                  self::$test_class[] = $data;
                  return self::$test_class; 
              }else{
                  return false;
              }
          }
    
          // PUT /class/ID 更新某个指定班级的信息(全部信息)
          private static function putData($request_data)
          {
              $class_id = (int)$request_data['class'];
              if ($class_id == 0) {
                  return false;
              }
    
              $data = array();
              if (!empty($request_data['name']) && isset($request_data['count'])) {
                  $data['name'] = $request_data['name'];
                  $data['count'] = (int)$request_data['count'];
                  self::$test_class[$class_id] = $data;
                  return self::$test_class;
              }else{
                  return false;
              }
          }
    
          // PATCH /class/ID 更新某个指定班级的信息 (部分信息)
          private static function pacthData($request_data)
          {
              $class_id = (int)$request_data['class'];
              if ($class_id == 0) {
                  return false;
              }
              if (!empty($request_data['name'])) {
                  self::$test_class[$class_id]['name'] = $request_data['name'];
              }
              if (isset($request_data['count'])) {
                  self::$test_class[$class_id]['count'] = $request_data['count'];
              }
              return self::$test_class;
          }
    
          // DELETE /class/ID 删除某个班
          private static function deleteData($request_data)
          {
              $class_id = (int)$request_data['class'];
              if ($class_id == 0) {
                  return false;
              }
              unset(self::$test_class[$class_id]);
              return self::$test_class;
          }
      }
      ?>
    

Response.php

  • 包含一个Response类,即输出类。

  • 根据接收到的Content-Type,将Request类返回的数组拼接成对应的格式,加上header后输出

      <?php
      /**
      * 包含一个Response类,即输出类。根据接收到的Content-Type,将Request类返回的数组拼接成对应的格式,加上header后输出
      */
      class Response
      {
          const HTTP_VERSION = "HTTP/1.1";
      
          public function sendResponse($data)
          {
              // 获取数据
              if ($data) {
                  $code = 200;
                  $message = "OK";
              }else{
                  $code = 404;
                  $data = array('error' => "Not Found");
                  $message = "Not Found";
              }
      
              header(self::HTTP_VERSION . " $code $message");
              $content_type = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : $_SERVER['HTTP_ACCEPT'];
              if (strpos($content_type, 'application/json') !== false) {
                  header("Content-Type: application/json");
                  echo self::encodeJson($data);
              }elseif (strpos($content_type, 'application/xml') !== false) {
                  header("Content-Type: application/xml");
                  echo self::encodeXml($data);
              }else{
                  header("Content-Type: text/html");
                  echo self::encodeHtml($data);
              }
          }
      
          // json 格式
          private static function encodeJson($responseData)
          {
              return json_encode($responseData);
          }
      
          // xml 格式
          private static function encodeXml($responseData)
          {
              $xml = new SimpleXMLElement('<?xml version="1.0"?><rest></rest>');
              foreach ($responseData as $key => $value) {
                  if (is_array($value)) {
                      foreach ($value as $k => $v) {
                          $xml->addChild($k,$v);
                      }
                  }else{
                      $xml->addChild($key,$value);
                  }
              }
              return $xml->asXML();
          }
      
          // html 格式
          private static function encodeHtml($responseData)
          {
              $html = "<table border='1'>";
              foreach ($responseData as $key => $value) {
                  $html .= "<tr>";
                  if (is_array($value)) {
                      foreach ($value as $k => $v) {
                          $html .= "<td>$k</td><td>$v</td>";
                      }
                  }else{
                      $html .= "<td>$key</td><td>$value</td>";
                  }
                  $html .= "</tr>";
              }
              $html .="</table>";
              return $html;
          }
      }
      ?>
    

index.php

  • 入口文件
  • 调用 Request->getRequest 获取数据
  • 调用 Response->sendResponse 处理并返回数据

.htaccess

  • 重写URL,使URL以 /restful/class/1 形式访问文件

      Options +FollowSymlinks
      RewriteEngine on
      
      # 重写规则
      RewriteRule ^class$   index.php?class=all [nc,qsa]
      RewriteRule ^class/(\d+)$   index.php?class=$1 [nc,qsa]
    

测试方法

  • 采用 postman 测试

GET

  • 获取 json 类型
    • image
  • 获取 xml
    • image
  • 获取 html
    • image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容