Подход REST в PHP
- Опубликовано 20:59:47 14.12.2009
- Метки:
Продолжим тему начатую в прошлой статье про подход REST, рассмотрим со стороны сервера с использованием языка PHP. Согласно принципу REST нам предстоит реализовать четыре операции: GET, PUT, POST и DELETE.
Примеры будут построены на основе классической схемы построения современных web приложений построенной по потерну MVC (Model View Controller). Мой код будет базироваться на моем движке, но я думаю кто знаком с патерном MVC смогут понять, я рассмотрю только основные заморочки.
Рассмотрим подробней как ExtJS передает и принимает данные. Адрес по которому ExtJs обращается для работы с данными настраивается в Ext.data.HttpProxy параметром url.
var proxy = new Ext.data.HttpProxy({
url: '/controller'
});
Также если не охота связываться или по каким то причинам не возможно использовать разные HTTP методы. То можно указать для них другие урлы и методы вот так:
var proxy = new Ext.data.HttpProxy({
url: '/controller',
api: {
load: {url: '/controller/load', method: 'GET'},
create: '/controller/create',
destroy: '/controller/destroy',
save: '/controller/update'
}
});
Но мы то пойдем джедайским путем и будем использовать HTTP методы.
Первая проблема состоит в том, что PHP не разбирает переданные параметры методом PUT поэтому — это предстоит сделать нам, взяв их прям из потока php://input.Для начала создадим класс который будет прозрачно возвращать нам данные независимо от метода.
class Request {
public $params,$method;
public function __construct() {
$this->method = $_SERVER["REQUEST_METHOD"]; // Получим метод
if($this->method == 'PUT'){ // Если метод PUT парсим параметры в ручную :)
$this->params = array();
$putdata = file_get_contents('php://input'); // Взяли все данные
parse_str($putdata,$this->params); // Распарсили
} else {
this->params = $_REQUEST;
}
}
}
Вот такой получился у нас простенький класс.
Вторая проблема может возникнуть при удаление и обновление. ExtJs идентификатор объекта добавляет в адрес скрипта вот так /url/id. Большинство MVC фраемворков данный формат хорошо разбирают и как правило передают во внутрь метода контроллера. Что делать если ваш движок этого не умеет, тогда можно сделать переадресацию с помощью mod rewrite. Либо, например, указав в качестве урла /app.php?/controller, а там уже парсить строку запроса самому, взяв из переменной $_SERVER["PATH_INFO"]. Например вот такой регуляркой preg_match ('/^\/([a-z]+\w)\/([0–9]+)$/', $_SERVER["PATH_INFO"], $matches).
Третья проблема -это то что ExtJs для вставке новой и изменение старой записи параметры передает в качестве JSON строке, в переменной с именем указанном в Ext.data.Store, в переменной root вообще-то это не большая проблема, берем и конвертируем с помощью функции json_decode (stripslashes ($param['data'])).
Формат отдачи данных для ExtJs единый для всех методов.Нужно передать флаг success об успешности операции. Также передается массив данных, которые претерпели изменения в переменной, которая указана в Ext.data.Store в переменной root.
Теперь создадим наш контроллер, который будет обрабатывать пользователей нашего сайта.
class CRestController extends Controller {
public function rest($params) { // в метод передается как раз список параметров, идущих после названия метода разделенных слешем
$request = new Request();
$id = isset($params[0])?$params[0]:false; // вытащим id он у нас идет первым
$data = isset($request->params['data'])?json_decode(stripslashes($param['data'])):false; // Распарсим наши JSON данные
try {
switch ($this->request->method) { // Данные функции должны быть определены в конечных контроллерах
case 'GET':
return $this->load(); // Получение списка параметров
break;
case 'POST':
return $this->create($data);
break;
case 'PUT':
return $this->update($id,$data);
break;
case 'DELETE':
return $this->destroy($id);
break;
}
} catch(Exception $ex)
{
return new JsonView($this,array(
'success' => false,
'message' => $ex->getMessage()
));
}
}
}
Рассматривать каждый метод не буду, их реализация зависит от используемого движка. Но все они должны вернуть клиенту структуру такого вида:
{
success:true, // Флаг успешности операции
message:'', // Сообщение если нужно
data:[ // При удаление и если при обновление данные сервер не изменяет, параметр не нужен
/* массив данных согласно структуре заданной в Ext.data.Record */
]
}
У меня в движке, это происходит примерно так:
function load(){
return new JsonView($this,array(
'success' => true,
'data' => MUser::getAll()
));
}
В моем движке JsonView отвечает за вывод данных в JSON, вы же можете для этих целях использовать функцию json_encode. Я постарался как можно понятней изложить суть вопроса, но если, что-то все таки не понятно, спрашивайте в комментариях. Также на сайте ExtJS появился пример использования этой технологии, можете посмотреть там
Понравилась статья? Помогите блогу перейдите по рекламе, вам это ничего не будет стоить.