• PHP-Дайджест № 151 (25 февраля – 11 марта 2019)
    +1

    От to*() функций ожидаешь, что они любой треш преобразуют в соответствующий тип. Поэтому возвращение null мне кажется странным. Теряется смысл этих функций, потому что придется каждый раз дополнительно делать проверку на null. Тогда уж кидать TypeError, по аналогии с https://wiki.php.net/rfc/consistent_type_errors

  • Composer для самых маленьких
    0

    Там теперь достаточно подключить профиль к GitHub и дать соответствующие права. Если
    вы авторизовались через GitHub давно, как я, то надо просто разлогиниться и войти снова, тогда вам предложат доставить разрешения. После этого все библиотеки будут обновляться автоматически

  • Как я боролся с бесплатным хостингом и Composer
    0

    Я к тому, что зачем обновлять зависимости на сервере?
    Во-первых, вы можете нарваться на обновление, которое поломает приложение. Подразумевается обновление зависимостей на машине разработчика, коммит composer.lock и уже выполнение composer install на сервере. Т.о. вендоры будут идентичными.
    Во-вторых, это может отожрать много памяти, что даже ini_set("memory_limit", -1); не поможет, т.к. ее не хватит физически (мы же все-таки о бесплатном хостинге говорим)

  • Как я боролся с бесплатным хостингом и Composer
    +3
    //По умолчанию composer update, так как он используется чаще чем ?command=install

    А зачем на хостинге запускать composer update?

  • Composer для самых маленьких
    0
    Да, это есть в документации:
    Note: This feature has severe technical limitations, as the composer.json metadata will still be read from the branch name you specify before the hash. You should therefore only use this as a temporary solution during development to remediate transient issues, until you can switch to tagged releases. The Composer team does not actively support this feature and will not accept bug reports related to it.

    Отчасти это послужило «пинком под зад» в расстановке semver-тегов для своих внутренних компонтентов
  • За что я ненавижу Eloquent ORM
    0
    Прототип он в том смысле, что обычно для продакшена после этих действий нужны всякие мелкие доработки — валидация, интерфейс, дополнительные действия в логике.

    Если потом придет задача, к примеру:


    • раскрашивать строку таблицы цветом в зависимости от статуса заказа
    • выводить не таблицей, а списком
    • какие-то даты выводить в формате php:Y-m-d, какие-то в intl:yyyy-MMMM-dd
    • ...

    Не проще в таком случае выкинуть виджет и сделать все обычным foreach?
    Да, вижу, что у него много опций и, скорее всего, они покрывают все юзкейсы, но в итоге получается все такой же "километровый конфиг".


    Ну я бы не назвал это «немного») Сколько здесь вручную написанных функций и классов, да еще и магические аннотации. Это ведь все код, который надо поддерживать. И сколько неявного кода надо учитывать, который выполняется «где-то там».

    Не так много:


    • OrderController — и там и там он был частично сгенерирован
    • Сущности — и там и там, только у вас migration-first, у меня наоборот, создаются модели, а миграции генерируются
    • Модель для поиска — и там и там (да, у вас она сгенерировалась, но по факту код был полностью изменен и добавлены те же публичные поля, что и у меня)
    • Форма для поиска — и там и там (только у меня через класс, у вас через шаблон)
    • Логика поиска — у меня в репозитории, у вас в модели (по количеству кода — ± одинаково)

    Забавно, что в итоге "кода, который нужно поддерживать"
    (git ls-tree -r master --name-only | wc -l)
    в Symfony — 63 файлов
    в Yii — 173


    да еще и магические аннотации

    Тоже так думал вначале, но сейчас понимаю, что это очень удобно, тем более что поддержка аннотаций в PhpStorm есть


    Пример

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

  • За что я ненавижу Eloquent ORM
    +1
    Challenge accepted =)
    Получилось, немного посложнее, чем у вас, но надо сказать, что это уже не прототип, а вполне себе рабочий вариант.
    При этом не заметил каких-то ограничений, которые накладывает Doctrine
  • За что я ненавижу Eloquent ORM
    0
    Попробовал сделать аналогичный проект на symfony/doctrine
    Не эксперт в прототипировании, но мне кажется плюс-минус одинаково?
  • Используем аннотации в PHP по максимуму
    0

    Почему используется именно sunrise/http-router?


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

  • MVC + Scenario против Толстых Контроллеров
    0

    Хотелось бы увидеть код. Основной вопрос: как быть с условиями? К примеру, если валидация прошла успешно, то создаем пользователя и редиректим на страницу просмотра, если нет — то рендерим форму с ошибками. В ваших примерах все линейно:
    'UserModel > UserViewModel > view, hello'

  • MVC + Scenario против Толстых Контроллеров
    0
    А можете проиллюстрировать как в вашем подходе будет выглядеть создание/редактирование?
  • Пошаговое создание бандла для Symfony 4
    0
    тем более, что они автоматом ставятся в любой проект, который использует Symfony 4

    Речь идет о новых проектах, использующих flex. Если кто-то обновил свое приложение с 3.4 до 4 и захочет поставить ваш бандл, он очень не обрадуется появившемуся flex, который внезапно переопределит все конфиги :)


    а вот sensio/framework-extra-bundle тут действительно нужен. Он необходим для роутинга через аннотации.

    Не рекомендуется использовать такого рода "магию" в бандлах. Равно как и использование автовайринга и автоконфигрирования: Best Practices for Reusable Bundles


    Services should not use autowiring or autoconfiguration. Instead, all services should be defined explicitly.
  • Пошаговое создание бандла для Symfony 4
    +3

    Раздел с созданием скелета бандла — спорный. Гораздо проще использовать стандартный composer init, т.к. в вашем случае удалить придется гораздо больше, чем создать. К тому же вы добавляете лишние зависимости (по сути бандл должен зависеть только от symfony/framework-bundle, как минимум symfony/flex, sensio/framework-extra-bundle и symfony/lts — лишние)


    Ну а в остальном создание ничем не отличается от других версий Symfony

  • Пошаговое создание бандла для Symfony 4
    +2
    Вместо `CompiledPass` проще использовать `!tagged`: symfony.com/blog/new-in-symfony-3-4-simpler-injection-of-tagged-services
  • PHP 8: чего ждать. Письмо Зеева Сураски
    0
    Мне кажется они там придумывают новые слои абстракции совершенно не задумываясь нужно ли это комуто вообще.

    А можете пример привести? По-моему конечного пользователя все эти абстракции не касаются

  • Shopkeeper 4.0 — Интернет-магазин на Symfony + Angular + MongoDB
    +1

    От autoescape можно избавиться


    {% autoescape false %}
        {{ renderOutputTypeChunk(currentPage, fields, 'header', 'page_') }}
    {% endautoescape %}

    https://twig.symfony.com/doc/2.x/advanced.html#automatic-escaping


    new TwigFunction('renderOutputTypeChunk', [$this, 'renderOutputTypeChunkFunction'], [
        'is_safe' => ['html'],
    ]),

    Чтобы получать инстанс twig вместо передачи контейнера лучше


    new TwigFunction('renderOutputTypeChunk', [$this, 'renderOutputTypeChunkFunction'], [
        'needs_environment' => true,
    ]),

    Тогда он будет передаваться первым параметром:


    public function renderOutputTypeChunkFunction(\Twig_Environment $environment, $itemData, $fieldsData, $chunkName, $chunkNamePrefix = '')
    {
  • Роскомнадзор, кажется, разделил выгрузку на две части для конспирации
    0
    Не обязательно иметь ключи шифрования, чтобы получить доступ к переписке
  • Простое объяснение принципов SOLID
    0
    Забавно вы выбираете цитаты :)
    > Во-вторых, если сервису нужно что-то декодировать или интерпретировать, то это тоже дополнительная отвественность

    Но сервис _в любом случае_ эту ответственность несет. Не может не нести.

    А ответ на самую интересную часть так и не дали:
    не говоря о возможных дополнительных зависмостях типа json-декодера.

    Как передавать зависимости, которые необходимы для обработки зависимостей, которые, в случае передачи уже сконфигурированных данных не нужны?
  • PHP-Дайджест № 131 (13 – 27 мая 2018)
    0

    Основная проблема — dev-зависимости на проде. В случае, если используется assetic, придется ставить java, для webpacknode.js.


    Мы эту проблему решили в рамках `Capistrano`
        task :webpack_build do
          run_locally do
            execute "./node_modules/.bin/encore production"
          end
        end

    и


      task :upload do
        release_path = fetch(:release_path)
        web_path = fetch(:web_path)
    
        on roles(:web) do
            execute :mkdir, "-pv", "#{release_path}/#{web_path}/build"
            upload! "#{web_path}/build", "#{release_path}/#{web_path}", :recursive => true
        end
      end
  • Внедрение предметно-ориентированного проектирования в PHP
    0

    Судя по источнику перевода, это у автора стиль такой, а не у переводчика

  • Выбираем Yii2 или laravel
    0
    Помельче: хелперы для работы с конфигами, или какими-то данными.

    Что вы под этим имеете в виду?

  • Выбираем Yii2 или laravel
    +1
    Это совсем не то, что делает Yii.
    Laravel тоже так не умеет, на сколько я помню, но его вы почему-то включили в обзор
  • Выбираем Yii2 или laravel
    0

    https://github.com/symfony/website-skeleton/blob/4.0/composer.json


     "require": {
            // ...
            "symfony/webpack-encore-pack": "*",
            // ...
        },
        "require-dev": {
            // ...
            "symfony/maker-bundle": "^1.0",
            // ...
        },
  • Выбираем Yii2 или laravel
    0
    В Симфони есть генератор готовых интерфейсов?

    https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html


    Встроенный удобный сборщик фронтенда как у Ларавел?

    https://symfony.com/doc/current/frontend.html

  • Выбираем Yii2 или laravel
    –1
    Зарегистрировать UserInterface из секьюрити в контейнере, чтобы потом он мог резолвиться через автовайринг или парам резолвинг. Можно сделать, но это оверинжинеринг

    А в чем именно оверинженеринг? Простенькая фэктори + строчка в конфиге


    Symfony\Component\Security\Core\User\UserInterface:
        factory: ['@App\UserProvider', 'get']
  • Используем PHP по назначению
    +4

    <?= — это не short-tag, а алиас на <?php echo, <? — вот short-tag
    http://php.net/manual/ru/language.basic-syntax.phptags.php


    Тег <?= доступен всегда, вне зависимости от настройки short_open_tag.
  • Yii 2.0.14
    +1

    Не рассматриваете вариант выпустить хотфикс, где отключите эту возможность? Все-таки минорный релиз не должен ломать BC

  • Операция «Ы» и новая библиотека ABI
    0

    Попытался поставить, но не заработало. Полагаю, потому что APIURL захардкожен (http://grigorov.com/abi/index.php)

  • Диалоговый телеграм бот на PHP
    0

    У меня в свое время получилось что-то вроде этого: https://github.com/BoShurik/telegram-bot-example. Отличие в том что я запоминаю не только команду, но и данные которые ввел пользователь, т.о. можно, например, заполнить заявку пошагово

  • Диалоговый телеграм бот на PHP
    +1

    Не скажу за автора, но я отказался из-за странной системы команд: невозможно пробросить свои зависимости в конструктор, как следствие — сложно интегрировать с существующим сайтом/приложением. Это больше похоже на фреймворк для создания бота, чем на библиотеку :)

  • Управление зависимостями в PHP
    0

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


    Ну и при подходе с композером никто не заставляет ждать цепочку "issue — fix — tag", всегда можете форкнуть и использовать форк до исправления ошибки.

  • PHP-Дайджест № 119 (10 – 29 октября 2017)
    0

    Зачем хранить пароли в одном файле/файлах, а не в конкретных переменных окружения?
    Хотя бы поэтому: https://twitter.com/o_cee/status/892306836199800836

  • PHP-Дайджест № 119 (10 – 29 октября 2017)
    0
    Всё, что вы должны знать о переменных окружения в PHP:
    Тенденция иметь только одну переменную, как APP_CONFIG_PATH, и читать её через '%env(json:file:APP_CONFIG_PATH)%' для меня выглядит как заново изобретать старый добрый parameters.yml

    Увы но так нельзя. Точнее в этом мало смысла, т.к. у нас будет доступ ко всему конфигу сразу, а не к конкретному ключу
    https://github.com/symfony/symfony/issues/24674#issuecomment-340267955

  • Использование событийной модели в Doctrine 2 + Symfony 3
    0

    kernel.terminate не вызывается в консоле. Конкретно в этом случае это не важно, но если, к примеру, данные будут обновляться по крону из какой-нибудь API, то как тогда?

  • Быстрый пул для php+websocket без прослойки nodejs на основе lua+nginx
    +1

    LuaJit на 7 месте с 8 секундами

  • Синглтоны и общие экземпляры
    0
    AwesomeAbility в моем примере далека до God-object, хотя она и правда имеет многовато обязаностей. Но слишком много обязаностей не всегда означатает God-object.

    Если сейчас он таким не является, то в будущем — весьма вероятно, "если вдруг еще понадобится влиять на животных"


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

    DI контейнер. Если говорить о PHP и Symfony в частности, то даже конфигурировать почти не придется. Думаю в других языках есть аналоги.


    Стейт и отображение решил бы так:


    Код
    class Unit
    {
        private $abilites;
    
        public function activateStimPack(EventDispatcher $dispatcher)
        {
            $ability = new StimPackAbility($this, 10 /* seconds */);
            $dispatcher->dispatch(Abilities::STIM_PACK_ACTIVATE, $ability);
        }
    
        public function deactivateStimPacks(EventDispatcher $dispatcher)
        {
            $abilities = $this->getAbilities();
            foreach ($abilities as $ability) {
                $dispatcher->dispatch(Abilities::STIM_PACK_DEACTIVATE, $ability);
            }
        }
    }
    
    class StimPackListener
    {
        public function __construct(EventDispatcher $dispatcher, GameTimer $timer)
        {
    
        }
    
        public function onActivate(StimPackAbility $ability)
        {
            $ability->getUnit()->addAbility($ability);
            // Add other effects
            $timer = $this->timer->tick(function() use ($ability){
                $ability->decSeconds();
    
                if ($ability->getSeconds() == 0) {
                    $this->dispatcher->dispatch(Abilities::STIM_PACK_DEACTIVATE, $ability);
                }
            });
    
            $ability->setTimer($timer);
        }
    
        public function onDeactivate(StimPackAbility $ability)
        {
            $ability->getUnit()->removeAbility($ability);
            // Remove other effects
            $ability->getTimer()->destroy();
        }
    }

    У вас вместо одной супер-абилити будет множество эвентов, которые просто влияют на юнит

    В моем подходе эвент = абилке. Я ее рассматриваю не как объект, а как процесс. В текущем варианте вполне можно их сохранять и выводить.


    Кто отвечает за применение эффектов в вашем подходе? Сама абилка или юнит к которому она добавлена?
    И как активируются AwesomeAbility из вашего предыдущего примера? Ведь по условию ее эффекты распространяются не только на того, кто ее использовал


    На самом деле не претендую на правильность моего подхода. Просто решил посмотреть как он ляжет на вашу задачу. И вроде пока узких мест не вижу.

  • Синглтоны и общие экземпляры
    +1
    Я не совсем понял, как вы предлагаете создавать эту комплексную абилку?

    $this->getEventDispatcher()->dispatch(Ability::AWESOME, new AwesomeAbilityEvent($subject, $target));

    Вместо того, чтобы создать одну AwesomeAbility — создать 5 подабилок? А что это даст?

    Это не пять абилок, это пять обработчиков одной абилки. Таким образом решаем проблему Single Responsibility. В вашем варианте у вас получается God-object

  • Синглтоны и общие экземпляры
    0

    Я бы через Event Dispatcher сделал:


    Как-то так
    <?php
    
    abstract class AbstractAwesomeAbilityListener
    {
        public function __construct(
            GameTime $time, 
            PlayerStorage $storage, 
            GameConfig $config
        )
        {
            // ...
        }
    
        abstract protected function doActivate();
    
        public function onActivate()
        {
            if (!$this->isAllowed()) {
                return;
            }
    
            $this->doActivate();
        }
    
        /**
         * @return bool
         */
        protected function isAllowed()
        {
            // ...
        }
    }
    
    class CrewListener extends AbstractAwesomeAbilityListener
    {
        public function __construct(
            CrewContainer $container, 
            GameTime $time, 
            PlayerStorage $storage, 
            GameConfig $config
        )
        {
            parent::__construct($time, $storage, $config);
    
            // ...
        }
    
        protected function doActivate()
        {
            // ...
        }
    }
    
    class PlantsListener extends AbstractAwesomeAbilityListener
    {
        public function __construct(
            CrewContainer $container, 
            GameTime $time, 
            PlayerStorage $storage, 
            GameConfig $config
        )
        {
            parent::__construct($time, $storage, $config);
    
            // ...
        }
    
        protected function doActivate()
        {
            // ...
        }
    }
    
    class EnemyListener extends AbstractAwesomeAbilityListener
    {
        public function __construct(
            CrewContainer $container, 
            GameTime $time, 
            PlayerStorage $storage, 
            GameConfig $config
        )
        {
            parent::__construct($time, $storage, $config);
    
            // ...
        }
    
        protected function doActivate()
        {
            // ...
        }
    }
  • Вебсокеты на php. Выбираем вебсокет-сервер
    +1

    И тут мы пришли к тому, что вам писал mayorovp. На один слой больше за счет такой вот обертки.
    Либо имеем нарушение принципа единственной ответственности, когда вебсокет сервер у нас еще занимается парсингом вывода и перезапуском упавших процессов.

  • Вебсокеты на php. Выбираем вебсокет-сервер
    0
    Мне кажется или мы про Яблоки vs. Апельсины? :)

    Весьма вероятно :)


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