Установка Slim и Symfony Console

Подготовка структуры директорий API. Добавление образа PHP-CLI. Установка Slim Framework. Ускорение установки в Composer v1.

  • 00:00:50 - Работа с PHP в консоли
  • 00:01:59 - Философия Docker по контейнеру на процесс
  • 00:03:04 - Образ для PHP CLI
  • 00:05:16 - Установка Composer
  • 00:07:55 - Проверка работы Composer
  • 00:09:34 - Ускорение Composer v1
  • 00:11:52 - Инициализация composer.json
  • 00:13:24 - Пакет Security Advisories
  • 00:14:07 - Установка и обзор Slim
  • 00:20:15 - Команда установки зависимостей
  • 00:21:38 - Исправление статуса ошибок в PHP
  • 00:23:39 - Обработчик ошибок фреймворка
  • 00:25:07 - Конфигурация через переменные окружения
  • 00:28:24 - Контейнер внедрения зависимостей
  • 00:30:46 - Папка src и автозагрузка
  • 00:32:34 - Вынос экшенов в классы
  • 00:33:40 - Работа с JSON
  • 00:35:08 - Формирование JSON-ответа
  • 00:36:17 - Контроллеры по PSR-15
  • 00:39:26 - Инъекция ResponseFactory
  • 00:40:35 - Контейнер с autowiring
  • 00:43:19 - Класс JsonResponse
  • 00:46:22 - Вынос маршрутов и посредников
  • 00:47:20 - Вынос настройки контейнера
  • 00:49:06 - Автозагрузка конфигурации
  • 00:51:23 - Поддержка разных окружений
  • 00:53:43 - Бутстрап приложения
  • 00:55:23 - Установка Symfony Console
  • 00:58:14 - Загрузка команд из контейнера
  • 01:00:24 - Запуск команд через Composer
  • 01:01:48 - Неинтерактивный запуск команд
  • 01:02:48 - Что дальше

В 44 эпизоде перейдём на Composer 2.0, где установка плагина уже не понадобится.

Скрытый контент (код, слайды, ...) для подписчиков. Открыть →
Дмитрий Елисеев
elisdn.ru
Комментарии (68)
Александр Кулик

Небольшой оффтоп. Можете показать, как реализован видео сервис?

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

В каком смысле?

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

Пока просто стандартный показ <video><src="video.mp4"></video> с файлового хостинга.

Ответить
Александр Кулик

Спасибо

Ответить
Александр Кулик

Как правильно загружать и показывать видео с сервера

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

Это не для требования, а для эмуляции. Чтобы он не видел реально установленную в системе версию.

Ответить
Sergei

56:25 А зачем использовать рефлексию, когда мы можем также явно указать класс для контейнера? рефлексия же медленная, или экономия на спичках?

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

Экономия на спичках.

Ответить
Роман

php -- --install-dir что значат первые два тире?

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

Это значит, что параметры для php закончились и остальное надо игнорировать, так как далее пойдут параметры уже для самого скрипта.

Ответить
Oaks

Что значит объявление функции static вне класса ?

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

То, что функция или переменная после него создаётся всего один раз.

Ответить
Андрей

Здравствуйте, Дмитрий! Спасибо за огромную проделанную работу.

В коде вы неоднократно используете анонимные статические функции вне класса. В официальной документации по PHP мне удалось найти лишь, что "Начиная с PHP 5.4, анонимные функции могут быть объявлены статически. Это предотвратит их автоматическое связывание с текущим классом. Объекты также не будут с ними связаны во время выполнения."

Однако не удалось найти, что "функция или переменная после него создаётся всего один раз". Подскажите, пожалуйста, где об этом можно почитать?

Ответить
Андрей

Внимательно перечитал этот раздел официальной документации вместе с пользовательскими комментариями к нему, однако никакой информации об анонимных статических функциях там не нашел.

В различных статьях на иных ресурсах использование статических анонимных рассматривается лишь в контексте связывания с $this из текущего класса, упоминается о некотором увеличении производительности при их использовании. Но нигде нет информации, что "функция или переменная после него создаётся всего один раз".

Пожалуйста, объясните необходимость использования, например, в routes.php именно статической анонимной функции и что означает в этом контексте "функция или переменная после него создаётся всего один раз".

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

никакой информации об анонимных статических функциях там не нашел.

Это общая информация об использовании конструкций global и static в таком виде с чем угодно. Хоть с переменными, хоть с функциями.

Но нигде нет информации, что "функция или переменная после него создаётся всего один раз".

Про это по ссылке выше есть два предложения:

Статическая переменная существует только в локальной области видимости функции, но не теряет своего значения, когда выполнение программы выходит из этой области видимости.

Теперь $a будет проинициализирована только при первом вызове функции, а каждый вызов функции будет выводить значение $a и инкрементировать его.

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

Объясните необходимость использования, например, в routes.php именно статической анонимной функции... Упоминается о некотором увеличении производительности при их использовании.

Никакой необходимости нет. Это просто плагин EA Extended в PhpStorm рекомендует анонимные функции обозначать со словом static для микрооптимизации производительности. Особенно если метод с такой функцией внутри вызывается много раз в цикле, чтобы там на каждой итерации снова и снова одну и ту же анонимку не создавать.

Ответить
Сарибжанов Ильдар

Чутка погундеть пришёл: «Чтобы не морочиться с конфигурационными файлами, типа conf или .env удобнее использовать окружение докера»

спустя 2 минуты: «Чтобы эти параметры не прописывать по всему коду удобнее создать конфигурационный файл» 0_о

Я слегка запутался, так конфигурационные файлы - это плохо или хорошо?

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

Имеется в виду не морочиться с копированием и ручным заполнением параметров в локальных файлах вроде config-local.php или .env-local из .gitignore, как это делается в Yii и Laravel.

Вместо этого делаем фиксированный config.php с прямым чтением getenv(...) из окружения.

Ответить
Сарибжанов Ильдар

Универсальность порождает избыточность. Фреймворки дают готовые файлы, чтобы можно было быстро стартануть. Конечно, в нашем случае нет смысла делать какие-то conf-local, хотя в большой команде, если всё окружение будет разворачиваться локально, то, возможно и будет смысл иметь какие-то индивидуальные настройки из .local файла.

Например, если в проде у нас кэш в редиса, а очереди в реббита, в деве/стейже очереди синхронные, а локально было бы проще кэш отключить совсем.

В общем, какие-то конфиг файлы могут быть «тонко настраиваемыми» и тогда придётся их заполнять.

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

Например, если в проде у нас очереди в реббите, в деве/стейже очереди синхронные.

Как раз такое разделение весьма опасно тем, что на деве и стейже всё синхронно работает, а на проде что-то будет асинхронно падать. Или если в проде есть репликация БД и конфигурация с двумя базами, а на деве её нет и конфигурация с одной. Или если в проде почта отправляется по SMTP, а на локалке эмулируется сохранением в файлы.

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

Единственное, что в config/dev/cache.php и для тестов будет отключен кэш через enable=false.

В итоге необходимость в личном файле config-local для каждого программиста полностью отпадает.

Ответить
Ruslan

я не понял момент с php-di (с 39 минуты) . Мы сначала добавили use DI\Container; в индекс, и он на в композер подставил зависимость, или до это в композел руками вписали cтроку "php-di/php-di": "^6.0", ? Или просто из-за монтажа так получилось? а до этого было docker-compose run --rm api-php-cli composer require php-di/php-di.

Если руками редактировать composer.json , то потребуется composer update. Проясните пожалуйста.

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

В новом проекте не правьте вручную, а всегда делайте composer require. Тогда оно само с нужными версиями пропишется.

Просто у меня уже готовый код из коммитов, где всё уже заранее прописалось.

Ответить
Ruslan

Спасибо. Я понял. Думал может какая фишка есть, которая это вставляет, а я не знаю.

Ответить
Ruslan

43min. У вас подсвечивается папка src и при создании класса подставляется namespace и declare(strict_types=1)

Как этого добиться?

По этому мануалу мне удалось добиться подстановки namespace

Папка не подсвечивается. :)

Ответить
Ruslan

Нашел. Тупо нажать правой кнопкой и выбрать Mark as Source. Но с declare(strict_types=1) Как быть?

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

Чтобы вручную не помечать папки через Mark as Source и не размечать vendor, нужно зайти в PHP > Composer и включить там опцию Mark packages as libraries. Это заодно правильно настроит игнор и импорт из папки vendor.

А для declare перейдите в Editor > File and Code Templates и там впишите declare в PHP File Header.

Ответить
А

Спасибо, очень помог совет.

Ответить
Ruslan

Еще один тупой вопрос:

Когда мы делаем $app->get('/', Http\Action\HomeAction::class)

HomeAction::class - эта конструкция возвращает полное имя класса HomeAction, т.е. строку.

а нам нужно вызвать объект как функцию т.е. $action($request, $response, $args)

Почему без скобок происходит вызов?

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

Этим мы просто маршрутизатору передаём строкой имя класса. А сам фреймворк уже потом создаёт объект и производит вызов с $request и $response.

Ответить
Shaitan

Вот у меня тут вопросик есть) Как правильно поступать с правами? Докер не под юзеровским айдишником делает папку вендор. Из за чего проблемы с правами. Знаю что в докерфайле можно присвоить uid и gid, корректен ли такой способ? Или данную манипуляцию в мэйкфайле можно? Какая практика вообще общепринятая?

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

С vendor всегда работаем изнутри контейнера, запуская composer require и composer update. Поэтому права здесь нам не мешают.

Но если что-то генерируем в коде и надо поменять права снаружи, то меняем владельца на себя:

sudo chown $USER:$USER api -R
Ответить
BATPYIIIKOB

Хочется поблагодарить Дмитрия и его супругу за проделанную работу и за самый годный контент по "правильному" программированию в рунет сети. Слежу за деятельностью Дмитрия ещё с создания его сайта блога. Спасибо большое.

Ответить
Юлия Елисеева

Спасибо за тёплые слова! Очень приятно, если видеоматериалы вам помогают. Сейчас мы экспериментируем над записью эпизодов, качеством и этапами обработки. Обо всём пишу в своём блоге, возможно это покажется интересным.

Ответить
Андрей

Вы контроллеры сделали фреймворконезависимыми. А что насчет консольных команд? Они напрямую зависят от symfony/console. Почему в случае с консольными командами мы делаем это допущение?

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

Для контроллеров есть десятки HTTP-фреймворков и для независимости есть PSR-7 и PSR-15.

А для консольных команд популярен только symfony/console. От него уходить некуда и незачем.

Ответить
elmut

есть файл composer.json и к нему подключил свой собственный Compsoer-пакет(расширение находится на локальном компьютере).

"repositories": [
    {
        "type": "path",
        "url": "./Packages/Session",
        "options": {
            "symlink": true
        }
    }
],
"require": {
    "packages/session": "*"
}

Как можно сделать так чтобы при изменении Composer-пакет локальный, главный Compsoer ненужно было обновлять composer update

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

Проставить с папки символическую ссылку если она не ставится автоматически.

Ответить
А

Тут в видео array_merge_recursive, а в коммите array_replace_recursive. Помню, весной от и до прошерстил почему конфиги криво мерджились. Потом следующие уроки посмотрел и уже после этого разобрался как recursive функции php работают.

Если кто-то будет мучится с array_replace функциями из этих видео - просто не забивайте сильного голову, потом все равно либа от Laminas их заменит.

Ответить
rodigy

array_merge_recursice все отрабатывает не так как ожидалось, тоже на это обратил внимание

Ответить
Ярослав

Напишу, может кому пригодится. В composer 2.0 hirak/prestissimo не работает. Видать из-за ненадобности. Так что я убрал этот плагин и вот мой рабочий вариант:


RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/bin --filename=composer --quiet \ 
&& rm -rf /root/.composer/cache
Ответить
Дмитрий Елисеев

Строка rm -rf /root/.composer/cache теперь тоже не нужна.

Ответить
Никита

Спасибо за урок, тут был вопрос. Я с ним разобрался благодаря комментариям

Ответить
Ruslan

Игнорируйте тест установки скелетона, идите дальше, там где всё устанавливается по мере надобности. И будет счастье :)

Ответить
Дядя Женя

Вопрос по оплате и прочим удобствам, связанным с ней. Решил оформить подписку. Вбил данные карты и ничего дальше не происходит. Деньги не списываются, никаких кодов не приходит, висит пустой бланк заказа. Даже вернее сказать совсем пустой, белый, без полей. Была бы возможность прикрепить скрин - показал бы. И жаль, что в кабинете нет возможности задать вопрос по теме оплаты. Карта мастеркард. Вроде должна работать на перечисление в другую страну, по крайней мере проверена в некоторых магазинах Европы )))

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

В почте выяснили, что в другом браузере всё получилось. Может какое-то расширение браузера мешало.

Ответить
Дядя Женя

Да, что-то я забыл тут написать о решении проблемы. В любом случае - спасибо

Ответить
Богдан

Почему не использовать отдельно образ с контейнером композера?
https://hub.docker.com/_/composer

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

Для первой установки можно сделать composer create-project через него. Но дальше уже удобнее чистый php-cli, где мы сами указываем версию PHP и доустанавливаем нужные расширения.

Ответить
Богдан

Понял, спасибо!)

Ответить
Сергей

Добрый вечер, Дмитрий. Остановился на 10 минуте данного урока. Прохожу курс на Ubuntu через VMware После добавления apk update образы перестали собираться с ошибкой

Step 2/7 : RUN apk update && apk add unzip
 ---> Running in 7d69e8a93cd8
fetch dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
ERROR: dl-cdn.alpinelinux.org/alpine/v3.14/main: temporary error (try again later)
WARNING: Ignoring dl-cdn.alpinelinux.org/alpine/v3.14/main: No such file or directory
fetch dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
ERROR: dl-cdn.alpinelinux.org/alpine/v3.14/community: temporary error (try again later)
WARNING: Ignoring dl-cdn.alpinelinux.org/alpine/v3.14/community: No such file or directory
2 errors; 32 distinct packages available
ERROR: Service 'api-php-cli' failed to build: The command '/bin/sh -c apk update && apk add unzip' returned a non-zero code: 2
make: *** [Makefile:19: docker-build] Error 1

Гуглил, пишут, что проблема связана скорее всего с DNS, тк сижу под виртуалкой, пробовал несколько рецептов, в тч указывал DNS в daemon.js, раскоментировал строчку DOCKER_OPTS. Ничего не помогает. Также пробовал использовать dockerfile последней версии из вашего хранилища, в этом случае ошибка другая, не может найти ни один пакет.

Помогите пожалуйста разобраться

Ответить
Сергей

Дмитрий, вы ещё на связи? А то странно, деньги за курс списываются, а фидбека нет :\

В общем, разобрался сам. Проблема была действительно связана с DNS. Необходимо создать файл /etc/docker/daemon.json со следующим содержимым:

{
    "dns": ["192.168.0.1", "8.8.8.8"]
}

после чего, как пишут, достаточно перезапустить докер демон, но мне помогла только перезагрузка ОС

Ответить
worfect

Вот тут прям хорошо реализовал "от простого к сложному". Что-то уровня 10 файликов в курсе по ООП, или может быть даже выше.

Ответить
Игорь

я так понимаю что скрестить rpcjson и slim плохая идея?

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

Если в index.php вписать запуск RPC-сервера, то HTTP-фреймворк с контроллерами не пригодится.

Но при желании можно сделать один контроллер и запускать сервер там, передавая ему сообщение из $request->getBody() и возвращая его ответ в виде $response. Это может быть полезно если помимо RPC-сервера потребуются другие контроллеры.

Ответить
rodigy

На текущий момент slim версии 4.9.

В примерах документации слим для роутов с плейсхолдерами типа $app->get('/path/{id}', ....) в классах с __invoke они попадают третьим параметром $args. Но в psr RequestHandlerInterface нет такого, как достать?

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

В PSR они попадают в атрибуты $request->getAttribute('id')

Ответить
Санжар

Херак реально помог, годный плагин :D

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

С новым Composer v2 плагин уже не нужен.

Ответить
Александр

Дмитрий, не подскажите насчет написания документации
Например для описания API можно использовать Swager
А для проектной документации, что можно было бы использовать?
Например чтоб описать флоу какого то процесса, добавить диаграмы - что то в этом роде

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

При хранении документации в коде диаграммы удобно сочинять текстом в файлах PlantUML. Для просмотра можно поставить его плагин в PhpStorm.

Ответить
Egor

делаю make init и получаю ошибки, хотя с прошлого видео сервер настроен, сайт загружен, по домену открывается, SSL сертификат установлен...

 => ERROR [auction_gateway 2/4] COPY ./common/nginx/snippets /etc/nginx/snippets
 => ERROR [auction_gateway 3/4] COPY ./development/nginx/conf.d /etc/nginx/conf.d

Как можно поправить?

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

А эти папки точно есть?

Ответить
Egor

Возможно накосячил где-то, у меня бывает. Я поздно подключился, да ещё на вин10. Постоянно то с пакетами беда, то с командами. Решу. Спасибо

Ответить
Павел

Здравствуйте, Дмитрий! Правильно ли я понял, что версия php в контейнере composer всегда должна совпадать с версией php в контейнере php-fpm, иначе могут быть проблемы?

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

Да, версии PHP везде должны быть одинаковые. Иначе новый код на более старом PHP может падать с ошибками.

Ответить
Константин

Спасибо за курс, Дмитрий! Возник вопрос - мы подключаем все конфиги из папок, и потом просто мерджим получившиеся массивы с настройками, но тогда возникает проблема, вдруг кто-то добавит новый файл с каким-то конфигом, и там будут такие же ключи как и в предыдущих файлах, и получается мы просто перезатрём предыдущие значения? Стоит ли проверять дублирующиеся ключи и выдавать понятную ошибку в таком случае.

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Google
GitHub
Yandex
MailRu