JsonView
и XmlView
позволяют вам создавать ответы JSON и XML,
и интегрировать их с
Cake\Controller\Component\RequestHandlerComponent
.
Активируя RequestHandlerComponent
в вашем приложении, а также поддержку
расширений json
и/или xml
, вы можете автоматически использовать
новые классы представлений. JsonView
и XmlView
будут далее именоваться
просто как представления данных в этом разделе.
Существует два способа, с помощью которых вы можете создать представления
данных. Первый - используя ключ _serialize
, и второй - создав обычные
файлы шаблонов.
Прежде чем вы сможете использовать классы представлений данных, вам нужно
сначала загрузить
Cake\Controller\Component\RequestHandlerComponent
в вашем
контроллере:
public function initialize()
{
...
$this->loadComponent('RequestHandler');
}
Это может быть сделано в вашем AppController
, и активирует автоматическое
переключение классов представлений, в зависимости от типа содержимого. Вы
также можете настроить компонент с помощью опции viewClassMap
, чтобы
сопоставить типы вашим кастомным классам и/или добавить сопоставления также и
для других типов данных (отличных от JSON и XML).
Вы опционально можете включить поддержку расширений json и/или xml, используя
маршрутизацию по расширениям файлов. Это позволит вам
получать доступ к данным в определенном формате, будь то JSON
, XML
или
какой-либо другой формат, используя URL, оканчивающийся на имя типа ответа, как
если бы это было расширением файла. К примеру
http://example.com/articles.json
.
По умолчанию, когда не включена
маршрутизацию по расширениям файлов, запрос, для
которого использовался заголовок Accept
, определяет какого типа формат
должен быть выведен пользователю. Например, формат Accept
, используемый для
вывода ответа в формате JSON
- application/json
.
Ключ _serialize
- это особая переменная представления, указывающая, какие
другие переменные представления должны быть сериализованы при использовании
представлений данных. Это позволяет вам избежать определение файлов шаблонов
для экшенов ваших контроллеров, если вам не требуется какое-то особое
форматирование перед тем, как ваши данные будут сконвертированы в json/xml.
Если вам необходимо совершить какие-либо манипуляции с вашими переменными
представления перед генерированием ответа - используйте файлы шаблонов.
Значением переменной _serialize
может быть как строка, так и массив
переменных представления для сериализации:
namespace App\Controller;
class ArticlesController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
}
public function index()
{
// Установить переменные представления, которые должны
// быть сериализованы.
$this->set('articles', $this->paginate());
// Указываем, какие переменные представления JsonView
// должен сериализовать.
$this->set('_serialize', 'articles');
}
}
Вы можете также определить _serialize
как массив переменных
представления, которые нам нужно совместить:
namespace App\Controller;
class ArticlesController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
}
public function index()
{
// Какой-то код, создавший $articles и $comments
// Установливаем переменные представления, которые должны
// быть сериализованы.
$this->set(compact('articles', 'comments'));
// Указываем, какие переменные представления JsonView
// должен сериализовать.
$this->set('_serialize', ['articles', 'comments']);
}
}
Определяя _serialize
как массив, мы получаем преимущество автоматического
добавления элемента верхнего уровня <response>
при использовании
XmlView
. Если вы используете строковое значение для
_serialize
и XmlView, убедитесь в том, что ваша переменная представления
имеет единственный элемент верхнего уровня. Если элементов верхнего уровня
будет больше одного, Xml не сможет сгенерироваться.
Вы должны использовать файлы шаблонов, если вам нужно сделать какие-либо манипуляции с содержимым вашего представления перед созданием окончательного вывода. Например, если бы у нас были статьи, у которых было бы поле, содержащее сгенерированный HTML, мы, вероятно, хотели бы исключить это из ответа JSON. Это как раз та ситуация, когда файл представления будет полезен:
// Код контроллера
class ArticlesController extends AppController
{
public function index()
{
$articles = $this->paginate('Articles');
$this->set(compact('articles'));
}
}
// Код представления - src/Template/Articles/json/index.ctp
foreach ($articles as &$article) {
unset($article->generated_html);
}
echo json_encode(compact('articles'));
Вы можете выполнять более сложные манипуляции или использовать хелперы для форматирования. Классы представления данных не поддерживают макеты. Они предполагают, что в файле представлений выводится сериализованный контент.
Примечание
С версии 3.1.0 AppController
в каркасе приложения автоматически
добавляет '_serialize' => true
ко всем запросам XML/JSON. Вам
придется удалить этот код из коллбэк-метода beforeRender()
,
либо установить значение '_serialize' => false
в экшенах вашего
контроллера, если вы хотите использовать файлы представлений.
XmlView
¶По умолчанию при использовании _serialize
XmlView обернет ваши
сериализованные переменные в узел <response>
. Вы можете задать свое
собственное имя для этого узла, используя переменную представления
_rootNode
.
Класс XmlView поддерживает переменную _xmlOptions
, которая позволяет
вам изменять опции, используемые при генерировании XML
The XmlView class supports the _xmlOptions
variable that allows you to
customize the options used to generate XML, например tags
вместо
attributes
.
JsonView
¶Класс JsonView поддерживает переменную _jsonOptions
, которая позволяет
вам настроить битовую маску, используемую для генерирования JSON. См.
json_encode для более полной информации о
валидных значениях данной опции.
Например, чтобы сериализовать вывод ошибок валидации сущностей (entities) CakePHP в совместимой с JSON форме, сделайте следующее:
// Вэкшене вашего контроллера при ошибке сохранения
$this->set('errors', $articles->errors());
$this->set('_jsonOptions', JSON_FORCE_OBJECT);
$this->set('_serialize', ['errors']);
При использовании JsonView
вы можете использовать специальную переменную
представления _jsonp
для активации возможности получения ответа JSONP.
Если установить значение true
, класс представления проверяет, задан ли
параметр строки запроса с именем «callback» и, если это так, следует обернуть
ответ json в функцию с указанным именем. Если вы хотите использовать
собственное имя параметра строки запроса вместо «callback», установите
_jsonp
на требуемое имя вместо true
.
В то время, как RequestHandlerComponent может автоматически определять представление, основываясь на типе содержимого запроса или на расширении, вы также можете управлять сопоставлением представлений в вашем контроллере:
// src/Controller/VideosController.php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Network\Exception\NotFoundException;
class VideosController extends AppController
{
public function export($format = '')
{
$format = strtolower($format);
// Формат сопоставления представлений
$formats = [
'xml' => 'Xml',
'json' => 'Json',
];
// Ошибка на неизвестных типах
if (!isset($formats[$format])) {
throw new NotFoundException(__('Unknown format.'));
}
// Установка формата вывода представления
$this->viewBuilder()->className($formats[$format]);
// Получение данных
$videos = $this->Videos->find('latest');
// Назначение представления данных
$this->set(compact('videos'));
$this->set('_serialize', ['videos']);
// Принудительная загрузка
// До версии 3.4.0
// $this->response->download('report-' . date('YmdHis') . '.' . $format);
return $this->response->withDownload('report-' . date('YmdHis') . '.' . $format);
}
}