13 марта в 00:15

PHP-Дайджест № 104 – интересные новости, материалы и инструменты (1 – 12 марта 2017)



Предлагаем вашему вниманию очередную подборку со ссылками на новости и материалы.
Приятного чтения!


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



PHP


  • RFC — Deprecation of fallback to root scope — На данный момент в случае, если функция или константа не найдены в пространстве имен, будет попытка найти сущность с таким именем в глобальном пространстве. Предлагается объявить функциональность устаревшей и бросать ошибку уровня Notice:

    Undefined function \My\NS\strlen(), assumed \strlen()
    Undefined constant \My\NS\PHP_VERSION, assumed \PHP_VERSION
    

Инструменты



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



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



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

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

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

Комментарии (33)

  • +1
    Огромное спасибо за дайджесты и отдельное спасибо за наш stacker — не забыли, приятно.
  • 0
    antanas-arvasevicius/enumerable-type — Строго типизированная реализация Enum.

    Сколько себя помню :) всегда люди пытались реализовать Enum в PHP. Даже я пару раз пытался. Эта реализация выглядит лучше многих, но опять ограничения, прежде всего с десериализацией :( Что не так с PHP, что нельзя впилить такой тип в ядро?

    • 0

      Посмотрел код проекта. Оказалось все еще хуже чем я думал. Список доступных значений для ENUM получается с помощью рефлексии наследующего класса. Метод valueToString вообще мастерский говнокод.


      Я ENUM в PHP рассматриваю как ValueObject и отношусь к нему соответствующе. В сущностях храню сам объект, а не его значение, список доступных значений описываю в явном виде и добавляю методы необходимыми для бизнеслогики.

      • 0

        enum — ValueObject или значения типа enum — ValueObject?

        • 0

          не очень понял вопрос.


          Значение, для свойства объекта доменной области, может быть перечисление (enum). Для контроля за этим перечислением его удобно описать в виде объекта значения (ValueObject). Получается что-то вроде:


          $my_type = TicketType::priority();
          if ($ticket->type()->equals($my_type)) {
          }

          или так


          if ($ticket->type()->isPriority()) {
          }
          • 0

            Понял. Значения типа Enum — ValueObject.

      • 0

        все реализации ENUM в PHP через рефлексию. Так как у вас обычно классы ENUM условно маленькие а результат операции разумно кешируется во внутреннем поле, то накладные расходы весьма малы

        • 0

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


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

          • 0
            Можно реализовать все тоже самое кеширование и прочие радости без рефлексии

            это я не понял вообще


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

            Это почему нельзя? что мне помешает?


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


            Я вот пользуюсь реализацией myclabs/php-enum и там указываются константы.

            • 0
              Это почему нельзя? что мне помешает?

              Пример на основе того же myclabs/php-enum. Я добавляю человеческое описание для вывода на frontend


              class Action extends Enum
              {
                  const VIEW = 'view';
                  const EDIT = 'edit';
              
                  // константы воспринимаются как варианты значения
                  // формат предназначен для перевода
                  const TITLE_VIEW = 'acme.demo.action.view';
                  const TITLE_EDIT = 'acme.demo.action.edit';
              
                  // можно использовать для radio/checkbox/select
                  public static function choices()
                  {
                      return [
                          self::VIEW => self::TITLE_VIEW,
                          self::EDIT => self::TITLE_EDIT,
                      ];
                  }
              
                  public function title()
                  {
                      return static::choices()[$this->getValue()];
                      // можно былоб писать проще и не создавать метод choices,
                      // но тогда такую конструкцию тяжелее использовать для radio/checkbox/select
                      //return 'acme.demo.action.'.$this->getValue();
                  }
              }

              Можно не добавлять префикс для значения, но тогда теряется контекст. Одно и то же значение в разном контексте может по разному переводится.


              Пример на основе antanas-arvasevicius/enumerable-type. Я добавляю свои методы для бизнеслогики


              class Action extends EnumerableType
              {
                  final public static View()
                  {
                      return static::get('view');
                  }
              
                  final public static Edit()
                  {
                      return static::get('edit');
                  }
              
                  // воспринимается как вариант значения
                  final public static equals(Action $action)
                  {
                      return $this->id() === $action->id();
                  }
              }
              • 0

                Чёт я запутался… вы пишете:


                … случае использования подхода с рефлексией этого сделать нельзя.

                я с этим не согласился и потом вы мне приводите именно пример что можно! Что то пошло не так?


                в случая же 2 вы как то сразу схитрили. Зачем метод делать final public static? Да именно такие, и только такие, методы воспринимаются как значения. Ну ограничение той реализации. Точно так же как в myclabs/php-enum константы. Что особо не влияет на саму возможность делать


                методы необходимые для бизнес логики и человеческое описание для вариантов значения для вывода на frontend.
                • 0
                  я с этим не согласился и потом вы мне приводите именно пример что можно! Что то пошло не так?

                  Как раз я привожу пример что нельзя. myclabs/php-enum воспринимает константы с описанием как варианты значения. Тоесть метод Action::toArray() вернет TITLE_VIEW, что не корректно. Можно объявить TITLE_VIEW как не константу, но это все ухищрения чтоб угодить инструменту, а не бизнесу.


                  Хорошее решение этой проблемы предлагает библиотека marc-mabe/php-enum, которая воспринимает только публичные константы, но нужен PHP 7.1.


                  в случая же 2 вы как то сразу схитрили. Зачем метод делать final public static?

                  Да, схитрил. Естественно. Потому что с точки зрения бизнеса не должно быть final и не final методов. Весь объект должен быть final. А если инструмент требует помечать методы как final, то я вынужден и остальные методы тоже помечать как final, чтоб защитить класс.


                  Я хочу сказать, что используя подход с рефлексией, мы получаем автоматизацию генерации списка доступных значений (Action::choices()), и в тоже время некоторые ограничения на использование методов или констант.
                  Создав один метод Action::choices() вручную, мы сохраним все те же самые функции, но не будем иметь ограничений накладываемых рефлексией.

                  • 0

                    А… да по поводу непонимания мой косяк. Извиняюсь был невнимателен. День тяжелый.


                    Но всё же.


                    используя подход с рефлексией, мы получаем автоматизацию генерации списка доступных значений

                    Да, собственно я с этого начал. И да, вы правы ограничения есть, однако это не это не равно утверждению "с рефлексией этого сделать нельзя".

                    • 0
                      И да, вы правы ограничения есть, однако это не это не равно утверждению "с рефлексией этого сделать нельзя".

                      Если ограничения не позволяют нам что-то сделать, значит это сделать нельзя. Разве нет?
                      Если ограничения накладываются в результате использования рефлексии, то значит "с рефлексией этого сделать нельзя".
                      Вроде все логично.


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

                    • +1

                      Попробовал реализацию через рефлексию. Оказалось действительно в чем-то удобнее. Спасибо что просветили.


                      Проблему с человеческим описанием в myclabs/php-enum можно решить так:


                      final class Action extends Enum
                      {
                          const VIEW = 'view';
                          const EDIT = 'edit';
                      
                          // можно использовать для radio/checkbox/select
                          public static function choices()
                          {
                              $choices = [];
                              foreach (self::values() as $value) {
                                  $choices[$value->getValue()] = (string) $value;
                              }
                      
                              return $choices;
                          }
                      
                          public function __toString()
                          {
                              return 'acme.demo.action.'.strtolower($this->getKey());
                          }
                      }

                      Но вот решил я сравнить производительность реализации через рефлексию и с явным описанием вариантов значений и получилось что рефлексия в 3-4 раза медленнее в зависимости от версии php.


                      $ php tests/benchmark.php 100000
                      Reflection enum: 1.25 MiB - 14079 ms
                      Reflection enum no magic: 1.25 MiB - 11286 ms
                      Explicit enum: 1.25 MiB - 3221 ms

                      Тест no magic это тест без использования магических функций __call() и __callStatic() и даже он оказывается медленнее в 3 раза.
                      Отсюда делаем вывод. За удобство нужно платить.

                      • 0

                        Хотелось бы взглянуть на бенчмарк полностью.

                        • 0

                          Вангую что нет кэша для рефлексий.


                          В целом же профит от enum-ов в возможности проверять по типам. Без этого смысла заморачиваться нет.

                          • +1

                            огорчу. кеш есть.


                            Для сравнения добавил в тест:



                            Результат:


                            $ php tests/benchmark.php 100000
                            Reflection enum: 1.25 MiB - 10401 ms
                            Reflection enum no magic: 1.25 MiB - 11382 ms
                            MyClabs enum: 1.25 MiB - 18531 ms
                            MarcMabe enum: 1.25 MiB - 11422 ms
                            MarcMabe enum no magic: 1.25 MiB - 11278 ms
                            HappyTypes enum: 1.50 MiB - 6992 ms
                            Explicit enum: 1.50 MiB - 2848 ms

                            билд и сорцы.

            • 0

              Я кинул пару PR в myclabs/php-enum, может вам пригодится

  • +2

    Отличная подборка в этот раз. Нашёл для себя новые штуки. Одно только огорчило:


    Двухфакторная аутентификация в Laravel с помощью SMS (Twilio)

    Не стоит рекламировать SMS в качестве фактора аутентификации. Дырявый канал.

  • +2
    https://wiki.php.net/rfc/fallback-to-root-scope-deprecation

    Самый странный RFC который я видел, это кому то реально нужно?
    • +1

      Как я понимаю, сильно упростит создание автозагрузчиков функций.

      • 0

        А нам придется перед каждой функцией и константой писать слеш. Этож сколько проектов начнет заваливать логи нотисами, а потом и вовсе упадет. Тогда уж и для функций языка нужно вводить неймспайсы.

  • 0

    -

  • 0

    Автору Maxlab/stacker большое спасибо, недавно начал осваивать Docker, а тут все и сразу да еще и с виде о описанием.

    • 0
      На здоровье!) Ролики, только нужно переписать будет, на скорость делал, с первого раза — гомно конечно.
  • +1

    justinrainbow/json-schema не очень удобно использовать. thephpleague/json-guard как-то поприятнее.

    • 0
      Спасибо, добавил в подборку
  • +3
    Laravel Forge API — API сервиса теперь задокументировано. Имеется неофициальный клиент mpociot/blacksmith.

    Пользуясь случаем попиарю свою реализацию API SDK — https://github.com/tzurbaev/laravel-forge-api :)

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