REST (Representational State Transfer - передача состояния представления) - архитектурный стиль взаимодействия компонентов распределённого приложения в сети. REST представляет собой согласованный набор ограничений, учитываемых при проектировании распределённой гипермедиа-системы. В определённых случаях (интернет-магазины, поисковые системы, прочие системы, основанные на данных) это приводит к повышению производительности и упрощению архитектуры. REST является альтернативой RPC.
В сети Интернет вызов удалённой процедуры может представлять собой обычный HTTP-запрос (обычно GET или POST; такой запрос называют "REST-запрос"), а необходимые данные передаются в качестве параметров запроса.
Для веб-служб, построенных с учётом REST (то есть не нарушающих накладываемых им ограничений), применяют термин "RESTful".
В отличие от веб-сервисов на основе SOAP, не существует "официального" стандарта для RESTful веб-API. Дело в том, что REST является архитектурным стилем, в то время как SOAP является протоколом. Несмотря на то, что REST не является стандартом сам по себе, большинство RESTful-реализаций используют такие стандарты, как HTTP, URL, JSON и XML (но XML зачастую не принято использовать).
REST - это концепция для взаимодействия компонентов основанный на протоколе HTTP.
В Сети обмен происходит по протоколу HTTP: запрос - ответ. Для того, чтобы передать какие-то данные, их нужно как-то идентифицировать, то есть указать их "признак", "действие" или что-то подобное. И поэтому раньше данные требовалось оформить в виде какого-то сложного формата, обычно это XML или JSON.
Так вот, REST говорит что этого делать не нужно. Данные передаём как есть, только у HTTP-запроса указывается метод (параметр) для этих данных. Обычно мы оперируем GET и POST, поскольку они работают "из коробки" в HTML и их поддерживает любой браузер. Но на самом деле, метод у HTTP может быть абсолютно любым. Есть некие общепринятые: PUT, DELETE, OPTIONS, PATCH, но это совсем не стандарт.
То есть, например мы хотим отправить на сервер GET-запрос по адресу сайт/task и получить список задач (таски). Потом мы хотим добавить новую задачу: отправляем на тот же адрес сайт/task, но уже методом POST. Потом решили, что для редактирования задачи нужно отправить уже PUT и опять же на тот же адрес. И, уж коли пошла такая пьянка, то отправляем и метод DELETE для удаления какой-то задачи.
Формирование GET-запроса очень простое - достаточно набрать адрес в браузере. Для POST уже нужна HTML-форма с method=POST. Эти же методы прекрасно работают и через AJAX. Но, что касается PUT и DELETE, то ни HTML, ни браузер о них ничего не знают. Формально мы всё-таки можем их указывать, но наткнёмся на последнюю стенку - сервер, который также как правило ничего не знает об этих методах и рубанётся с ошибкой 501 или 405.
Таким образом, хоть HTTP и поддерживает произвольные методы, но в реальности работают только два: GET и POST.
Чтобы обойти это ограничение и применить REST к нашим сайтам, придумали хитрость. Все "нестандартные" запросы в своём теле должны содержать отдельное поле, где и указывается "желаемый" метод.
Устоявшаяся практика - метод указывать в поле _method формы или AJAX-запроса.
<form method="POST"> <input type="hidden" name="_method" value="PUT"> ... прочие данные формы ... </form>
То есть реальная отправка это POST, но приложение проверяет поле _method и по нему уже принимает решение что делать дальше.
Такой разбор выполняет роутер приложения. Если это так, то правила роутинга указываются примерно так:
[ 'method' => 'POST', // create new task (Create) 'pattern' => 'task', 'action' => '\Controller\Task\Task@create', ], [ 'method' => 'GET', // task show (Read) 'pattern' => 'task', 'action' => '\Controller\Task\Task@read', ], [ 'method' => 'PUT', // update/edit task (Update) 'pattern' => 'task', 'action' => '\Controller\Task\Task@update', ], [ 'method' => 'DELETE', // delete task (Delete) 'pattern' => 'task', 'action' => '\Controller\Task\Task@delete', ]
Обратите внимание, что во всех случаях используется один http-адрес: сайт/task - меняются только методы, которые указываются либо в HTML-форме, либо AJAX-запросе.
Здесь мы подходим к другой концепции - CRUD, которая не что иное, как аббревиатура от Create, Read, Update, Delete - Создать, Прочитать, Обновить, Удалить. Это не что иное, как основные операции для подавляющего большинства данных.
CRUD нужен для того, чтобы разделить программный код на отдельные части, каждая из которых отвечает за свои действия. В данном примере будет использован PHP-класс \Controller\Task\Task, где каждый HTTP-метод будет выполнен своим PHP-методом:
Если не использовать REST, то скорее всего пришлось бы указывать действие либо по отдельному URL-адресу, либо в GET-параметрах. Как-то так:
Для REST, конечно, требуется хоть какой-то роутинг, способный понимать _method. В общем случае это будет так:
$method = 'get'; // метод по умолчанию if ($_POST) { if (isset($_POST['_method'])) { $method = $_POST['_method']; } else { $method = 'post'; } }
Дальше роутер смотрит правила и находит PHP-метод для запуска.
REST - это только концепция, набор правил. Если же применять эти правила к приложению, то уже говорят о RESTFul. Например REST предполагает использование модели "клиент-сервер". Если мы предположим, что сервер - это реальный сервер хостинга, а клиент - пользователь сайта, то для RESTFul нужно уже настраивать реальный сервер, чтобы он понимал используемые HTTP-методы. Вряд ли кто-то будет это делать, поэтому с этой точки зрения приложение не может считаться RESTFul.
Но, с другой стороны, если REST-сервер - это просто абстракция, то какая нам разница как вообще работает реальный сервер, если его основная задача - просто отдавать и принимать что нам нужно? Даже если мы используем хитрость с _method, это работает как положено, а значит приложение соответствует RESTFul.
В целом стоит отметить, что сейчас REST и RESTFul - фактически синонимы. Если PHP-приложение может принимать хоть каким-то способом HTTP-метод, то считается, что это уже полноценный RESTFul. Нужно просто понимать, что архитектура REST позволяет нам использовать HTTP примерно так, как он изначально и задумывался.