Вышел очередной выпуск новостей про Yii и новая порция релизов. Опубликовал на хабре.
-
Новости Yii 2020, выпуск 7
12 ноября 2020
-
Зачистка контекста в unit-тестах
9 ноября 2020
Unit-тесты должны быть изолированы. То есть тесты должны проходить если выполнять из по-одному или если включить в PHPUnit режим выполнения в случайном порядке через
phpunit.xml.dist
:<phpunit executionOrder="default">
Для этого, если тест работает с окружением (например, с файловой системой), окружение нужно подчищать. Причём подчищать и до и после через
setUp()
иtearDown()
:final class MyTest extends PHPUnit\Framework\TestCase { public function setUp(): void { $this->cleanup(); $path = realpath(sys_get_temp_dir()); mkdir($path, 755); } public function tearDown(): void { $this->cleanup(); } private function cleanup(): void { $path = realpath(sys_get_temp_dir()); rmdir($path) }
Зачистка делается два раза и до и после потому как если какой-то тест упадёт, зачистка в
tearDown()
не выполнится и окружение "встанет". -
Windows Terminal и пара разных версий PHP в отдельных вкладках
24 октября 2020
Недавно у меня умер SSD и заставил настраивать заново всё окружение. Опробованные Linux по тем или иным причинам не зашли (но я ещё попробую, может пропустил что). Вернулся на Windows 10.
Для тестов фреймворка мне необходимы несколько версий PHP и в этот раз удалось сделать удобно. В Windows Terminal у меня теперь несколько профилей с git bash и в каждом отдельная версия PHP.
Делается так:
- Берём сам PHP, распаковываем в отдельные директории. Например,
C:\php74
,C:\php80
. - Добавляем профили:
{ "guid": "{e084a08a-ad94-499d-9573-1d5904b4e9a0}", "name": "Git Bash with PHP 8", "suppressApplicationTitle": true, "icon" : "%PROGRAMFILES%/Git/mingw64/share/git/git-for-windows.ico", "commandline": "cmd.exe /C \"SET PATH=%PATH%;C:\\php80\\&& \"%PROGRAMFILES%\\Git\\bin\\bash.exe\" -login -i -l\"", "startingDirectory": "D:\\src\\" }, { "guid": "{08a7817f-8812-4eb0-b4b7-a4939fc9d14a}", "name": "Git Bash with PHP 7", "suppressApplicationTitle": true, "icon" : "%PROGRAMFILES%/Git/mingw64/share/git/git-for-windows.ico", "commandline": "cmd.exe /C \"SET PATH=%PATH%;C:\\php74\\&& \"%PROGRAMFILES%\\Git\\bin\\bash.exe\" -login -i -l\"", "startingDirectory": "D:\\src\\" }
- Берём сам PHP, распаковываем в отдельные директории. Например,
-
Yii 2 за балансировщиком нагрузки
14 октября 2020
Система asset-ов Yii 2 очень удобна. Можно расположить ресурсы в пакетах или ближе к исходникам и фреймворк при первом запросе на генерируемую PHP страницу скопирует их (или сделает симлинк) в нужное место.
Пока экземпляр приложения один, всё работает замечательно, а вот когда появляется балансировщик, это уже не работает потому как запрос каждый раз уходит на разный сервер. Проблем тут несколько. Yii, чтобы избавить от залипания браузерного кеша, при выборе директории, в которую копируется ресурс, использует время изменения директории:
$path = (is_file($path) ? dirname($path) : $path) . filemtime($path); return sprintf('%x', crc32($path . Yii::getVersion() . '|' . $this->linkAssets));
На каждом экземпляре приложения время будет разным, поэтому ресурсы окажутся в разных директория и если HTML будет запрошен с одного сервера, а ресурсы с других, получим 404.
Решается просто. В конфиге задаём
hashCallback
для компонентаassetManager
:'hashCallback' => static function ($path) { return hash('md4', $path); }
Но до конца это проблему не решает. Теперь пути совпадают, но при первых запросах получается что в HTML прописан путь к ресурсу с другого сервера, а там ещё запросы не обрабатывались и такого ресурса нет. Опять 404.
Бороться с этим можно несколькими способами. Первый сводится к тому, что ресурсы собираются на машине разработчика или билд-сервере и раскатываются вместе с приложением. Вариаций тут много:
- Отказаться от asset manager, использовать файлы в вебруте.
- Использовать webpack или другую систему сборки на node.
- Собирать ресурсы командой
asset
.
Второй способ — сделать ресурсы общими. Здесь опять несколько вариаций:
- Использовать NFS чтобы сделать файловую систему ресурсов общей. Но это не очень быстро и надёжно.
- Использовать CDN. Например, ресурсы закинуть на S3 и раздавать оттуда. Заодно получим снижение нагрузки на серверах приложений.
Последний вариант делается при помощи пакета
mikk150/yii2-asset-manager-flysystem
. Ставим, настраиваем:'assetManager' => [ 'class' => mikk150\assetmanager\AssetManager::class, 'basePath' => './', 'baseUrl' => 'Базовый URL статического контента', 'flySystem' => [ 'class' => creocoder\flysystem\AwsS3Filesystem::class, 'host' => 'Хост статического контента', 'key' => 'Ключик S3', 'secret' => 'Secret S3', 'region' => 'Регион S3', 'version' => 'Версия файлов', 'bucket' => 'Bucket', 'prefix' => 'Путь к ресурсам' . '/assets', ], ],
-
Рефакторинг в стиле ниндзя и другие приемчики
25 сентября 2020
1-го октября, в 19:00 веду вместе с бывшим коллегой, Валентином Назаровым, интересный стрим про рефакторинг. Рефакторить будут Валентин Удальцов и Леонид Корсаков. Оба те разработчики, у которых стоит учиться. Подопытный — «код популярного опенсорс-проекта на гитхабе»... ну вы поняли какого ;)
-
Новости Yii 2020, выпуск 6
18 сентября 2020
Почти три месяца прошло с последнего выпуска новостей. От нас почти ничего не было слышно. Мы работали. После расширения команды Yii 3 я больше занимаюсь управлением, ревью, проектированием и обсуждениями, чем непосредственно кодом. Получается неплохо. В общем темп ускорился, и мы всё ближе к нашим целям.
Активность на официальном форуме и форуме yiiframework.ru стала совсем низкой если сравнивать со временами Yii 1 и Yii 2. Сообщество перешло в разные социальные сети и чаты. Я думаю, что такая миграция — это плохо. В соцсетях и чатах практически невозможно найти предыдущие ответы. Одни и те же вопросы повторяются практически каждый день и ответы не оседают в поиске. Почти уверен, что тот, кто первым начнёт собирать вопросы и ответы и публиковать их как статьи в wiki или посты в блоге, станет довольно популярным.
А теперь перейдём к тому, что же интересного случилось с последнего выпуска.
-
PHP vs Go
25 августа 2020
15 августа записали видео где попытались разобраться, как пишут приложения на PHP и Go. Участники кроме меня:
- Елена Граховац - руководитель программного комитета конференции GolangConf 2019, экс-ведущая подкаста GolangShow.
- Илья Шихалеев - соорганизатор go-митапов в Йошкар-Оле, Казани и онлайне, по работе также пишет на PHP.
- Руслан Ханов - соорганизует PHP-митапы http://symcode.ru в Петербурге.
- Дискуссию вёл Антон Морев (Wormsoft).
-
AhrefsBot и другие прожорливые поисковые боты
17 августа 2020
Нагрузку на сайт нередко делают не посетители, а разные поисковые боты. Когда-то проблемы были даже от робота Google, но сейчас он научился снижать аппетиты при появлении ошибок или существенном повышении времени ответа. Яндекс тоже поумерил аппетиты и настраивается через Вебмастер.
Но "голодные" боты ещё остались. Один из таких - AhrefsBot. На наше счастье, многие боты, которые сами не умеют регулировать свой аппетит, подчиняются
robots.txt
в корне сайта, директивеCrawl-Delay
. Она выставляет задержку между парсингом следующей страницы в секундах. Одной секунды для многих проектов вполне достаточно (86400 страниц). Если мало - можно использовать дробные значения.User-agent: * Crawl-Delay: 1
UPD: для особо непослушных ботов можно и пожёстче через Nginx.
Создаём в
/etc/nginx
конфигblock-bots.conf
:if ($http_user_agent ~* SemrushBot|MJ12bot|AhrefsBot|DotBot|PetalBot|LinkpadBot|SputnikBot|statdom.ru|MegaIndex.ru|WebDataStats|Jooblebot|BackupLand|NetcraftSurveyAgent|openstat.ru) { return 444; }
И подключаем в каждый блок
server
каждого конфига:server { include block-bots.conf;
-
PHP friendly классы
5 августа 2020
Дружественные классы видят как минимум protected-методы друг друга. В PHP реализуются так:
abstract class Base { protected function doit() { throw new \RuntimeException('Not implemented'); } } class Closed extends Base { protected function doit() { echo 'done!'; } } class Opener extends Base { public function execute(Closed $closed) { $closed->doit(); } } $closed = new Closed(); $opener = new Opener(); $opener->execute($closed);
Здесь можно запустить. Если что, это не баг.
Как это использовать? В Yii 3 мы так закрываем DI-контейнер и диспетчер событий чтобы в рантайме они были только для чтения, но, при этом их можно было сконфигурировать специальными friendly-конфигураторами на этапе инициализации приложения.
Сделано это чтобы не дать стрелять себе в ногу, в этом плюс. Минус в том, что про такую фичу PHP мало кто знает и это вызывает вопросы:
-
PHP fwdays - доклад про код и интервью с автором Composer
16 июля 2020
Выложили видео с конференции PHP fwdays. Изначально я планировал сделать только доклад, но организаторы попросили дополнительно взять интервью у одного из создателей Composer, Jordi Boggiano.
Доклад называется "поговорим про код". В нём я рассказал про подходы, которые позволяют коду меньше ломаться.
Интервью я брал первый раз. Оно на английском. Как оценивать то, что получилось не знаю, будет интересно если отпишетесь в комментариях.