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-методом:

  • для POST будет выполнен метод create()
  • для GET будет выполнен метод read()
  • для PUT будет выполнен метод update()
  • для DELETE будет выполнен метод delete()

Если не использовать REST, то скорее всего пришлось бы указывать действие либо по отдельному URL-адресу, либо в GET-параметрах. Как-то так:

  • сайт/task/create
  • сайт/task/update/7
  • сайт/task/delete/5
  • сайт/task?action=create
  • сайт/task?action=update&id=7
  • сайт/task?action=delete&id=5

Для 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 примерно так, как он изначально и задумывался.