PHP-Дайджест № 110 – свежие новости, материалы и инструменты (28 мая – 11 июня 2017)



    Свежая подборка со ссылками на новости и материалы. В выпуске: PHP 7.2.0 Alpha 1, свежие предложения из PHP Internals, Symfony 3.3.0, Yii 1.1.19 и 2.0.12, нововведния Laravel 5.5, спор о Visual Debt и многое другое. Приятного чтения!



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




    PHP


    • Короткий синтаксис для анонимных функций — В Internals активно обсуждается возможная реализация коротких лямбд. Ранее рассматривался и был отклонен на голосовании синтаксис с тильдой: $x ~> $x + 1;, а также ^($x) => $x + $y. На данный момент рассматриваются следующие возможные варианты:

      fn(params) => expr
      function(params) => expr
      (params) ==> expr
      (params) => expr
      [](params) => expr
      

    • Включить PCS в ядро — Предложение для PHP 7.3 пока не оформленное в официальный RFC. PCS — это модуль, который позволяет писать расширения для PHP на PHP и С одновременно. Подробнее о PCS. Включение такой возможности в ядро позволит переписать многие расширения на PHP. Это, в свою очередь, позволит сильно упростить код, уменьшить число багов, и увеличить количество потенциальных ментейнеров.

    Инструменты


    • reactphp/http v0.7.0 — HTTP/HTTPS сервер на базе ReactPHP.
    • hollodotme/fast-cgi-client — FactCGI клиент для отправки (а)синхронных запросов в PHP-FPM. Слайды, примеры использования с Redis и с RabbitMQ.
    • samdark/hydrator — Извлечение данных и заполнение данными объектов. Пост в поддержку.
    • phunkie/phunkie — Набор структур для функционального программирования на PHP. Туториал в поддержку.
    • gilbitron/sqsd — Демон эмулирует работу Amazon SQSD на локальной машине.
    • formapro/pvm — Библиотека для описания схемы процесса (workflow). Поддерживает асинхронные переходы и параллельное выполнение задач.
    • Composercat — Десктопное GUI приложение для Composer.
    • php-enqueue/enqueue-dev — Очередь сообщений с поддержкой транспортов AMQP (RabbitMQ, ActiveMQ), STOMP, Amazon SQS, Redis, Doctrine DBAL, Filesystem.

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



    Занимательное


    • joaoescribano/UltimaPHP — Сервер популярной некогда игры Ultima Online на PHP.
    • 6 файлов, которые являются валидным PHP — GIF, PDF, JPG, которые можно выполнить как PHP.
    • Тайпхинты и интерфейсы — визуальный шум? — Jeffrey Way опубликовал видео, в котором рекомендует удалить тайпхинты, интерфейс, и объявление final, называя их визуальным шумом. На что получил ряд критических ответов, например тут, тут, и тут. Энтузиасты даже создали специальный инструмент статического анализа для поиска «визуального шума» — phpvisualdebt.

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

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

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

    Zfort Group
    113,00
    Компания
    Поделиться публикацией

    Комментарии 51

      –1
      Что-то относительно мало ссылок, или мне так кажется?
        +1
        В среднем в дайджестах бывает 50-70 ссылок, сейчас ближе к 50
        +1
        Сейчас идёт голосование за интересное RFC — сделать последовательными индексы в массивах, формируемых функциями array_*
        https://wiki.php.net/rfc/negative_array_index

        Вкратце — скорее всего, не попадёт в PHP 7.2, но возможно будет в PHP 8
          +4
          Вышла бета версия yii2 плагина для IDEA/PhpStorm.
          Скачать можно из закладки Beta на https://plugins.jetbrains.com/plugin/9388-yii2-support
          или по этой ссылке .

          Из нового:
          Автокомплит для правил валидации
          Автотип для Yii::createObject

          Прошу помочь с бета тестированием. Баги пишите в гит хаб: https://github.com/nvlad/yii2support
            0
            Прошел PHP-FWdays в Киеве. Обещают поделиться видео через одну/две недели. Скорей всего к следующему дайджесту появятся
              0
              Кто-то может новичку PHP объяснить смысл https://wiki.php.net/rfc/parameter-no-type-variance

              В наследнике появляется возможность забить на тип аргумента в родителе (то есть мы расширяем). В комментах к пуллреквесту срач насчет нарушает ли контрвариация аргумента LSP или нет (вроде как нет). Но у меня вопрос — зачем? Даем пользователям библиотек продолжать использовать свои бестиповые наследники?
                +1
                Я не могу себе придумать практическое применение этого вброса, который почти наверняка будет вести к нарушению LSP и OCP. Хочу схватиться за голову и бегать…
                  0
                  Как раз таки этот «вброс» ведет к частично более полному соблюдению LSP, в этом и суть.

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

                  Сброс тайп-хинта сигнатуры позволит вам реализовать прослойки для управления обратной совместимостью, при этом сигнатуры вы все еще можете определять через phpdoc
                    0
                    Откровенно говоря, Ваше краткое определение LSP тоже заставляет хвататься за голову и…
                      0
                      А я не говорил, что это определение. Это одно из следствий со стороны обсуджаемого вопроса.

                      Если вы хотите строго по определению, то пожалуйста. Представьте, что у вас есть тип T с методом T::f(A $a). И есть тип S extends T с методом, который отличается только отсутствием тайпхинта S::f($a).

                      Если сам код методов идентичен, то если свойство q(T x) верно, то и свойство q(S y) тоже будет верным

                      Таким образом исключение тайпхинта не нарушает LSP, а текущее поведение (фатал парсера) — нарушает. Что подтверждает мое утверждение

                      ведет к частично более полному соблюдению LSP

                        0
                        Во-первых, старайтесь никогда не приводить примеры абстрактных коней в вакууме, так как они за собой влекут точно такие же выводы.
                        Во-вторых, Вы на основе чего программируете? Реализации? Не ведет это «к частично более полному соблюдению LSP». Если сигнатура гласила Razor::shave(Beard $beard), то, для возможности побрить что-то еще, необходимо не глушить сигнатуру в дочернем классе, а пересматривать решение на уровне интерфейса. Почему не, к примеру, Razor::shave(ShaveableInterface $hairySurface)?

                        Вы не подумайте, я на Вас бочку не качу)
                        Просто не в состоянии своё недоумение выразить в полной мере касательно «parameter-no-type-variance». Только и просится фраза «Зачем?!».
                          0
                          Только и просится фраза «Зачем?!»

                          Все началось с какого-то обсуждения в internals где предлагали что-то пофиксить но для того чтобы не ломать обратную совместимость пришлось ваять этот RFC. Все как обычно.

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

                            то если у Razor есть наследники (положим, это библиотека), то изменить сигнатуру указанным образом невозможно, это тут же нарушает LSP для наследников.

                            Если же сделать нового «правильного» наследника, с нужной сигнатурой, то текущая версия PHP кидается ворнингами (т.к. пока мы живем с инвариантами)

                            https://externals.io/thread/514
                            https://wiki.php.net/rfc/return_types#variance_and_signature_validation

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

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

                      0
                      Суть предложения в том, что если у предка указан тайпхинт, то потомок может уже не писать его, он будет взят из предка
                      По крайней мере я так это понял
                        0
                        В комментах указано
                        // This RFC proposes allowing the type to be widened to be untyped aka any
                        // type can be passed as the parameter.
                        // Any type restrictions can be done via user code in the method body.
                        


                        То есть ограничения снимаются и дело не просто в отсутствии варнинга.
                      +1
                      Огромное спасибо!
                        0
                        всегда с удовольствием читаю. спасибо.
                          0
                          Спасибо! Всегда читаю этот дайджест.
                          6 файлов, которые являются валидным PHP — GIF, PDF, JPG, которые можно выполнить как PHP.

                          Примажусь по случаю Как запустить *.jpg как *.php или как предотвратить исполнение загруженных юзером файлов
                            0
                            И про тоже интересно зачем.

                            В примере есть код:
                            class WidgetFactory {
                                function create() {
                                    return new Widget();
                                }
                            }
                             
                            class CustomWidgetFactory extends WidgetFactory {
                                function create() {
                                    $object = new Widget();
                             
                                    return true; //This is an error that cannot be statically analyzed.
                                }
                            }
                            


                            Что мешает указать у метода create (): Widget?
                            Ну помешает вернуть true спецификатор: object, но что делать с остальными объектами, которые несовместимы с Widget?
                            0
                            Подскажите, что в RFC значит Accepted — Pending Implementation?
                              0
                              Одобрен, но ожидает реализации в коде.
                                0
                                То есть object typehinting скорее всего не ждать в 7.2? И вообще не факт, что оно дойдет до реализации в таком виде?
                            +1

                            Надеюсь это будет


                            (params) => expr
                              0
                              тоже подумал, что не плохо было бы сделать как в js, но этот вариант не просто так запихнули на предпоследнюю позицию
                              //пример
                              $param = 5;
                              [
                              	($param) => $param*2
                              ]
                              
                              //может восприниматься парсером так:
                              [$param => $param*2] //[5 => 10]
                              
                              //или так
                              [
                              	function($param) {return $param*2}
                              ]
                              

                              скорее всего выберут fn
                                0

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


                                [($param => $param*2)]
                                  0
                                  это понятно, но магии в php итак хватает, думаю разработчики не пойдут на такой шаг, к тому же это может поломать старые проекты
                                  в общем поживём увидим

                                  а в вашем примере благодаря скобкам что получится массив или функция?
                                    0

                                    Думаю должно быть очевидно что [func]

                                      0
                                      понятно, я неправильно прочёл фразу «хочешь однозначности в массиве? — оберни в скрбки», думал что вы подразумеваете массив, хотя там должна быть функция
                                  0
                                  скорее всего выберут fn

                                  function fn() {
                                      // bad ass
                                  }
                                  
                                  [fn($x) => $x ** 2]

                                  то есть все те же проблемы и еще большая обратная несовместимость. С другой стороны....


                                  [
                                      ($x => $x**2)
                                  ]

                                  уже будет нам говорить что это массив выражений. Скобки неплохой вариант устранения двусмысленности с точки зрения синтаксиса. Вот только парсеру это не помогает особо и этот вариант все равно остается сложным. Ну мол что бы было кошерно надо как-то по первой лексеме понять что у нас тут лямбда.


                                  Потому скорее уж примут function ($x) => $x ** 2.

                                    0
                                    теперь понятно для чего они добавили второй и третий варианты

                                    вообщем будем ждать голосования
                                    0
                                    Потому скорее уж примут

                                    Почему не (params) ==> expr? Оператор ==> еще свободен, да и набирать не сильно сложнее чем =>.

                                      0
                                      еще свободен

                                      1. потому что проблема не в двусмысленности, ее устраняют скобки. Идея в том что бы поменьше операторов добавлять, хотя с другой стороны идея так же что бы одни и те же операторы сохраняли свой смысл вне зависимости от контекста чего не происходит с =>.
                                      2. потому что профита с точки зрения реализации парсера это не добавляет.
                                      3. потому что => лучше чем ==> или ~>.
                                        0
                                        1. Новый оператор как раз в стиле PHP
                                        2. Отследить контекст ему проще?
                                        3. Хз, тильда непривычна, [](params) как-то странно выглядит, а function ($x) => совсем не короткий и оттого бессмысленный вариант. ИМХО, выберут между => и ==>.
                                          0

                                          2 нет. PHP юзает LR(1) парсер, то есть "не двусмысленно" это когда он может понять что он парсит смотря максимум на одну лексему вперед. Так что "просто" это когда у нас есть кейворд в самом начале выражения. Типа fn или function. Тогда парсер запросто все обработает.


                                          В случае с массивом — скобочка будет для него сигналом что он парсит выражение, а не конструкцию в контексте массивов или генераторов, так что тоже все вроде бы ок. Но вот внутри выражения ламбда или нет — это он может догадаться распарсив список аргументов и это надо будет уже делать хитрости.


                                          3 Между этими вариантами нет смысла что либо выбирать на самом деле. fn удобно и хороший компромис но вводит новое ключевое слово (обратная совместимость). function — длинно, хотя по факту не то что бы сильно:


                                          $items = array_map(function ($row) => $this->hydrator->hydrate($row), $rows);
                                          $total = array_reduce($items, function ($sum, $item) => $sum + $item->price());
                                          
                                          // vs
                                          
                                          $items = array_map($row => $this->hydrator->hydrate($row), $rows);
                                          $total = array_reduce($items, ($sum, $item) => $sum + $item->price());
                                            0

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


                                            $items = array_map($row => $this->hydrator->hydrate($row), $rows);
                                            $items = array_map($row ~> $this->hydrator->hydrate($row), $rows);
                                            $items = array_map($row ==> $this->hydrator->hydrate($row), $rows);
                                            $items = array_map(function ($row) => $this->hydrator->hydrate($row), $rows);
                                            $items = array_map(function ($row) { return $this->hydrator->hydrate($row); }, $rows);
                                            $items = array_map(function ($row) { 
                                                return $this->hydrator->hydrate($row); 
                                            }, $rows);
                                              0
                                              это явно не то чего всем хочется.

                                              ну тут как говорится, "хоти в одну руку, а..." Увы приходится идти на компромиссы в пользу простоты сопровождения парсера и отсутствия нарушений обратной совместимости :(

                                                0

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

                                                  0

                                                  Представьте что вас просят добавить фичу, и вы можете реализовать фичу двумя способами:


                                                  • удобный пользователю, то что они хотят, но это усложнит реализацию на порядок и вам придется ее поддерживать годами (дорого)
                                                  • чуть менее удобный пользователю, зато намного более простой с точки зрения реализации, не требующий кардинальных изменений. (дешево)

                                                  Да, второй вариант всем не понраву, но он решает проблемы какого-то процента пользователей. Либо же не делать ничего. Как бы вы поступили?

                                                    +1
                                                    А Вы, как бы поступили?)

                                                    Лично на мой взгляд, в php достаточно фич из разряда makeSomethingLikeFooButInAnotherWay. Если можно удержаться от «двусмысленности», то лучше так и поступить.
                                                      0

                                                      Выбрал бы первый вариант (==> отношу к нему же) — кривая фича вообще никому не нужна (их тут и так слишком много), если это что-то ломает — есть следующая мажорная версия, а если это слишком сложно — не стал бы делать.

                                                        0
                                                        Выбрал бы первый вариант

                                                        то есть "то что они хотят, но это усложнит реализацию на порядок и вам придется ее поддерживать годами (дорого)".


                                                        а если это слишком сложно — не стал бы делать.

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


                                                        Но все еще есть процент людей которым фича нужна даже с "лишним" кейвордом в начале.


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

                                                          0
                                                          то есть

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


                                                          Но все еще есть процент людей которым фича нужна даже с "лишним" кейвордом в начале.

                                                          Она была нужна давным давно, сейчас смысла в ней не очень много на самом деле. Но вообще дело не в лишнем function, а в том что эта запись совсем не короткая, глядишь там еще и use придется писать, а то сложно же по другому сделать...

                                                            0
                                                            нежелание сделать нормально сразу это обычная лень.

                                                            вам надо сделать в парсере гиганский кастыль который сможет чекать на N лексем вперед. Я не считаю что это "сделать нормально".


                                                            сейчас смысла в ней не очень много на самом деле.

                                                            аргументируйте. Есть альтернативы?


                                                            глядишь там еще и use придется писать

                                                            Почитайте RFC. В частности:


                                                            importing used variables from the outer scope implicitly

                                                            а то сложно же по другому сделать...

                                                            это как раз таки сделать не сложно. Сложно с парсером без кейворда в начале выражения.

                                                              0
                                                              аргументируйте. Есть альтернативы?

                                                              Что именно аргументировать? Анонимные функции есть давным-давно, короткий синтаксис всего лишь сахар, который первый раз был предложен пару лет назад (там кстати даже pr был...), за это время все уже привыкли к стандартному синтаксису + явный use имеет свои преимущества.

                                                                +1

                                                                Есть большая разница между "анонимными функциями" и "функциональными выражениями". В JS мире эту разницу тоже не сильно понимают потому пихают arrow functions бездумно.


                                                                явный use имеет свои преимущества.

                                                                которые не имеют смысла в этом контексте.


                                                                за это время все уже привыкли к стандартному синтаксису

                                                                примерно так же про синтаксис массивов говорили.

                                                                  0
                                                                  Есть большая разница между "анонимными функциями" и "функциональными выражениями".

                                                                  И в чем же эта разница?


                                                                  примерно так же про синтаксис массивов говорили.

                                                                  А вот его как раз реализовали правильно :)

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

                                Самое читаемое