REST API
API — адреса, которые отдают не страницы, а данные в формате JSON: их читает мобильное приложение или код на JavaScript. REST — распространённый способ построить API, где адрес обозначает ресурс (статьи), а HTTP-метод — действие над ним. В CakePHP для этого есть маршруты ресурсов и представление JSON, которому не нужны шаблоны.
Маршруты
// config/routes.php
$routes->scope('/api', function (RouteBuilder $builder): void {
$builder->setExtensions(['json']);
$builder->resources('Articles');
});Этот блок ставят внутри общей функции файла рядом с scope('/'). Одна строка resources() создаёт пять маршрутов:
| Запрос | Действие |
|---|---|
GET /api/articles | index() |
GET /api/articles/5 | view(5) |
POST /api/articles | add() |
PUT /api/articles/5 | edit(5) |
DELETE /api/articles/5 | delete(5) |
Ответ JSON
// src/Controller/ArticlesController.php
use Cake\View\JsonView;
public function viewClasses(): array
{
return [JsonView::class];
}
public function index(): void
{
$articles = $this->Articles->find()->all();
$this->set(compact('articles'));
$this->viewBuilder()->setOption('serialize', ['articles']);
}viewClasses() разрешает контроллеру отвечать в формате JSON. Настройка serialize называет переменные, которые попадут в ответ. Откройте /api/articles.json — вместо страницы придёт объект с ключом articles и массивом статей. Шаблон для этого не нужен.
Одна запись
public function view(int $id): void
{
$article = $this->Articles->get($id);
$this->set(compact('article'));
$this->viewBuilder()->setOption('serialize', ['article']);
}Если статьи нет, get() вернёт ошибку 404 — тоже в формате JSON.
Приём данных
Клиент API присылает данные в теле запроса в формате JSON. Чтобы getData() их понимал, в метод middleware() файла src/Application.php добавляют посредник:
use Cake\Http\Middleware\BodyParserMiddleware;
->add(new BodyParserMiddleware())После этого действие создания выглядит привычно:
public function add(): void
{
$article = $this->Articles->newEntity($this->request->getData());
if ($this->Articles->save($article)) {
$this->response = $this->response->withStatus(201);
$this->set(compact('article'));
$this->viewBuilder()->setOption('serialize', ['article']);
return;
}
$this->response = $this->response->withStatus(422);
$this->set('errors', $article->getErrors());
$this->viewBuilder()->setOption('serialize', ['errors']);
}При успехе клиент получает созданную статью и код 201, при ошибке проверки — код 422 и сообщения по полям.
Проверка из терминала
curl -H "Accept: application/json" http://localhost:8765/api/articles/1Заголовок Accept работает так же, как окончание .json в адресе.
Скрытые поля
В ответ попадают все поля записи. Те, что отдавать нельзя, перечисляют в классе записи:
// src/Model/Entity/User.php
protected array $_hidden = ['password'];Защита от CSRF
Проверка токена CSRF рассчитана на формы и отклонит запросы POST от клиента API. Для адресов /api её отключают, а пользователя проверяют токеном в заголовке — плагин Authentication умеет и это.
Частая ошибка
Без $_hidden API отдаёт запись целиком — вместе с хешем пароля. А связанные данные из contain() попадают в ответ со всеми своими полями. Проверьте глазами ответ каждого маршрута и скройте всё, что клиенту знать не нужно.