Построение и тестирование 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.phpCodeception ставил глобально и переменную PATH поправил чтобы команда всегда была доступна.
Дмитрий ЕлисеевЗамените FunctionalTester на ApiTester
Дмитрийне в этом дело, я и так уже пробовал... в общем нашел уже причину блин все делал по учебнику версия codeception была 2.1.11 обновил до 2.2.9 - все норм сгенерил с тем же конфигом
ОлегДмитрий, чуть-чуть оффтопа)) Подскажите, пожалуйста, как добавить зависимость в composer.json на примере https://github.com/par0noid/ts3admin.class
Дмитрий Елисеев
ОлегБлагодарю, а я его пробовал 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_nikStevan, а может Вам подучить русский язык? )))
StevanТо за мене вероватно не би био неки проблем, али би онима који нису Словени могло да одузме мало више времена. Вероватно би научли таман за Руске туторијале за Yii3 :)
slo_nikStevan, вот, думаю Вам понравится)))
https://elisdn.ru/blog/102/yii2-application-development-cookbook
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 комит хранит ссылку только на предыдущий. Если из коммита начинаются несколько веток, то верхних будет два. Поэтому можно так:
ДмитрийПриветствую. Заметил одну неприятную вещь: связи по 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 ?
Дмитрий ЕлисеевКлонируете репозиторий:
Подтягиваете зависимости:
Инициализируете локальную Development конфигурацию:
Прописываете настройки БД в common/config/main-local.php и test-local.php
Применяете миграции:
В отдельных окнах терминалов запускаете серверы:
Получаете сайт по адресу 127.0.0.1:8090 и API по 127.0.0.1:8080.
Запускаете тесты:
Максат Жанат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 говорит, оборачивать ли накат миграций одной общей транзакцией. Здесь можно это отключить.
ДмитрийКлонировал, как указано выше ваш проект, ничего не менял, открываю:
Что я делаю не так?
Дмитрий ЕлисеевНе настроили сервер на работу поддомена из папки api/web, чтобы было api.project/auth
Yohan SКак общаться yii2 с блоком Word в Microsoft Word с помощью xmlrpc?
Дмитрий ЕлисеевЧерез http://php.net/manual/ru/function.xmlrpc-encode-request.php
СтасЗдравствуйте! Я столкнулся с что не удаляются данные 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 но вывод получается не красивым со скобками, цифрами...
подскажите что не так и куда смотреть?
Иван – gredasov.ruНашел такую штуку в настройках codeception.yml:
settings: colors: falseТогда вывод получается нормальным:
ЕвгенийДоброго времени суток, Дмитрий. Подскажите пожалуйста:
Мне необходимо настроить рест через модуль, а не как у Вас в вебинаре, так как скрипт.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