PHP-Дайджест № 182 (1 – 22 июня 2020)


    Свежая подборка со ссылками на новости и материалы. В выпуске: 3 принятых и 6 новых RFC-предложений из PHP Internals, включая голосование за новый синтаксис для атрибутов — @@ и почему #[] был бы лучше, переименования black/whitelist в PHP-мире, как отлаживают PHP-разработчики, аналог ngrok на PHP, видео, подкасты и многое другое.

    Приятного чтения!



    Новости и релизы



    PHP Internals


    • check [RFC] Attribute Amendments — Приняты дополнения к атрибутам: возможность группировать <<Attr1, Attr2>>, PhpAttribute переименован в Attribute, валидация и возможность добавлять несколько одинаковых атрибутов.
    • check [RFC] Ensure correct signatures of magic methods — Сигнатуры магических методов в PHP 8 будут валидироваться. Например, сейчас можно объявить в классе вот такой магический метод:
      Скрытый текст
      class Foo
      {
          function __get(int $name): void
          {
              echo $name;
          }
      }
      (new Foo)->{42};
      
      В PHP 8 это вызовет ошибку на этапе компиляции.
    • check [RFC] Make sorting stable — Все стандартные функции сортировки в PHP (sort, usort, asort и т.д.) начиная с PHP 8.0 будут стабильными. Это значит, что гарантируется оригинальный порядок элементов с одинаковыми значениями. В текущих версиях легко найти примеры, когда это не так.
    • cross [RFC] Opcache optimization without any caching — Отклонено предложение по выполнению оптимизаций без кеширования опкодов.
    • [RFC] Make constructors and destructors return void — Сейчас в PHP можно возвращать любые значения из конструкторов и деструкторов, например:
      Скрытый текст
      class Test {
              public function __construct() {
                      return 0;
              }
      
              public function __destruct() {
                      return 1;
              }
      }
      
      $test = new Test();
      
      // this prints 0
      echo $test->__construct();
      // this prints 1
      echo $test->__destruct();
      
      Предлагается в PHP 8.0 бросать Deprecated предупреждение в таких случаях. А уже в PHP 9.0 запретить полностью и генерировать Fatal Error.
    • [RFC] Treat namespaced names as single token — Из-за того, что каждый элемент неймспейса рассматривается интерпретатором как отдельный токен, внутри неймспейса не может быть ключевого слова. Например, namespace app\function { class Foo {} }; свалится с ошибкой Parse error. Предлагается считать токеном весь неймспейс — это позволит минимизировать проблемы обратной совместимости при введении новых ключевых слов.
    • [RFC] Rename T_PAAMAYIM_NEKUDOTAYIM to T_DOUBLE_COLON — Токен :: в PHP называется T_PAAMAYIM_NEKUDOTAYIM — этот факт даже был обозначен как проблема № 1 в списке грустей PHP.
      Автор предлагает переименовать токен. Смысла в этом нет, потому что в сообщениях об ошибке итак выводится ::, а с таким названием он и гуглится идеально.
    • [RFC] Shorter Attribute Syntax — Аттрибуты уже были приняты для PHP 8, но синтаксис многим не по душе. На голосование выставлено три варианта: <<Attr>> (текущий) vs @@Attr vs #[Attr]. Brent Roоse привел несколько убедительных аргументов в пользу #[ ]:
      • Такой же синтаксис в Rust.
      • Он обратно совместим: #[Attribute] просто проигнорируется интерпретатором PHP <=7.4 как комментарий.
      • @@ можно спутать с оператором подавления ошибок (пример).
      • <<>> тоже не очень, потому что можно спутать с битовыми операторами и в будущем с дженериками, которые вероятно будут использовать одинарные угловые скобки <>.

    • [RFC] Change terminology to ExcludeList — Тема переименования потенциально неполиткорректных терминов не обошла стороной и PHP-мир. В Internals были горячие обсуждения.
      В ядре PHP изменение только в одном месте: директиву конфигурации опкеша opcache.blacklist_filename предлагается заменить на opcache.exclude_list_filename.
      В других PHP-инструментах соответствующие изменения уже внесли: PHPUnit, Drupal, Xdebug, Yii, Composer (+ работа с не-master Git-ветками). Также есть обсуждение правил для PHP_CodeSniffer для поиска «плохих» слов.
    • [RFC] Nullsafe operator — Вместо пачки вложенных условий предлагается добавить возможность обращения к свойству или методу с проверкой на null:
      $country = $session?->user?->getAddress()?->country;

      Вместо
      $country =  null;
      
      if ($session !== null) {
          $user = $session->user;
      
          if ($user !== null) {
              $address = $user->getAddress();
      
              if ($address !== null) {
                  $country = $address->country;
              }
          }
      }
      
    • Обновлено расписание PHP 8.0 — Заморозка новых фич сдвинута на 4 августа, а финальный релиз назначен на 26 ноября.
    • Пощупать PHP 8 можно на известном ресурсе 3v4l.org. Для этого достаточно посмотреть результат запуска в ветке php-master.

    Инструменты


    • beyondcode/expose — Сервис туннелирования на чистом PHP. Аналог ngrok. Подробнее было в канале PHP Digest.
    • canvural/php-openapi-faker — Библиотека для генерации тестовых данных для OpenAPI запросов/ответов/схем.
    • doctrine/migrations 3.0.0 — Мажорное обновление инструмента для миграций.
    • mathiasverraes/uptodocs — Маленький инструмент, который находит блоки PHP-кода в Markdown-файлах и запускает их для поиска падающих.

    Symfony



    Laravel



    Yii



    Laminas



    Async PHP



    Материалы для обучения



    Аудио/Видео



    Спасибо за внимание!

    Если вы заметили ошибку или неточность — сообщите, пожалуйста, в личку.
    Вопросы и предложения пишите на почту или в твиттер.

    Больше новостей и комментариев в Telegram-канале PHP Digest.

    Прислать ссылку
    Поиск ссылок по всем дайджестам
    Предыдущий выпуск: PHP-Дайджест № 181

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 58

      +3
      > Brent Roоse привел несколько убедительных аргументов в пользу #[ ]:

      > Такой же синтаксис в Rust.
        +1

        Хах, Rust уже становится законодателем мод? )

        +3
        Еще два возможно интересных лайва в этом месяце:

        1. В эту пятницу (26.06) на ютубе будет лайв-запись интервью с самим Романом о PHP-дайджесте и не только.

        2. В следующую среду (1.07) на ютубе будет интерактивная лайв-запись подкаста SDCast
        о код-ревью с Александром Макаровым, Сергеем Жуком и не только: сслыка на эфир появится в ближайшие дни на этом канале.
        +8
        Тема переименования потенциально неполиткорректных терминов не обошла стороной и PHP-мир.

        Совсем с дубу рухнули… Делать им нечего. На месте SamDark я бы послал их лесом, а не поддавался на провокации. =\

          +2

          Мир сходит с ума, ладно списки, больше негодования вызывает переименование master в main, такое ощущение что у слова мастер только один перевод существует. А потом мы main переименуем во что-то более корректное, т.к. превосходство одного человека над другим это оскорбительно и все должны быть равны.

            +2

            Не, ну оправдания ради, те изменения что в PR Yii (на которые я ссылался в комменте выше) действительно улучшают в некоторых местах читаемость.

              +1

              Exclude/include часто понятнее, чем blacklist/whitelist.

                +1

                Поэтому и применили. Там была ещё попытка master/slave переименовать и primary/replica, но в итоге откатили. Технически получилось очень плохо. Оно того не стоит.

                  +10
                  Но ведь семантика терминов «whitelist» и «include[list]» совершенно разная!

                  Во-первых, как «blacklist», так и «whitelist» — списки исключений. Например, в каком-нибудь условном адблоке адреса из белого списка являются исключениями из общих правил блокировки, не должны проверяться регулярками и пролетать насквозь. И точно также адреса из чёрного списка являются исключениями из общих правил — они тоже не должны проверяться, а сразу блокироваться. Уже здесь назревает путаница, потому что в новой терминологии теперь есть свои «исключения» — «exclude»! А «include» рядом ещё и создаёт впечатление, что для того, чтобы с объектом было проведено какое-то действие, он должен быть «включён» в список «includelist», а это не так.

                  Во-вторых, разные проекты заменяют «неполиткорректные» старые термины разными новыми. Где-то это «blocklist», где-то «stoplist», где-то «excludelist», где-то просто «exclude». Такая фрагментация только добавит проблем.

                  В-третьих, новые термины ещё и весьма неоднозначные — например в xdebug теперь есть XDEBUG_PATH_INCLUDE. Это что — путь, по которому что-то лежит? Как CPLUS_INCLUDE_PATH? Нет. А читается именно так.

                  Эту дичь следует остановить немедленно. Я уверен, что людей, которые не одобряют такие изменения, достаточно, однако всеобщее внедрение в проектах «кодексов поведения» приводит к тому, что они даже боятся высказаться против, потому что «Расист! Расист!». Наблюдаем ru.wikipedia.org/wiki/Спираль_молчания во всей красе.
                    +4

                    Высказаться не против, но куда высказываться? Из всех людей которых я знаю никто не одобрил такие переименования.

                      0

                      Не знаю как там в разных проектах, но в Yii стало понятней после переименования, чем было до.

                +3

                У меня задача — сделать максимально хорошо фреймворку как долгосрочному проекту. Если переименование технически не делает плохо и весомая часть сообщества становится от этого счастливее, не вижу причин не переименовать. Если при этом читается лучше, то появляется ещё и личная мотивация это сделать.

                  +5
                  весомая часть сообщества становится от этого счастливее
                  13 дизлайков, и 1 лайк под тем МРом, если посмотреть, то почти все МРы на переименования, задизлайканы, что показываем что не всем это нравится.
                    –1

                    Конечно не всем. Это не нравится тем, у кого культурно-исторический бэкграунд не такой и они откровенно не понимают, как на такое можно обижаться и вообще зачем оно надо. Все дизлайки там как раз от наших ребят и да, понятно почему. Потому что проблемы у нас этой нет и никогда не было. Но это не значит что её нет у других. Если посмотреть на фидбек в том же твиттере, становится понятно, что всё-таки многим это, как ни странно, важно.

                      0

                      Помимо собственно культуры (что очень важно!) есть еще нюанс, что для нас термин на неродном языке. Ну мастер, ну слейв — делов-то. А вот было бы по-русски (какой-нибудь там 1C) — хозяин / раб. Уже немного корежит, правда?

                        +2
                        Кого будет корежить от этого после событий 17-го года? Нет больше ни хозяев, ни рабов ( в правовом поле) и очень давно.
                          +2
                          А вот было бы по-русски (какой-нибудь там 1C) — хозяин / раб
                          Пример подобран не совсем корректно, поскольку «хозяин» в русском языке в основном воспринимается довольно однозначно, а «master» несёт в себе несколько совершенно разных значений, если я не ошибаюсь.

                          P.S.: К тому же, запрет слова «хозяин» может оскорбить чувства любителей БДСМ.
                          +2
                          Этот фидбек показывает только общую безграмотность.

                          en.wikipedia.org/wiki/Blacklisting#Origins_of_the_term

                          Сам термин несколько старше расовой проблемы и дискриминации применительно к афроамериканцам, что и явилось основой движения против термина.
                      +2
                      Иногда задаю вопрос, этим борцам за социальную справедливость, читали ли они Бредбери, а именно «451º по Фаренгейту». По моей скромной статистике только 1 лайк и 0 ответов, вообще каких либо.
                        0

                        Антиутопии читать не всем приятно, как и читать в общем. Пожалуй, Harrison Bergeron подходит к экстремальным проявлениям чуть лучше, чем Бредбери.

                          0

                          Спасибо, прочту!

                      +8
                      Предлагаю выпилить из php оператор подавления ошибок, тогда синтаксису @Attr ничего мешать не будет.
                        +4
                        Боюсь тогда придется выпилить из PHP все ворнинги и заменить их на эксепшены.
                        К примеру такой код:
                        $а = file_get_contents('https://domain.com');
                        

                        Выкинет ворнинг если удаленный ресурс недоступен. И это нормально, что удаленный ресурс может быть недоступен. Только еслиб эта функция бросала эксепшен, то я просто обернул бы ее в try… catch и обработал бы ошибку как надо. В текущем же варианте, чтоб не засорять лог ошибок, приходится добавлять @ перед этой функцией и лишь затем проверять, а не произошла ли ошибка.

                        Конечно можно решить эту проблему с помощью set_error_handler, но данный механизм крайне не гибкий и неудобный в использовании, ведь в место того, чтоб ловить ворнинг в конкретном одном месте оно будет ловить ворнинги отовсюду в коде, хотя как раз там нужно чтоб они сыпались в лог.
                          +2
                          Заменить все нотисы и ворнинги на эксепшны тоже давно пора. Я вообще ждал этого в 7.0 и был дико разочарован, когда оказалось, что на эксепнны заменили только фаталы.

                          В любом случае все фреймворки и так ловят ошибки с помощью set_error_handler и бросают там соответствующие эксепшны. Да и в велосипедных решениях часто практикуется именно такой подход.

                          А вот сколько лет назад я последний раз видел код с собакой — я наверное и не упомню уже.
                          0
                          Конечно можно решить эту проблему с помощью set_error_handler, но данный механизм крайне не гибкий и неудобный в использовании, ведь в место того, чтоб ловить ворнинг в конкретном одном месте оно будет ловить ворнинги отовсюду в коде, хотя как раз там нужно чтоб они сыпались в лог.
                          Делают и в «конкретном одном месте»:
                          set_error_handler(self::$emptyErrorHandler);
                          
                          $value = include $fileName;
                          
                          restore_error_handler();
                            0
                            Если ворнинги засоряют лог ошибок, то всегда можно выставить нужный log level. Ваш КО :) Вообще забавно как с одной стороны синтаксис языка делают все строже чтобы программист не дай бог ничего не смог нашкодить, а с другой дают ему такой инструмент как подавление ошибок с помощью @. Давно пора использовать @ в качестве атрибутов.
                            +1
                            Поддерживаю. Причем выпилить не столько оператор подавления, сколько сами ошибки в принципе. Наличие разных сущностей для одного и того же — Exception и Error (+ не забываем про return false местами, можно вообще запретить return bool — без него нормально было бы) — существенно усложняет жизнь.

                            upd: пока читал статью и писал коммент — выше уже сказали про замену ошибок на эксепешены…
                            +6
                            T_PAAMAYIM_NEKUDOTAYIM — этот факт даже был обозначен как проблема № 1 в списке грустей PHP.

                            Если кому интересно, то PAAMAYIM NEKUDOTAYIM это на иврите "פעמיים נקודתיים" означает дважды двоеточее.
                              +1
                              возможно этот список составил скрытый антисемит!
                              +11

                              От предложенного синтаксиса аннотаций у меня кровоточат глаза. Вариант с #[] реально лучше выглядит.

                                0
                                Мне изначально тоже так показалось, но потом я прочитал RFC. Да и в целом: закладывать логику в комментарии — довольно спорная идея. Вариант с собачками весьма неплох.
                                  0

                                  В целом я больше привык к аннотациям в стиле Java или C#, и там и там они выглядят неплохо. Вариант с комментом можно сделать отдельным синтаксисом, который с первого взгляда выглядит как комментарий, но для языка является синтаксической конструкцией, при этом сохраняется хоть какая-то обратная совместимость со старым версиями php как бонус.

                                    +1
                                    при этом сохраняется хоть какая-то обратная совместимость со старым версиями php
                                    На мой взгляд это ещё один способ усложнить жизнь.
                                    Ностальгия
                                    <!--[if IE]>
                                    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
                                    <![endif]-->
                                    

                                    Особенно вот это круто
                                    $object = new #[ExampleAttribute] class () {};
                                    $f1 = #[ExampleAttribute] function () {};
                                    $f2 = #[ExampleAttribute] fn() => 1;
                                +7
                                В Symfony 6 для конфигов будут использоваться PHP-файлы вместо YAML или XML.

                                Никогда не понимал зачем вообще эти форматы используются в PHP фреймворке
                                  0
                                  Для более гибкой работы при развёртывании, всякие jenkins и прочие CI/CD могут без проблем редактировать YAML или XML.
                                    +2

                                    Это было актуально (тоже этим занимался) примерно до 3.3 симфони, потом она начала адекватно с .env работать, что со стороны CI/CD на порядки удобнее.

                                    –4
                                    Возможность использовать php для конфигов была и раньше. YAML просто более удобный.
                                      +4
                                      В файлах конфигурации на PHP можно выполнять код, и эта «фича» далеко не всегда желательна.
                                        0
                                        1. Чтобы не было соблазна писать туда любой код и вообще делать конфиги слишком динамичными.
                                        2. Связка PHPStorm + Symfony plugin = автокомплит прямо в yaml-конфиге. Будет ли он реализован и таким же удобным как в yaml? Сейчас я не вижу подсказок для php-конфигов.
                                        3. Можно использовать конфиги на php (в 4 и 5 версиях) и все доки это учитывают.

                                        Ссылка из поста, если я правильно понял, на PR о внутренних и библиотечных конфигах. У меня глаза кровоточили когда надо было заглянуть в конфиг symfony или бандла, а там внезапно xml.
                                        +2
                                        А с дебагом, имхо, самый частый подход — dump & die в легких случаях и дебаггер, когда прям вообще дичь непонятная происходит)
                                          +1

                                          Если какой-то framework — там в этом dump может быть столько всего что замучаешься листать :)


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

                                            +1
                                            Тут напрямую от ситуации зависит, что то мелкое — dump, непонятно что происходит — xdebug.
                                              0

                                              Согласен, хотя простота запуска отладчика меня совсем избаловала… :)

                                            +1
                                            В дебаггере мне не нравится один момент — когда в шторме начинаешь переходить по строкам дальше то он начинает переходить в автозагрузчик, в методы композера, в которых подключаются файлы, и тут можно клацать кол часа что бы пройти пару строчек кода
                                              +3

                                              Это легко решается в PhpStorm. В настройках Preferences | Languages & Frameworks | PHP | Debug | Step Filters нужно добавить пути, которые вас не интересуют и отладчик автоматически их будет пропускать.



                                              Дока: https://www.jetbrains.com/help/phpstorm/step-filters.html#ff36ae77

                                            –1

                                            есть симфоневский вардампер и блакфайр (странно, как еще не перименовали). иксдебаг чересчур тяжелый.

                                              +2
                                              Совсем уже поехали с переименованиями. Как будто это как-то повлияет на реальность.
                                                –2
                                                Французы любят пых, это важно)
                                                  +1
                                                  Спасибо за подборку!
                                                    –1
                                                    $country = $session?->user?->getAddress()?->country;


                                                    Зачем? Как в цепочке обработать null?
                                                    Это тоже самое что и подавление ошибок @ — зло
                                                      +1

                                                      не тоже.
                                                      например, в js/typescript используется. очень удобно.

                                                        –3
                                                        Очень удобно что?

                                                        for($i = 0; $i < 100; ++$i) {
                                                        ...
                                                          $country = $session?->user?->getAddress()?->country;
                                                          $district = $session?->user?->getAddress()?->district;
                                                          $street = $session?->user?->getAddress()?->street;
                                                        ...
                                                          $user?->setName($cache?->getUser(1)?->name); // nice
                                                        ...
                                                        }
                                                        


                                                          0
                                                          Зависит от задачи. Если ты парсишь сторонние ресурсы и предполагаешь что каких то полей может не быть, но сохранить все равно хочешь, пусть и с пустыми полями то такой вариант намного лучше и читабельнее чем плодить 100500 if(!empty())
                                                        +2

                                                        Если надо обработать null особым образом, а не просто null вернуть, то не используйте.

                                                        0
                                                        Также сделали правила для PHP_CodeSniffer для поиска «плохих» слов.


                                                        Не «сделали», а открыли issue и начали обсуждение. Кроме обсуждения, там ничего нет.
                                                          0

                                                          Поправил текст, спасибо.

                                                        Only users with full accounts can post comments. Log in, please.