Построение и тестирование REST API в Yii2

Вебинар-скринкаст о сравнении протоколов удалённого вызова процедур RPC, доступа к объектам SOAP и архитектуры REST для реализации API для работы с сайтом. Рассмотрели написание RESTFul API для проекта на Yii2 Framework и его тестирование с использованием Codeception:

Открыть на YouTube | Исходники примера

Приглашаю на следующие видеоуроки. Анонс и ссылку на эфир, как обычно, пришлю в отдельной рассылке по вебинарам:

И задавайте вопросы в комментариях. Заранее спасибо и до встречи в эфире!

Комментарии

 

Леша

Спасибо Дим. Очень кстати)))

Ответить

 

Ержан Шаймерденов

Спасибо, очень доступно и познавательно!

Ответить

 

Михаил – ardupilot-mega.ru

Дмитрий спасибо за выложенное видео, но 6 часов видео - это многовато! мне 3 дня езды на работу смотреть )))

Ответить

 

KOVALSKY

Ставим на ютюбе скорость плеера 1.5x и все становится чуть быстрее, но не менее понятно ;)

Ответить

 

Max Eyed

Спасибо, Дмитрий. Просто отлично!

Дурацкий вопрос: а как в редакторе импортировать классы без вызова контекстного меню?
Как, например, вот тут: https://youtu.be/jDj_JggZXsU?t=4h50m42s

Ответить

 

Дмитрий Елисеев

Поставить курсор после класса и нажать Ctrl + Пробел.

Ответить

 

Max Eyed

У меня на такое вместо импорта вставляется yii\filters\auth\ перед классом.

Ответить

 

Дмитрий Елисеев

Settings - Editor - General - Autoimport - Enable auto-import in namespace scope.

Ответить

 

Max Eyed

Включено!

Ответить

 

Артём

Alt + enter. Тогда class импортируется в use

Ответить

 

Денис Бондарь

Alt + Enter на классе и выбираете Import. Без контекстного меню, кажется, это не получится сделать.

Ответить

 

slo_nik

Добрый день.
Благодарю за ссылку, буду пересматривать и пробовать реализовать у себя. Вопросы, наверняка, будут после.

Ответить

 

ТимЛид

Как можно было элементарную тему растянуть на 6 часов?? Полнейший бред... читайте официальную доку, не в обиду автору.

Ответить

 

slo_nik

Сделайте лучше!
А мы посмотрим и оценим, насколько Ваш комментарий соответствует действительности.

Ответить

 

slo_nik

Добрый вечер, Дмитрий.
Пытаюсь пересматривать, но что-то постоянно отвлекает))) Ну не в этом дело.
Такой вопрос появился. По поводу повторного использования запроса(идемпотентность, если правильно запомнил).
Вы сказали, что запрос методом DELETE подпадает под это определение, что сколько бы не отправляли запрос на удаление несуществующего поста, всегда вернётся список остальных постов.
А правильно ли это? Может в этом случае возвращать ошибку, а не список постов?

p.s. приблизительно на 1:27 минуте.

Ответить

 

Дмитрий Елисеев

Чаще DELETE будет возвращать статус 204 No Content.

Ответить

 

Дмитрий

Привет теска, подскажи почему в API при генерации тестов не добавился метод haveFixtures?
конфиг норм, все перерыл уже

class_name: FunctionalTester
modules:
    enabled:
        - REST:
            depends: PhpBrowser
            url: 'http://api.link.yii/index-test.php'
            part: [json]
        - Yii2:
            part: [orm, fixtures] # тут главное указано что должен подгружать и методы фикстур
            entryScript: index-test.php

Codeception ставил глобально и переменную PATH поправил чтобы команда всегда была доступна.

Ответить

 

Дмитрий Елисеев

Замените FunctionalTester на ApiTester

Ответить

 

Дмитрий

не в этом дело, я и так уже пробовал... в общем нашел уже причину блин все делал по учебнику версия codeception была 2.1.11 обновил до 2.2.9 - все норм сгенерил с тем же конфигом

Ответить

 

Олег

Дмитрий, чуть-чуть оффтопа)) Подскажите, пожалуйста, как добавить зависимость в composer.json на примере https://github.com/par0noid/ts3admin.class

Ответить

 

Дмитрий Елисеев
composer require par0noid/ts3admin
Ответить

 

Олег

Благодарю, а я его пробовал omposer require par0noid/ts3admin.class

Ответить

 

Stevan

Дмитрий, you should consider making webinars and tutorials on English also, There is really a lack of Yii2 content in English language compared to other frameworks,

Ответить

 

slo_nik

Stevan, а может Вам подучить русский язык? )))

Ответить

 

Stevan

То за мене вероватно не би био неки проблем, али би онима који нису Словени могло да одузме мало више времена. Вероватно би научли таман за Руске туторијале за Yii3 :)

Ответить

 

slo_nik

Дмитирй, ещё раз благодарю за интересный вебинар.
Досмотрел почти до конца, чуть-чуть осталось)))
Такой вопрос.
Всё работает, тестируется и так далее.
При обновлении профиля сделал специально ошибку в имени атрибута(description)
В ProfileController есть такая проверка

        if ($model->save() === false && $model->hasErrors()) {
            throw new ServerErrorHttpException('Failed to update the object for unknown reason.');
        }

Если я правильно понимаю, то должно вернуться исключение, раз ошибка в атрибуте, а возвращается неизменённая модель, то есть старые данные.
Так и должно быть?

Ответить

 

Дмитрий Елисеев

Метод $model->load($post) загрузит только атрибуты из rules(), а остальные пропустит.

Ответить

 

slo_nik

Получается, что ошибка вернётся только в том случае, если не сохранится модель.
А если ошибка в имени атрибута, или что-либо похожее, то никакой ошибки не будет?
Не стоит заморачиваться с настройками реакции на такие ошибки?

Ответить

 

Дмитрий Елисеев

Обычно не заморачиваются.

Ответить

 

slo_nik

Дмитрий, а как разделить тестовые базы для restful и основного сайта?
Файлы test.php и test-local.php в api/config я настроил, прописал там тестовую базу.
Но если выполнить в консоли php yii_test migrate, то настройки будут браться из common/test.php и test-local.php

Ответить

 

Дмитрий Елисеев

Сделайте ещё один файл yii_test_api с подгрузкой api/config/test-local.php.

Ответить

 

Slo_nik Дмитрий

Благодарю, попробую. Я пытался продублировать yii_test в api директории, но ничего не получилось. Буду пытаться сделать как Вы советуете
И вот ещё такой вопрос.
На вебинаре не рассмтривался вопрос регистрации. Если делать регистрацию, то что в таком случае возвращать пользователю? Ссылку на подтверждение e-mail или сразу авторизировать и возвращать токен?
Как обычно делают регистрацию для api?

Ответить

 

Дмитрий Елисеев

Если нужно подтверждать - то отправьте письмо со ссылкой и верните 200 OK.

Ответить

 

Александр Сахнов

Спасибо

Ответить

 

Вячеслав

Вопрос конечно не по теме, но

как с помощью git checkout перейти на один коммит вверх

откатиться вниз git checkout head~1

это для того чтобы слить с github исходники и сначала до конца пройтись по всем коммитам

Заранее спасибо

Ответить

 

Дмитрий Елисеев

В Git комит хранит ссылку только на предыдущий. Если из коммита начинаются несколько веток, то верхних будет два. Поэтому можно так:

git checkout master && git checkout HEAD~15
git checkout master && git checkout HEAD~14
git checkout master && git checkout HEAD~13
...
Ответить

 

Дмитрий

Приветствую. Заметил одну неприятную вещь: связи по with не возвращаются. Т.е. при запросе

Post::find()->with(['user']); - получаем только посты:
{
    "id": 1,
    "user_id": 1,
    "title": "title 1",
    "content": "post 1 ",
    "_links": {
        "self": {
            "href": "http://api.rest-api/v1/posts/1"
        }
    }
}, 

а вот с ?expand=author, получаем автора.
как можно решить эту проблему? Заранее благодарю.

Ответить

 

Дмитрий

причем, в запросе связь участвует, (при "левой" связи - ошибка), а в самом ответе связи нет

Ответить

 

Дмитрий Елисеев
public function fields()
{
    return array_merge(parent::fields(), [
        'author' => 'user',
    ]);
}
Ответить

 

Алко

Дмитрий, а подскажите, каким способом грузить через api картинку?

Ответить

 

Дмитрий Елисеев

У VK сделано так.

Ответить

 

Андрей

Большое спасибо за вебинар. Но после его просмотра возникло 2 вопроса:

1. В теоретической части упоминалась схема аутентификации с двумя токенами. Но в реализации используется схема с единственным токеном. Не очень понятно, как именно реализуется схема с двумя токенами. Правильно я понимаю, что для доступа используется только "короткий" токен? А при его истечении необходимо отправить на сервер отдельный запрос, в котором передаётся "длительный" токен и возвращается новый "короткий"? А после истечения "длительного" требуется новый ввод логина / пароля? И что мы получаем после проверки пароля - только "длительный" токен, или оба сразу?

2. Получившийся API очень сильно завязан на ActiveRecord Yii2. Но в последних статьях Вы описываете "слоистую" архитектуру, в которой контроллер вообще ничего не знает об AR. Возможно ли совместить сервисный слой и встроенные в Yii2 средства REST?

Ответить

 

Дмитрий Елисеев

1. Да, правильно. При логине приходит оба токена: текущий и восстановительный.

2. Возможно, если запрашивать данные из репозитория и вручную формировать массив для JSON.

Ответить

 

Дмитрий Елисеев

Можно воспользоваться готовым модулем yii2-oauth2-server для OAuth2 аутентификации.

Ответить

 

Андрей

Большое спасибо.

Ответить

 

Максат Жанат

Здравствуйте, как запустить правильно ваш проект на локалке , вместе со всеми мирациями?
Я новичок :) Или нужно начинать с composera ?

Ответить

 

Дмитрий Елисеев

Клонируете репозиторий:

git clone git@github.com:ElisDN/yii2-demo-rest-api project
cd project

Подтягиваете зависимости:

composer global require "fxp/composer-asset-plugin:^1.3.1"
composer install

Инициализируете локальную Development конфигурацию:

php init

Прописываете настройки БД в common/config/main-local.php и test-local.php

Применяете миграции:

php yii migrate
php yii_test migrate

В отдельных окнах терминалов запускаете серверы:

php -S 127.0.0.1:8090 -t frontend/web
php -S 127.0.0.1:8080 -t api/web

Получаете сайт по адресу 127.0.0.1:8090 и API по 127.0.0.1:8080.

Запускаете тесты:

vendor/bin/codecept run -- -c api
Ответить

 

Максат Жанат

Cпасибо огромное)

Ответить

 

Сергей

Было бы хорошо рассмотреть такие вещи:
если приходит фотка(или несколько файлов) в POST /post
Как переопределить метод create что бы сохранить эти файлы и вернуть готовый JSON со ссылками на сохраненные файлы(фотки) при статусе 201.

Я делал через afterAction, но неуверен или это правильно.

Ответить

 

Паша

Здравствуйте, у меня возникла проблема с фикстурами при тестировании API. Дело в том что из самой функции теста, при обращении к БД, видно что фикстуры юзеров подгрузились, но когда я возвращаю ответ из тестового хоста API в виде массива юзеров, видно что фикстуры не загружались, а в БД старые данные. Уже 2 дня мучаюсь и не понимаю почему так происходит... или так и должно быть, а я просто что то не так делаю? Использую постгресс для тестов.

Ответить

 

Дмитрий Елисеев

Проверьте, что установлено cleanup: false в codeception.yml

Ответить

 

Паша

Помогло, спасибо большое))

Ответить

 

Сидредин Агаширинов

Здравствуйте, Дмитрий! У меня такой вопрос: почему в исходниках к данному вебинару нет файлов index.php ни в папке frontend, ни в папке api? Хотя на видео эти файлы видны. Насчет наличия других файлов я пока не смотрел.

Ответить

 

Дмитрий Елисеев

Потому что эти файлы разворачиваются при выполнении команды php init.

Ответить

 

Сидредин Агаширинов

Понятно. Спасибо большое!

Ответить

 

Юрий

Дмитрий, подскажите, а можно ли реализовать REST API в модуле, не создавая отдельный экземпляр приложения?

У меня структура похожая немного на https://github.com/ElisDN/seokeys
Хотелось сделать модуль с REST API по урлу site.ru/api/controller...

Ответить

 

Дмитрий Елисеев

Да, можно создать модуль api и проследить, чтобы он всегда выдавал JSON/XML вместо HTML.

Ответить

 

Темир

Ввод-вывод средств на сайте.

Добрый день, подскажите есть ли что то готовое или в какую сторону смотреть, как организовать ввод-вывод средств на сайте, по типу сайтов фриланса, т.е. пользователь чтобы мог как пополнять средства на сайте так и выводить.

Ответить

 

Дмитрий Елисеев

Ввод - через любую систему платежей вроде Robokassa, Яндекс.Касса и прочее. Вывод обычно производят вручную по заявке.

Ответить

 

Валерий

Спасибо за вебинар. Как установить демо-проект с гита? Понимаю, что вопрос чайника.

Ответить

 

Валерий

Разобрался, спасибо. У меня другой вопрос. Вы сказали, что в SPA приложениях (Ангуляр), можно использовать механизм сессий при авторизации. Я не нашел этого в документации. В стеке MEAN авторизация работает практически "из коробки". Но у меня задача: предоставить доступ SPA приложению, написанному на Angular 4 к существующей БД MYSQ. У этой БД есть админка, написанная на Yii2.
Создание API является единственно правильным решением, или есть более простые альтернативы?

Ответить

 

Дмитрий Елисеев

Из HTML-кода с MySQL лучше работать только через API на сервере. Не открывать же MySQL сервер наружу напрямую.

Ответить

 

Денис Бондарь

Дим, вопрос по настройке codeception для api тестов.
У меня почему-то не получается использовать фикстуры в транзакциях.
Вот конфиг:

class_name: ApiTester
modules:
    enabled:
        - REST:
            depends: PhpBrowser
            url: http://my.tested.app/index-test.php
            part: [json]
        - Yii2:
            part: [orm, fixtures]
            entryScript: index-test.php
            cleanup: false # вот без этой строки не работает


Используется СУБД PostgreSQL. Может в ней проблема?
Проблему решил отключением транзакций cleanup: false
Пробовал отлаживать: фикстуры применяются в тесте, я их могу извлечь из БД через grabFixture() без проблем. Но само приложение, к которому я обращаюсь по АПИ, видит пустые таблицы. Может быть, конечно, иначе, кроме как отключать транзакции, и не получится.
В общем, хотелось бы понять, почему так происходит.

Ответить

 

Дмитрий Елисеев

Ппосто cleanup говорит, оборачивать ли накат миграций одной общей транзакцией. Здесь можно это отключить.

Ответить

 

Дмитрий

Клонировал, как указано выше ваш проект, ничего не менял, открываю:

http://project/api/web/б возвращает "api"
http://project/api/web/auth - Not Found

Что я делаю не так?

Ответить

 

Дмитрий Елисеев

Не настроили сервер на работу поддомена из папки api/web, чтобы было api.project/auth

Ответить

 

Yohan S

Как общаться yii2 с блоком Word в Microsoft Word с помощью xmlrpc?

Ответить

 

Стас

Здравствуйте! Я столкнулся с что не удаляются данные postgres после тестирования codeception. В сети не могу найти ничего эффективного. Необходимо, что бы база автоматически очищалась после завершения тестов.

Ответить

 

Дмитрий Елисеев

А зачем её очищать после? Фикстуры её очистят до.

Ответить

 

Дмитрий

А где хранить токены на клиенте и какие?

Ответить

 

Дмитрий Елисеев

В localStorage браузера или в мобильном приложении.

Ответить

 

Марсель Зарипов

Подскажите пожалуйста какие действия надо совершить чтобы развернуть данный проект не на локальном а на боевом сервере?

Ответить

 

Дмитрий Елисеев

Сделать поддомены и настроить их на работу с папками backend/web и api/web.

Ответить

 

Nodirbek

здравствуйте! можете не много поделится инфо по swagger на yii2

Ответить

 

Дмитрий Елисеев

Подключаем библиотеку swagger-php и генерируем документацию по аннотациям в экшенах.

Ответить

 

Nodirbek

Спасибо )

Ответить

 

Марсель Зарипов

Форум умер

Ответить

 

Андрей

Дмитрий здравствуйте. Пытаюсь изучить данную тему. Получаю ошибку.

{
  "name": "Internal Server Error",
  "message": "An internal server error occurred.",
  "code": 0,
  "status": 500
}

В видео эти действия вы производите на 4:10:35 минуте. Уже все перепроверил, вроде все по вашим стопам выполнено. Но ошибка так и не уходит. Не могу приложить ума куда копать.Буду признателен в подсказке хоть в какую сторону смотреть.

Ответить

 

Дмитрий Елисеев

Включите YII_DEBUG или посмотрите в runtime/logs.

Ответить

 

Вячеслав

как такой запрос

return static::find()
    ->joinWith('tokens t')
    ->andWhere(['t.token' => $token])
    ->andWhere(['>', 't.expired_at', time()])
    ->one();

переделать для mongodb

Ответить

 

Дмитрий Елисеев

С yii2-mongodb не работал, так что не подскажу.

Ответить

 

Иван

Здравствуйте!

Спасибо за уроки, которые Вы делаете. Очень полезные и хорошо разжевано.

У меня один вопрос не могу в папке "api" посредственно примеры. Подскажите где они?

За ранее, благодарен.

Ответить

 

Дмитрий Елисеев

Какие именно примеры интересуют?

Ответить

 

Иван

Когда скачал исходники с репозитория. Хотел увидеть код в начале видео. Не подскажете где его взять? Хочу потренироваться, а то мало опыта в работе с классами.

Ответить

 

Дмитрий Елисеев

В репозитории только такой код с историей изменений в коммитах.

Ответить

 

Андрей Заусайлов

Добрый день!
Смотрю API yii2 из коробки с применением QueryParamAuth. Не могу понять почему создание объекта не срабатывает как надо. объект создается но он пытается перекинуть на просмотр нового созданного объекта без access-token и возникает ошибка 401. не совсем логично получается ведь access-token уже передан в POST для создания объекта
это можно посмотреть в yiisoft/yii2/rest/CreateAction::run
строка $response->getHeaders()->set('Location', Url::toRoute([$this->viewAction, 'id' => $id], true));

Ответить

 

Дмитрий Елисеев

Если с QueryParamAuth, то этот параметр нужно указывать и в адресе просмотра при редиректе.

Ответить

 

Иван – gredasov.ru

Здравствуйте, Дмитрий
Пытаюсь запустить тесты codeception но вывод получается не красивым со скобками, цифрами...

[1mApi\tests.api Tests (4) [22m-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------
[31;1mE[39;22m [35;1mAuthCest:[39;22m Bad method [32m(0.35s)[39m
[31;1mE[39;22m [35;1mAuthCest:[39;22m Wrong credentials [32m(0.09s)[39m
[31;1mE[39;22m [35;1mAuthCest:[39;22m Success [32m(0.09s)[39m
[31;1mE[39;22m [35;1mHomeCest:[39;22m Main page [32m(0.00s)[39m

подскажите что не так и куда смотреть?

Ответить

 

Иван – gredasov.ru

Нашел такую штуку в настройках codeception.yml:

settings:
    colors: false


Тогда вывод получается нормальным:

Api\tests.api Tests (3) ----------

+ AuthCest: Bad method (0.23s)
+ AuthCest: Wrong credentials (0.80s)
+ AuthCest: Success (0.79s)
----------------------------------------
Ответить

 

Евгений

Доброго времени суток, Дмитрий. Подскажите пожалуйста:

Мне необходимо настроить рест через модуль, а не как у Вас в вебинаре, так как скрипт.js должен обращаться к модулю и должно получится что-то вроде my_site/message/user

Мой модуль:

class Module extends \yii\base\Module{
  public $controllerNamespace = 'frontend\modules\messages\controllers';
  public $layout = 'main';
  public function init()
  {
    parent::init();
    \Yii::configure($this, [
      'components' => [
        'urlManager' => [
          'class'                 => 'yii\web\UrlManager',
          'enablePrettyUrl'       => true,
          'enableStrictParsing'   => true,
          'showScriptName'        => false,
          'rules'                 => [
            [
              'class'      => 'yii\rest\UrlRule',
              'controller' => 'user',
              'pluralize'  => false,
            ],  ],   ],   ], ]); }}

Контролер:

class UserController extends ActiveController
{
  public $modelClass = User::class;
}

Когда обращаюсь по адресу: my_site/message/user выдает xml, но когда по такому my_site/message/user/1- ничего не меняется, нет отображения именно записи с id=1

Ответить

Оставить комментарий

Войти | Завести аккаунт | Войти через


(никто не увидит)





Можно использовать теги <p> <ul> <li> <b> <i> <a> <pre>