• restful设计架构,例子


      1 /**
      2  * Project: imooc-restful
      3  * User: xialei
      4  * Date: 2016/9/18 0018
      5  * Time: 9:35
      6  */
      7 require_once __DIR__ . '/../handler/User.php';
      8 require_once __DIR__ . '/../handler/Article.php';
      9 require_once __DIR__ . '/../handler/MyHttpException.php';
     10 
     11 class Bridge
     12 {
     13     /**
     14      * @var User
     15      */
     16     private $user;
     17     /**
     18      * @var Article
     19      */
     20     private $article;
     21     /**
     22      * @var string 请求方法
     23      */
     24     private $method;
     25     /**
     26      * @var string 请求实体
     27      */
     28     private $entity;
     29 
     30     /**
     31      * @var integer ID
     32      */
     33     private $id;
     34 
     35     /**
     36      * @var array 允许请求的实体类
     37      */
     38     private $allowEntities = ['users', 'articles'];
     39 
     40     private $allowMethods = ['GET', 'POST', 'PUT', 'OPTIONS', 'HEAD', 'DELETE'];
     41 
     42     /**
     43      * Bridge constructor.
     44      */
     45     public function __construct()
     46     {
     47         $pdo = require_once __DIR__ . '/../db.php';
     48         $this->user = new User($pdo);
     49         $this->article = new Article($pdo);
     50         $this->setupRequestMethod();
     51         $this->setupEntity();
     52     }
     53 
     54     /**
     55      * 初始化实体
     56      */
     57     private function setupEntity()
     58     {
     59         $pathinfo = $_SERVER['PATH_INFO'];
     60         if (empty($pathinfo))
     61         {
     62             static::sendHttpStatus(400);
     63         }
     64         $params = explode('/', $pathinfo);
     65         $this->entity = $params[1];
     66         if (!in_array($this->entity, $this->allowEntities))
     67         {
     68             //实体不存在
     69             static::sendHttpStatus(404);
     70         }
     71         if (!empty($params[2]))
     72         {
     73             $this->id = $params[2];
     74         }
     75     }
     76 
     77     /**
     78      * 发送HTTP响应状态码
     79      * @param $code
     80      * @param string $error
     81      * @param array|null $data
     82      * @internal param null $message
     83      */
     84     static function sendHttpStatus($code, $error = '', $data = null)
     85     {
     86         static $_status = array(
     87             // Informational 1xx
     88             100 => 'Continue',
     89             101 => 'Switching Protocols',
     90             // Success 2xx
     91             200 => 'OK',
     92             201 => 'Created',
     93             202 => 'Accepted',
     94             203 => 'Non-Authoritative Information',
     95             204 => 'No Content',
     96             205 => 'Reset Content',
     97             206 => 'Partial Content',
     98             // Redirection 3xx
     99             300 => 'Multiple Choices',
    100             301 => 'Moved Permanently',
    101             302 => 'Found',  // 1.1
    102             303 => 'See Other',
    103             304 => 'Not Modified',
    104             305 => 'Use Proxy',
    105             // 306 is deprecated but reserved
    106             307 => 'Temporary Redirect',
    107             // Client Error 4xx
    108             400 => 'Bad Request',
    109             401 => 'Unauthorized',
    110             402 => 'Payment Required',
    111             403 => 'Forbidden',
    112             404 => 'Not Found',
    113             405 => 'Method Not Allowed',
    114             406 => 'Not Acceptable',
    115             407 => 'Proxy Authentication Required',
    116             408 => 'Request Timeout',
    117             409 => 'Conflict',
    118             410 => 'Gone',
    119             411 => 'Length Required',
    120             412 => 'Precondition Failed',
    121             413 => 'Request Entity Too Large',
    122             414 => 'Request-URI Too Long',
    123             415 => 'Unsupported Media Type',
    124             416 => 'Requested Range Not Satisfiable',
    125             417 => 'Expectation Failed',
    126             422 => 'Unprocessable Entity',
    127             // Server Error 5xx
    128             500 => 'Internal Server Error',
    129             501 => 'Not Implemented',
    130             502 => 'Bad Gateway',
    131             503 => 'Service Unavailable',
    132             504 => 'Gateway Timeout',
    133             505 => 'HTTP Version Not Supported',
    134             509 => 'Bandwidth Limit Exceeded'
    135         );
    136         if (isset($_status[$code]))
    137         {
    138             header('HTTP/1.1 ' . $code . ' ' . $_status[$code]);
    139             header('Content-Type:application/json;charset=utf-8');
    140             if ($code == 200) //2xx状态码
    141             {
    142                 echo json_encode($data, JSON_UNESCAPED_UNICODE);
    143             }
    144             else if ($code == 204)
    145             {
    146                 //无响应体
    147             }
    148             else
    149             {
    150                 if (empty($error))
    151                 {
    152                     $error = $_status[$code];
    153                 }
    154                 echo json_encode(['error' => $error], JSON_UNESCAPED_UNICODE);
    155             }
    156         }
    157         exit(0);
    158     }
    159 
    160     /**
    161      * 初始化请求方法
    162      */
    163     private function setupRequestMethod()
    164     {
    165         $this->method = $_SERVER['REQUEST_METHOD'];
    166         if (!in_array($this->method, $this->allowMethods))
    167         {
    168             //请求方法不被允许
    169             static::sendHttpStatus(405);
    170         }
    171     }
    172 
    173     /**
    174      * 处理请求
    175      */
    176     public function handle()
    177     {
    178         try
    179         {
    180             if ($this->entity == 'users')
    181             {
    182                 $this->handleUser();
    183             }
    184             if ($this->entity == 'articles')
    185             {
    186                 $this->handleArticle();
    187             }
    188         }
    189         catch (MyHttpException $e)
    190         {
    191             static::sendHttpStatus($e->getStatusCode(), $e->getMessage());
    192         }
    193     }
    194 
    195     /**
    196      * 获取请求体
    197      * @return mixed|null
    198      */
    199     private function getBodyParams()
    200     {
    201         $raw = file_get_contents('php://input');
    202         if (empty($raw))
    203         {
    204             return [];
    205         }
    206         return json_decode($raw, true);
    207     }
    208 
    209     private function getBodyParam($name, $defaultValue = null)
    210     {
    211         $data = $this->getBodyParams();
    212         return isset($data[$name]) ? $data[$name] : $defaultValue;
    213     }
    214 
    215     /**
    216      * 要求认证
    217      * @return bool|array
    218      * @throws MyHttpException
    219      */
    220     private function requestAuth()
    221     {
    222         if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW']))
    223         {
    224             try
    225             {
    226                 $user = $this->user->login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
    227                 return $user;
    228             }
    229             catch (MyHttpException $e)
    230             {
    231                 if ($e->getStatusCode() != 422)
    232                 {
    233                     throw $e;
    234                 }
    235             }
    236         }
    237         header("WWW-Authenticate:Basic realm='Private'");
    238         header('HTTP/1.0 401 Unauthorized');
    239         print "You are unauthorized to enter this area.";
    240         exit(0);
    241     }
    242 
    243     /**
    244      * 处理访问用户的请求
    245      */
    246     private function handleUser()
    247     {
    248         if ($this->method == 'GET')
    249         {
    250             if (empty($this->id))
    251             {
    252                 //客户端需要获取所有用户的信息,访问有效,但是无权限
    253                 throw new MyHttpException(403);
    254             }
    255             static::sendHttpStatus(200, null, $this->user->view($this->id));
    256         }
    257         else if ($this->method == 'POST')
    258         {
    259             $data = $this->getBodyParams();
    260             if (empty($data['username']))
    261             {
    262                 throw new MyHttpException(422, '用户名不能为空');
    263             }
    264             if (empty($data['password']))
    265             {
    266                 throw new MyHttpException(422, '密码不能为空');
    267             }
    268             static::sendHttpStatus(200, null, $this->user->register($data['username'], $data['password']));
    269         }
    270         else if ($this->method == 'PUT')
    271         {
    272             if (empty($this->id))
    273             {
    274                 throw new MyHttpException(400);
    275             }
    276             $params = $this->getBodyParams();
    277             if (empty($params) || empty($params['password']))
    278             {
    279                 throw new MyHttpException(422, '密码不能为空');
    280             }
    281             //检测认证参数
    282             $user = $this->requestAuth();
    283             $result = $this->user->update($user['userId'], $params['password']);
    284             static::sendHttpStatus(200, null, $result);
    285         }
    286         else
    287         {
    288             throw new MyHttpException(405);
    289         }
    290     }
    291 
    292     private function getQueryParam($name, $defaultValue = null)
    293     {
    294         return isset($_GET[$name]) ? $_GET[$name] : $defaultValue;
    295     }
    296 
    297     /**
    298      * 处理访问文章的请求
    299      */
    300     private function handleArticle()
    301     {
    302         if ($this->method == 'GET')
    303         {
    304             $user = $this->requestAuth();
    305             if (empty($this->id))
    306             {
    307                 $list = $this->article->all($user['userId'], $this->getQueryParam('page', 1), $this->getQueryParam('size', 10));
    308                 self::sendHttpStatus(200, null, $list);
    309             }
    310             self::sendHttpStatus(200, null, $this->article->view($this->id));
    311         }
    312         else if ($this->method == 'POST')
    313         {
    314             $user = $this->requestAuth();
    315             $data = $this->getBodyParams();
    316             if (empty($data['title']))
    317             {
    318                 throw new MyHttpException(422, '标题不能为空');
    319             }
    320             if (empty($data['content']))
    321             {
    322                 throw new MyHttpException(422, '内容不能为空');
    323             }
    324             $article = $this->article->create($data['title'], $data['content'], $user['userId']);
    325             static::sendHttpStatus(200, null, $article);
    326         }
    327         else if ($this->method == 'PUT')
    328         {
    329             if (empty($this->id))
    330             {
    331                 throw new MyHttpException(400);
    332             }
    333             $user = $this->requestAuth();
    334             $data = $this->getBodyParams();
    335             $title = isset($data['title']) ? $data['title'] : null;
    336             $content = isset($data['content']) ? $data['content'] : null;
    337             $article = $this->article->update($this->id, $title, $content, $user['userId']);
    338             static::sendHttpStatus(200, null, $article);
    339         }
    340         else if ($this->method == 'DELETE')
    341         {
    342             if (empty($this->id))
    343             {
    344                 throw new MyHttpException(400);
    345             }
    346             $user = $this->requestAuth();
    347             $this->article->delete($this->id, $user['userId']);
    348             static::sendHttpStatus(204, null, null);
    349         }
    350     }
    351 }
    352 
    353 
    354 $bridge = new Bridge();
    355 $bridge->handle();

    转于:https://www.imooc.com/video/14365 ,微信xialeistudio

      完整代码:https://github.com/xialeistudio/imooc-restful

  • 相关阅读:
    ! JOISC2020DAY2变色龙之恋
    ! JOISC2020DAY1扫除
    JOISC2020DAY1汉堡肉
    JOISC2020DAY1建筑装饰4
    ! JLOI/SHOI2016随机序列
    JLOI/SHOI2016黑暗前的幻想乡
    ! JLOI/SHOI2016成绩比较
    JLOI/SHOI2016方
    JLOI/SHOI2016侦查守卫
    ! AHOI/HNOI2017抛硬币
  • 原文地址:https://www.cnblogs.com/zhangzhijian/p/14526432.html
Copyright © 2020-2023  润新知