Как правильно загружать и показывать видео с сервера
Подготовка структуры директорий API. Добавление образа PHP-CLI. Установка Slim Framework. Ускорение установки в Composer v1.
В 44 эпизоде перейдём на Composer 2.0, где установка плагина уже не понадобится.
Чтобы не пропускать новые эпизоды подпишитесь на наш канал @deworkerpro в Telegram

Как правильно загружать и показывать видео с сервера
У композера вроде есть специально platform параметр для требования php https://getcomposer.org/doc/06-config.md#platform
Это не для требования, а для эмуляции. Чтобы он не видел реально установленную в системе версию.
56:25 А зачем использовать рефлексию, когда мы можем также явно указать класс для контейнера? рефлексия же медленная, или экономия на спичках?
Экономия на спичках.
php -- --install-dir что значат первые два тире?
Это значит, что параметры для php закончились и остальное надо игнорировать, так как далее пойдут параметры уже для самого скрипта.
Что значит объявление функции 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 для каждого программиста полностью отпадает.
я не понял момент с 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. Тогда оно само с нужными версиями пропишется.
Просто у меня уже готовый код из коммитов, где всё уже заранее прописалось.
Спасибо. Я понял. Думал может какая фишка есть, которая это вставляет, а я не знаю.
43min. У вас подсвечивается папка src и при создании класса подставляется namespace и declare(strict_types=1)
Как этого добиться?
По этому мануалу мне удалось добиться подстановки namespace
Папка не подсвечивается. :)
Нашел. Тупо нажать правой кнопкой и выбрать 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.
Спасибо, очень помог совет.
Еще один тупой вопрос:
Когда мы делаем $app->get('/', Http\Action\HomeAction::class)
HomeAction::class - эта конструкция возвращает полное имя класса HomeAction, т.е. строку.
а нам нужно вызвать объект как функцию т.е. $action($request, $response, $args)
Почему без скобок происходит вызов?
Этим мы просто маршрутизатору передаём строкой имя класса. А сам фреймворк уже потом создаёт объект и производит вызов с $request и $response.
Вот у меня тут вопросик есть) Как правильно поступать с правами? Докер не под юзеровским айдишником делает папку вендор. Из за чего проблемы с правами. Знаю что в докерфайле можно присвоить uid и gid, корректен ли такой способ? Или данную манипуляцию в мэйкфайле можно? Какая практика вообще общепринятая?
С vendor всегда работаем изнутри контейнера, запуская composer require и composer update. Поэтому права здесь нам не мешают.
Но если что-то генерируем в коде и надо поменять права снаружи, то меняем владельца на себя:
sudo chown $USER:$USER api -R
Хочется поблагодарить Дмитрия и его супругу за проделанную работу и за самый годный контент по "правильному" программированию в рунет сети. Слежу за деятельностью Дмитрия ещё с создания его сайта блога. Спасибо большое.
Спасибо за тёплые слова! Очень приятно, если видеоматериалы вам помогают. Сейчас мы экспериментируем над записью эпизодов, качеством и этапами обработки. Обо всём пишу в своём блоге, возможно это покажется интересным.
Вы контроллеры сделали фреймворконезависимыми. А что насчет консольных команд? Они напрямую зависят от symfony/console. Почему в случае с консольными командами мы делаем это допущение?
Для контроллеров есть десятки HTTP-фреймворков и для независимости есть PSR-7 и PSR-15.
А для консольных команд популярен только symfony/console. От него уходить некуда и незачем.
есть файл 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 их заменит.
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 теперь тоже не нужна.
Спасибо за урок, тут был вопрос. Я с ним разобрался благодаря комментариям
Понимаю, что прошло много времени с этого урока,но фрэймворк не устанавливается, выдает ошибку: https://monosnap.com/file/UPKsaVIBn6VR0j3kdAanhlB7hUFnu3
Игнорируйте тест установки скелетона, идите дальше, там где всё устанавливается по мере надобности. И будет счастье :)
Вопрос по оплате и прочим удобствам, связанным с ней. Решил оформить подписку. Вбил данные карты и ничего дальше не происходит. Деньги не списываются, никаких кодов не приходит, висит пустой бланк заказа. Даже вернее сказать совсем пустой, белый, без полей. Была бы возможность прикрепить скрин - показал бы. И жаль, что в кабинете нет возможности задать вопрос по теме оплаты. Карта мастеркард. Вроде должна работать на перечисление в другую страну, по крайней мере проверена в некоторых магазинах Европы )))
В почте выяснили, что в другом браузере всё получилось. Может какое-то расширение браузера мешало.
Да, что-то я забыл тут написать о решении проблемы. В любом случае - спасибо
Почему не использовать отдельно образ с контейнером композера?
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"]
}
после чего, как пишут, достаточно перезапустить докер демон, но мне помогла только перезагрузка ОС
Вот тут прям хорошо реализовал "от простого к сложному". Что-то уровня 10 файликов в курсе по ООП, или может быть даже выше.
я так понимаю что скрестить rpcjson и slim плохая идея?
Если в index.php вписать запуск RPC-сервера, то HTTP-фреймворк с контроллерами не пригодится.
Но при желании можно сделать один контроллер и запускать сервер там, передавая ему сообщение из $request->getBody() и возвращая его ответ в виде $response. Это может быть полезно если помимо RPC-сервера потребуются другие контроллеры.
На текущий момент slim версии 4.9.
В примерах документации слим для роутов с плейсхолдерами типа $app->get('/path/{id}', ....) в классах с __invoke они попадают третьим параметром $args. Но в psr RequestHandlerInterface нет такого, как достать?
В PSR они попадают в атрибуты $request->getAttribute('id')
Херак реально помог, годный плагин :D
С новым Composer v2 плагин уже не нужен.
Дмитрий, не подскажите насчет написания документации
Например для описания API можно использовать Swager
А для проектной документации, что можно было бы использовать?
Например чтоб описать флоу какого то процесса, добавить диаграмы - что то в этом роде
При хранении документации в коде диаграммы удобно сочинять текстом в файлах PlantUML. Для просмотра можно поставить его плагин в PhpStorm.
делаю 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
Как можно поправить?
А эти папки точно есть?
Возможно накосячил где-то, у меня бывает. Я поздно подключился, да ещё на вин10. Постоянно то с пакетами беда, то с командами. Решу. Спасибо
Здравствуйте, Дмитрий! Правильно ли я понял, что версия php в контейнере composer всегда должна совпадать с версией php в контейнере php-fpm, иначе могут быть проблемы?
Да, версии PHP везде должны быть одинаковые. Иначе новый код на более старом PHP может падать с ошибками.
Спасибо за курс, Дмитрий! Возник вопрос - мы подключаем все конфиги из папок, и потом просто мерджим получившиеся массивы с настройками, но тогда возникает проблема, вдруг кто-то добавит новый файл с каким-то конфигом, и там будут такие же ключи как и в предыдущих файлах, и получается мы просто перезатрём предыдущие значения? Стоит ли проверять дублирующиеся ключи и выдавать понятную ошибку в таком случае.
Конфигурации собираются по группам вроде 'db'=>[...] и 'log'=>[...]. Если кто-то добавит свою конфигурацию, то обычно создаст свою группу вроде 'cache'=>[...]. Так что чужие значения он этим врядли перезапишет.
А если он в своём файле cache.php для кэша переопределит фабрику логгера LoggerInterface::class=>fn(...), то это само по себе будет выглядеть странно.
Так что риск нечаянной перезаписи весьма мал.
Небольшой оффтоп. Можете показать, как реализован видео сервис?
В каком смысле?
Пока просто стандартный показ
<video><src="video.mp4"></video>с файлового хостинга.Спасибо