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

posted @ 2021-03-12 21:21  张志健  阅读(70)  评论(0编辑  收藏  举报