Установка 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
Комментарии (69)
Александр Кулик
2020-01-02 18:29

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

Ответить
Дмитрий Елисеев
2020-01-04 14:34

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

Ответить
Дмитрий Елисеев
2020-01-17 15:32

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

Ответить
Александр Кулик
2020-01-17 17:43

Спасибо

Ответить
Александр Кулик
2020-01-04 15:15

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

Ответить
Дмитрий Елисеев
2020-01-09 07:10

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

Ответить
Sergei
2020-01-09 16:37

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

Ответить
Дмитрий Елисеев
2020-01-10 08:55

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

Ответить
Роман
2020-01-10 11:08

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

Ответить
Дмитрий Елисеев
2020-01-10 16:03

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

Ответить
Oaks
2020-01-10 21:57

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

Ответить
Дмитрий Елисеев
2020-01-12 06:03

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

Ответить
Андрей
2020-08-14 16:05

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

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

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

Ответить
Андрей
2020-08-16 13:26

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

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

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

Ответить
Дмитрий Елисеев
2020-08-17 10:51

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

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

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

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

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

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

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

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

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

Ответить
Сарибжанов Ильдар
2020-01-19 04:10

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

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

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

Ответить
Дмитрий Елисеев
2020-01-19 06:07

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

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

Ответить
Сарибжанов Ильдар
2020-01-19 11:25

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

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

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

Ответить
Дмитрий Елисеев
2020-01-19 11:50

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

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

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

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

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

Ответить
Ruslan
2020-01-19 18:54

я не понял момент с 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. Проясните пожалуйста.

Ответить
Дмитрий Елисеев
2020-01-19 22:05

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

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

Ответить
Ruslan
2020-01-19 22:09

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

Ответить
Ruslan
2020-01-19 23:06

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

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

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

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

Ответить
Ruslan
2020-01-19 23:10

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

Ответить
Дмитрий Елисеев
2020-01-20 07:21

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

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

Ответить
А
2021-01-08 23:14

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

Ответить
Ruslan
2020-01-19 23:42

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

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

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

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

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

Ответить
Дмитрий Елисеев
2020-01-20 07:27

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

Ответить
Shaitan
2020-02-27 19:05

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

Ответить
Дмитрий Елисеев
2020-02-28 22:17

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

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

sudo chown $USER:$USER api -R
Ответить
BATPYIIIKOB
2020-05-05 12:44

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

Ответить
Юлия Елисеева
2020-05-12 07:53

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

Ответить
Андрей
2020-06-02 23:40

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

Ответить
Дмитрий Елисеев
2020-06-07 06:16

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

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

Ответить
elmut
2020-11-10 12:31

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

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

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

Ответить
Дмитрий Елисеев
2020-11-24 11:54

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

Ответить
А
2021-01-09 21:35

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

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

Ответить
rodigy
2021-12-08 01:01

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

Ответить
Ярослав
2021-01-13 21:32

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


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

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

Ответить
Никита
2021-01-25 18:04

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

Ответить
Ruslan
2021-02-13 11:07

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

Ответить
Дядя Женя
2021-04-07 06:20

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

Ответить
Дмитрий Елисеев
2021-04-09 08:21

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

Ответить
Дядя Женя
2021-04-09 18:38

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

Ответить
Богдан
2021-05-11 13:20

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

Ответить
Дмитрий Елисеев
2021-05-11 14:58

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

Ответить
Богдан
2021-05-12 07:39

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

Ответить
Сергей
2021-08-04 18:19

Добрый вечер, Дмитрий. Остановился на 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 последней версии из вашего хранилища, в этом случае ошибка другая, не может найти ни один пакет.

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

Ответить
Сергей
2021-08-10 19:29

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

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

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

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

Ответить
worfect
2021-08-22 22:07

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

Ответить
Игорь
2021-09-14 11:43

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

Ответить
Дмитрий Елисеев
2021-09-28 15:22

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

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

Ответить
rodigy
2021-12-09 00:04

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

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

Ответить
Дмитрий Елисеев
2021-12-18 12:39

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

Ответить
Санжар
2022-01-17 19:28

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

Ответить
Дмитрий Елисеев
2022-01-18 08:31

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

Ответить
Александр
2022-02-11 10:05

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

Ответить
Дмитрий Елисеев
2022-03-02 15:52

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

Ответить
Egor
2022-06-01 06:12

делаю 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

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

Ответить
Дмитрий Елисеев
2022-06-29 06:50

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

Ответить
Egor
2022-06-29 06:53

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

Ответить
Павел
2022-10-22 10:12

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

Ответить
Дмитрий Елисеев
2022-10-23 04:01

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

Ответить
Константин
2024-01-05 11:49

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

Ответить
Дмитрий Елисеев
2024-07-29 16:00

Конфигурации собираются по группам вроде 'db'=>[...] и 'log'=>[...]. Если кто-то добавит свою конфигурацию, то обычно создаст свою группу вроде 'cache'=>[...]. Так что чужие значения он этим врядли перезапишет.

А если он в своём файле cache.php для кэша переопределит фабрику логгера LoggerInterface::class=>fn(...), то это само по себе будет выглядеть странно.

Так что риск нечаянной перезаписи весьма мал.

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

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

Yandex
MailRu
GitHub
Google