PHP RESTful

REST (по-английски: Representational State Transfer, сокращенно REST) означает набор архитектурных ограничений и принципов.

Веб-API, соответствующие стилю проектирования REST, называются RESTful API. Они определяют ресурсы с точки зрения следующих трех аспектов:

  • Интуитивно понятный и краткий адрес ресурса: URI, например:http://example.com/resources/。
  • Передаваемый ресурс: интернет-медиатипы, которые веб-служба принимает и возвращает, например JSON, XML, YAM и т. д.
  • Операции над ресурсом: набор методов запроса, поддерживаемых веб-службой для этого ресурса (например, POST, GET, PUT или DELETE).

В этом учебнике мы будем использовать PHP (без фреймворка) для создания RESTful веб-службы. В конце статьи вы сможете скачать код, использованный в этой главе.

В этом учебнике вы узнаете следующее:

  • Создать RESTful веб-службу.
  • Использовать нативный PHP, не завися от какого-либо фреймворка.
  • Шаблоны URI должны следовать правилам REST.
  • Форматы, которые принимает и возвращает RESTful-сервис, могут быть JSON, XML и т. д.
  • Отвечайте соответствующими кодами состояния HTTP в зависимости от различных ситуаций.
  • Продемонстрируйте использование заголовков запроса.
  • Используйте REST-клиент для тестирования RESTful-веб-сервиса.

Пример RESTful-веб-сервиса

Следующий код — это класс RESTful-сервисаSite.php:

Пример

<?php /** Пример демонстрации RESTful из учебного руководства * Класс RESTful-сервиса*/ Class Site { private $sites = array( 1 => 'TaoBao', 2 => 'Google', 3 => 'Example', 4 => 'Baidu', 5 => 'Weibo', 6 => 'Sina' ); public function getAllSite(){ return $this->sites; } public function getSite($id){ $site = array($id => ($this->sites[$id]) ? $this->sites[$id] : $this->sites[1]); return $site; } } ?>

Сопоставление URI RESTful-сервисов

URI RESTful-сервисов должен быть задан как интуитивно понятный и краткий адрес ресурса. В .htaccess сервера Apache должны быть настроены соответствующие правила Rewrite.

В этом примере мы будем использовать два правила URI:

1. Получить список всех сайтов:

http://localhost/restexample/site/list/

2. Использовать id для получения конкретного сайта. Следующий URI получает сайт с id 3:

http://localhost/restexample/site/list/3/

Правила конфигурации файла проекта .htaccessследующие:

# 开启 rewrite 功能
Options +FollowSymlinks
RewriteEngine on

# 重写规则
RewriteRule ^site/list/$   RestController.php?view=all [nc,qsa]
RewriteRule ^site/list/([0-9]+)/$   RestController.php?view=single&id=$1 [nc,qsa]

Контроллер RESTful веб-сервиса

В.htaccessВ файле мы получаем соответствующий запрос в файле RestController.php, устанавливая параметр 'view', и перенаправляем к разным методам, получая разные параметры 'view'.RestController.php Код файла выглядит следующим образом:

Пример

<?php require_once("SiteRestHandler.php"); $view = ""; if(isset($_GET["view"])) $view = $_GET["view"]; /** Контроллер RESTful-сервиса * Сопоставление URL*/ switch($view){ case "all": //Обработать REST URL /site/list/ $siteRestHandler = new SiteRestHandler(); $siteRestHandler->getAllSites(); break; case "single": //Обработать REST URL /site/show/<id>/ $siteRestHandler = new SiteRestHandler(); $siteRestHandler->getSite($_GET["id"]); break; case "" : //404 - не найдено; break; } ?>

Простой базовый класс RESTful

Ниже представлен базовый класс для RESTful, используемый для обработки кодов состояния HTTP при ответе на запросы,SimpleRest.phpКод файла выглядит следующим образом:

Пример

<?php /** Простой базовый класс для RESTful веб-сервисов * Мы можем расширять требования на основе этого класса*/ class SimpleRest { private $httpVersion = "HTTP/1.1"; public function setHttpHeaders($contentType, $statusCode){ $statusMessage = $this -> getHttpStatusMessage($statusCode); header($this->httpVersion. " ". $statusCode ." ". $statusMessage); header("Content-Type:". $contentType); } public function getHttpStatusMessage($statusCode){ $httpStatus = array( 100 => 'Продолжить', 101 => 'Переключение протоколов', 200 => 'ОК', 201 => 'Создано', 202 => 'Принято', 203 => 'Неавторитетная информация', 204 => 'Нет содержимого', 205 => 'Сбросить содержимое', 206 => 'Частичное содержимое', 300 => 'Множественный выбор', 301 => 'Перемещено навсегда', 302 => 'Найдено', 303 => 'Смотреть другое', 304 => 'Не изменено', 305 => 'Использовать прокси', 306 => '(Не используется)', 307 => 'Временное перенаправление', 400 => 'Неверный запрос', 401 => 'Неавторизован', 402 => 'Требуется оплата', 403 => 'Запрещено', 404 => 'Не найдено', 405 => 'Метод не разрешён', 406 => 'Неприемлемо', 407 => 'Требуется аутентификация прокси', 408 => 'Тайм-аут запроса', 409 => 'Конфликт', 410 => 'Удалён', 411 => 'Требуется длина', 412 => 'Предусловие не выполнено', 413 => 'Объект запроса слишком велик', 414 => 'Request-URI слишком длинный', 415 => 'Неподдерживаемый тип носителя', 416 => 'Запрошенный диапазон не удовлетворён', 417 => 'Ожидание не выполнено', 500 => 'Внутренняя ошибка сервера', 501 => 'Не реализовано', 502 => 'Плохой шлюз', 503 => 'Сервис недоступен', 504 => 'Тайм-аут шлюза', 505 => 'Версия HTTP не поддерживается'); return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $status[500]; } } ?>

Класс обработчика RESTful веб-службы

Ниже приведён класс обработчика RESTful веб-службы SiteRestHandler.php, который наследует базовый класс RESTful, предоставленный выше. Класс определяет возвращаемый код состояния HTTP и формат данных, анализируя параметры запроса. В примере мы предоставляем три формата данных: "application/json", "application/xml" или "text/html":

SiteRestHandler.phpКод файла следующий:

Пример

<?php require_once("SimpleRest.php"); require_once("Site.php"); class SiteRestHandler extends SimpleRest { function getAllSites() { $site = new Site(); $rawData = $site->getAllSite(); if(empty($rawData)) { $statusCode = 404; $rawData = array('error' => 'Сайты не найдены!'); } else { $statusCode = 200; } $requestContentType = $_SERVER['HTTP_ACCEPT']; $this ->setHttpHeaders($requestContentType, $statusCode); if(strpos($requestContentType,'application/json') !== false){ $response = $this->encodeJson($rawData); echo $response; } else if(strpos($requestContentType,'text/html') !== false){ $response = $this->encodeHtml($rawData); echo $response; } else if(strpos($requestContentType,'application/xml') !== false){ $response = $this->encodeXml($rawData); echo $response; } } public function encodeHtml($responseData) { $htmlResponse = "<table border='1'>"; foreach($responseData as $key=>$value) { $htmlResponse .= "<tr><td>". $key. "</td><td>". $value. "</td></tr>"; } $htmlResponse .= "</table>"; return $htmlResponse; } public function encodeJson($responseData) { $jsonResponse = json_encode($responseData); return $jsonResponse; } public function encodeXml($responseData) { //Создать объект SimpleXMLElement $xml = new SimpleXMLElement('<?xml version="1.0"?><site></site>'); foreach($responseData as $key=>$value) { $xml->addChild($key, $value); } return $xml->asXML(); } public function getSite($id) { $site = new Site(); $rawData = $site->getSite($id); if(empty($rawData)) { $statusCode = 404; $rawData = array('error' => 'Сайты не найдены!'); } else { $statusCode = 200; } $requestContentType = $_SERVER['HTTP_ACCEPT']; $this ->setHttpHeaders($requestContentType, $statusCode); if(strpos($requestContentType,'application/json') !== false){ $response = $this->encodeJson($rawData); echo $response; } else if(strpos($requestContentType,'text/html') !== false){ $response = $this->encodeHtml($rawData); echo $response; } else if(strpos($requestContentType,'application/xml') !== false){ $response = $this->encodeXml($rawData); echo $response; } } } ?>

Далее мы обращаемся по адресу http://localhost/restexample/site/list/, и результат вывода выглядит следующим образом:


Клиент RESTful веб-службы

Далее мы можем использовать "Advance Rest Client" в браузере Google Chrome в качестве клиента RESTful веб-службы для запроса к нашей службе.

В примере запрашивается адрес http://localhost/restexample/site/list/, и полученные данные выглядят примерно так:Accept: application/json

Запросите сайт Example с id 3, адрес доступа: http://localhost/restexample/site/list/3/,

Скачать исходный код

Код, использованный в примере, можно скачать, нажав на следующую кнопку:

Скачать исходный код

Другие расширения