Пых
8.25K subscribers
263 photos
16 videos
6 files
581 links
Блог Валентина Удальцова о разработке на PHP.

Хобот @phpyhobot
https://youtube.com/@phpyh
https://vkvideo.ru/@phpyh
https://t.iss.one/isPHPdying

Статистика: https://t.iss.one/INOTAROBOT?start=st1219340804

Для связи используйте личные сообщения канала.
Download Telegram
📈 Выборочная оптимизация на примере Composer 2.2

Рекомендую январский выпуск Пятиминутки PHP, в котором Пётр разобрался, как разработчики ускорили Composer, и поставил под сомнение их результат.

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

1. Исследуем очередное узкое горлышко в программе.
2. Ищем предпосылку, при которой можно можно провести оптимизацию подпрограммы.
3. Выдвигаем гипотезу о том, что при использовании программы предпосылка выполняется достаточно часто.
4. В случае подтверждения гипотезы, проводим оптимизацию для этой предпосылки.

Здесь важен баланс между стоимостью оптимизации (затраты на внедрение, прирост сложности кода) и профитом от неё (изменение целевых метрик, доля улучшенных сценариев). Иными словами, игра должна стоить свеч.

https://5minphp.ru/episode95/
🔥15👍7
Сегодня коллеги поздравили меня прекрасным PHP-тортом! 🎉💚
👍130🎉106🔥21👎2👏2
SuperJob о зарплатах PHP-разработчика в июне 2022 года

Информация для канала предоставлена пресс-службой SuperJob.

Программисты PHP в среднем зарабатывают в Москве 250 тыс. руб. в месяц, в Санкт-Петербурге — 210 тыс. руб., в Екатеринбурге и Ростове-на-Дону — по 200 тыс. руб. Наиболее востребованы специалисты с опытом разработки на PHP от 2 лет. Работодатели отдают предпочтение кандидатам с опытом работы с различными фреймворками, навыками рефакторинга чужого кода и unit-тестирования. Также востребован опыт проектирования и поддержки клиент-серверного API.

Минимальные зарплаты для кандидатов с опытом работы с PHP от полугода составляют 90-120 тыс. руб. в Москве, 80-100 тыс. руб. в Санкт-Петербурге и от 60/70-100 тыс. руб. в городах миллионниках. Чтобы претендовать на такую зарплату, кандидат должен знать теории баз данных и иметь опыт работы с СУБД, знать ООП, JavaScript, HTML и CSS, XM, а также уметь читать техническую документацию на английском языке.

При этом максимальные зарплатные предложения составляют 300-500 тыс. руб. в Москве, 250-420 тыс. в Санкт-Петербурге, до 350 тыс. руб. в Екатеринбурге, Ростове-на-Дону и Краснодаре — до 400 тыс. руб. в месяц, в Новосибирске — 380 тыс. и в Казани – 350 тыс. руб. в месяц.

Кстати по данным SuperJob, за год средние зарплатные предложения в IT-сфере выросли на 20,4%, а количество вакансий в IT за месяц увеличилось на 11%.

Подробнее и больше цифр: https://www.superjob.ru/research/articles/113508/programmist-php/
👍55👎10
Пых
Какая у тебя ЗП в тысячах рублей?
Дудь, разлогинься 😂
В продолжение предыдущего поста предлагаю повторить наш опрос о ЗП. Сравним результаты с сентябрём 2020. Итак, пыхарь, сколько нынче получаешь в тысячах рублей?
Anonymous Poll
10%
<50
15%
50-100
18%
100-150
18%
150-200
15%
200-250
9%
250-300
5%
300-350
3%
350-400
1%
400-450
5%
>450
🔥43🤩5👍4👎4
🏫 Мой продвинутый курс по PHP

Я уже пару лет мечтаю о том, чтобы масштабно и комплексно поделиться знаниями, и наконец-то мне представилась возможность записать свой продвинутый курс по PHP! Огромное спасибо Loftschool за предложение посотрудничать!

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

https://youtu.be/yMrbatAM3bw
🔥130👍32👎3🎉1👌1
Тип parent

Недавно осознал, что parent можно использовать как тип в любых местах. Вроде и логично, но как-то странно... Согласитесь, вы бы поёжились, если бы увидели что-то подобное на ревью.

final class ParentOverdose extends ArrayObject
{
public function __construct(
public parent $iAmParent,
) {
parent::__construct();
}

public function iReturnParent(): parent
{
return new parent();
}

public function iAcceptParent(parent $parent): void
{
}
}

https://3v4l.org/TDXEa
🤯54🔥13👍11🤩7👏2
Ищу к себе в команду middle/senior разработчика!

В Happy Inc мы исследуем вовлечённость и лояльность персонала в крупных компаниях: проводим анонимные опросы, строим сложные отчёты, доставляем их клиентам в различных форматах.

У нас модульный монолит без легаси. PHP 8.1 / Symfony 6.1 / PostgreSQL 14 / RabbitMQ / OpenAPI / CQRS / Psalm / Thesis и всё, о чём я тут рассказываю. 😜

Full-time, пока приоритетно в офис, ЗП по результатам собеса.

Резюме мне в ЛС @vudaltsov.

Update: пока неактуально в связи с ситуацией.
👍33🤯3👎1
bind

Помните, я недавно рассказывал, почему не стоит пренебрегать функциями в PHP? В этом посте приведу ещё один пример функции, выполняющей роль фасада.

Иногда в инфраструктурном коде приходится обходить инкапсуляцию. Например, когда пишешь свой DataMapper или оборачиваешь корявое вендорное API.

Самый простой способ получить доступ к чему-то приватному — это привязать замыкание к контексту класса при помощи Closure::bind (подробнее в статье Ocramius). Однако у сигнатуры этого метода есть ряд проблем:

1. По опыту удобнее всего менять scope, а не $this, но параметр $newScope идёт третьим.
2. Можно было бы скипнуть второй параметр, используя именованные аргументы, но $newThis не имеет значения по умолчанию, поэтому приходится явно передавать null.
3. Метод возвращает ?Closure, из-за чего приходится проверять !== null вместо того, чтобы сразу писать Closure::bind(fn () => ...)().
4. Не поддерживается статанализ (лечится добавлением соответствуюещго стаба в проект или в анализаторы через PR).

Что будем делать? Мучиться? Нет, добавим в проект простую функцию bind, которая разом решит все проблемы!

Вариант такой функции: https://3v4l.org/K1LUG.
Кстати, Psalm падает при использовании @template of Closure, а вот PhpStan справляется: https://phpstan.org/r/40205124-4b2f-4c1b-94fe-a05eb14488e2.

И ещё. Я считаю, не стоит делать composer-пакеты из таких функций, потому что в каждом проекте они будут называться и выглядеть по-разному. Такие тривиальные штуки гораздо проще копировать и адаптировать под свои представления о прекрасном, чем тянуть сомнительные зависимости.
👍22🔥8👎1
Как изощрённо очистить свойство после чтения

Встретил в коде Symfony альтернативное решение задачи из старого поста.

Пишите в комментариях, пропустили ли бы вы такой код на ревью и почему. 🤓

/**
* @return list<object>
*/
public function releaseEvents(): array
{
try {
return $this->events;
} finally {
$this->events = [];
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥67🤯34👎18👍4
Если вы используете Deployer, то после успешного пятничного деплоя можете поиграть в Блэкджек из консоли.

./vendor/bin/dep blackjack
🔥79🤩16👍12🤔2
Podlodka PHP Crew

Думаю, все вы слышали про однонедельные интенсивы от авторов известного подкаста Podlodka. Так вот, 31-ого октября стартует первая Podlodka PHP Crew!

Тема этого сезона — архитектура (антипаттерны, best practices, DDD, API, события). Среди докладчиков Александр Макаров, Антон Титов, Дмитрий Елисеев, Павел Лакосников и другие пыхари из Skyeng, ManyChat и Тинькофф.

Подробности на сайте, там же скоро финализируют расписание. Покупать билеты лучше сейчас — скидки действуют только до следующего понедельника!
👍33🔥8👎3
Пых
Continuous Integration CI — must have для проекта любого размера. CI повышает качество кодовой базы, дисциплинирует команду и сокращает количество и продолжительность ревью. Идеи проверок на базе нашего пайплайна в Happy Inc.: • кодстайл (PHP CS Fixer, …
Continuous Integration Tools 2.0

Почти полтора года назад я выложил пост с основными идеями для CI-пайплайна проекта на PHP. С тех пор не так много изменилось, разве что Rector стабилизировался и для многих стал инструментом рефакторинга номер один, а в Composer появился встроенный анализ уязвимостей.

Представляю обновлённый список по категориям ("+" помечены новые пункты, через "/" перечислены альтернативы).

Рефакторинг
+ автоматический рефакторинг и актуализация кода (Rector),
• кодстайл (PHP CS Fixer / PHP_CodeSniffer / EasyCodingStandard),
• статический анализ (Psalm / PHPStan / PHPMD).

Пакеты
+ проверка на уязвимости (composer audit),
• валидность composer.json (composer validate),
• явное требование задействованных пакетов (ComposerRequireChecker),
• отсутствие неиспользуемых пакетов (composer-unused).

Symfony Dependency Injection
+ собирабельность prod-контейнера (bin/console cache:clear --env=prod),
• проверка синтаксиса Yaml-файлов (bin/console lint:yaml config --parse-tags),
• проверка соответствия типов инъекций контейнера Symfony (bin/console lint:container),
• отсутствие устаревших сервисов и конфигов Symfony (bin/console debug:container --deprecations).

Twig
• проверка синтаксиса Twig-шаблонов (bin/console lint:twig).

Doctrine
• валидность маппинга и соответствие ему схемы БД (bin/console doctrine:schema:validate),
• корректность продакшн-конфигурации (bin/console doctrine:ensure-production-settings --env=prod).

Модули
• контроль связности/зацепления и направления зависимостей (Deptrac).

Ну и конечно же тесты
+ мутационное тестирование (Infection),
• сами тесты (PHPUnit / Codeception).

Список всё так же вдохновлён нашим пайплайном в HappyInc. Пишите в комментариях, без чего не обходится сборка вашего проекта и что ещё рекомендуете попробовать.

Также обратите внимание на репозиторий Static analysis tools for PHP и доклад 25+ инструментов для аудита кода.
🔥76👍27🤩31
🔴 Пыхэфир в эту субботу!

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

Буду готов обсудить новости из мира PHP, прокомментировать чей-нибудь код, ответить на любые вопросы по PHP да и просто поговорить за жизнь. Пишите в комментариях, всё, что вам могло бы быть интересно.

Встречаемся в субботу в 17 на канале PHP Point. Если не будете онлайн, не переживайте, запись никуда не денется.

https://youtu.be/2UiGZVrNG6c
👍53🔥27👎1
🔨 Первый в мире PHP-линч!

После нашей субботней встречи у меня появилась идея комментировать PHP-код на постоянной основе. Должно получиться пхплебно, зрелищно и очень познавательно!

Попробуем такой процесс:
1. Во время стрима вы скидываете в чат трансляции ссылки на репозитории и в трёх словах описываете, что там. Это может быть ваш пет-проект или библиотека, а может быть компонент (не)известного фреймворка. Заранее ссылки не принимаются.
2. Я выбираю проект по душе и клонирую репозиторий.
3. Комментирую на лету, говорю, что думаю, без обид.

Первый в мире PHP-линч пройдёт в эту среду в 18 часов на канале PHP Point. Запись обязательно будет.

https://youtu.be/MwMCzqvCGKo
🔥111👍25🤩2👎1
Пых
🔨 Первый в мире PHP-линч! После нашей субботней встречи у меня появилась идея комментировать PHP-код на постоянной основе. Должно получиться пхплебно, зрелищно и очень познавательно! Попробуем такой процесс: 1. Во время стрима вы скидываете в чат трансляции…
🩸 Буквально через 5 минут начнётся первый в мире PHP-линч! 🎉

В честь дебюта проекта я разыграю два билета на Podlodka PHP Crew! Один из них вручу тому, кто скинет на ревью самый полезный и интересный проект. Второй билет получит наиболее активный участник чата трансляции. Подключайтесь!

https://youtu.be/MwMCzqvCGKo

Update. В трансляцию добавлены эпизоды, автору shoman4eg/moy-nalog и Alex D вручены билеты!
👍24🔥14🤩2
🎙 Пых в пятом выпуске CONSOLE.DIALOG

Мой друг и бывший коллега Алексей Соловьёв пригласил меня на подкаст CONSOLE.DIALOG, чтобы обсудить принятие решений в IT. Поговорили про путь в разработке, коммуникацию в идеальной компании и про то, как мы однажды в Happy Inc. всё переписали.

Получилось очень лампово, уверен, вы что-нибудь для себя почерпнёте. Большое спасибо, Лёш, за такую неожиданную тему!

Послушать можно где угодно, выбирайте: https://consoledialog.mave.digital/ep-5.

Подписывайтесь на @lyohajs в Telegram и Алексея Соловьёва в YouTube.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥9🎉2
$reflectionPromotedProperty->hasDefaultValue()

final class A
{
public function __construct(
public string $a = 'default',
) {}
}
$property = new ReflectionProperty(A::class, 'a');
var_dump($property->hasDefaultValue()); // false

Довольно контринтуитивно, что этот код выведет false.

Однако если развернуть promoted свойство в обычное, станет понятно, почему:

final class A
{
public string $a;

public function __construct(
string $a = 'default',
) {
$this->a = $a;
}
}
$parameter = new ReflectionParameter([A::class, '__construct'], 'a');
var_dump($parameter->isDefaultValueAvailable()); // true

Дефолтное значение имеет не свойство, а параметр конструктора!
Как следствие, вот такой код

$class = new ReflectionClass(A::class);
$a = $class->newInstanceWithoutConstructor();
var_dump($a->a);

выбросит Typed property A::$a must not be accessed before initialization.

https://3v4l.org/kkf24
👍48🔥14🤩2
#[<T>] Дженерики через атрибуты

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

Ход мысли такой. Сейчас мы описываем общие типы для Psalm и PHPStan в phpdoc-ах, то есть, по сути, и используем стираемые дженерики, только с не особо стандартизованным синтаксисом и в комментариях, КАРЛ. А ещё у нас есть атрибуты — синтаксис в PHP, предназначенный для метаинформации. Так почему бы нам не объединить две эти вещи? Так как атрибуты в текущем виде слабо подходят для типизации, Рома предлагает расширить их синтаксис, в частности, разрешить ставить атрибуты над выражениями и перед типом возвращаемого значения.

https://pronskiy.com/blog/generics-via-attributes-in-php/

Я считаю, что это интересный альтернативный взгляд на дженерики в PHP, но с ним связано несколько проблем:

1. Нарушение принципа единой отвественности для атрибутов. Мы либо получим неоднозначность в определении понятия "атрибут", либо просто дженерики с похожим синтаксисом.

2. Инстанциированные атрибуты можно получить только через рефлексию. Рефлексия — это рантайм и автолоадинг. Статанализ же в идеале вообще не должен запускать анализируемый код. Именно поэтому появились такие проекты, как PHP Parser и Better Reflection. Если же обновлённые атрибуты будут использоваться только как синтаксис, то нет смысла их называть атрибутами.

3. Приведенную в статье декларацию атрибута-дженерика над выражением вообще не получится отрефлексировать, поскольку для выражений по определению невозможна рефлексия. Из-за этого синтаксис дженериков может быть реализован только на уровне языка.

Получается, что замаскированные под атрибуты дженерики технически не смогут ими быть. Ну а в таком случае проще реализовать стираемые дженерики с привычным синтаксисом array<string, object>. Если же по каким-то техническим причинам необходимо оборачивать декларации в #[], то пусть это просто будут дженерики с таким синтаксисом.

Что касается самой концепции стираемых дженериков, я её однозначно поддерживаю. Да, такой подход требует наличия внешнего анализатора, но взамен даёт стандартизированный синтаксис, нативный парсинг кода с дженериками и популяризацию обобщённого программирования среди PHP-разработчиков.

Я очень рад, что Рома в очередной раз подогрел дискуссию вокруг дженериков. Любой подобный движ полезен для сообщества и приближает нас к результату.
👍43👎12🤔5🔥2🤩1
Сколько, по вашему мнению, я, Валентин, стою как PHP-разработчик и тимлид в рублях в месяц?
Anonymous Poll
15%
200к
8%
250к
16%
300к
17%
350к
15%
400к
8%
450к
21%
БОЛЬШЕ!!!