Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

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/articlesindex()
GET /api/articles/5view(5)
POST /api/articlesadd()
PUT /api/articles/5edit(5)
DELETE /api/articles/5delete(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() попадают в ответ со всеми своими полями. Проверьте глазами ответ каждого маршрута и скройте всё, что клиенту знать не нужно.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.