• Как правильно писать тесты PHPUnit под ООП?

    Вам не надо тестировать приватные методы.
    Но как же тогда быть, вы скажете?
    Публичные методы используют эти приватные методы, так и проходит тестирование.
    Из этого вытекает, что класс должен быть небольшим и выполнять только одну задачу. Поэтому его приватные методы будут всегда задействованы при тестировании публичных.
    Но вы скажете, что у вас там в публичных методах обращения к базе данных и внешним API, как же тут быть?
    А быть тут просто: все зависимости вашего класса должны включаться в качестве аргументов конструктора, и через использование интерфейсов в аргументах. (Dependency Injection)
    Таким образом в тесте все зависимости класса заменяются теми же моками, и вы легко тестируете не просто сферического корня в вакууме (приватный метод), а именно то, что и нужно тестировать: функциональность самого класса, а не его частей, потому что в OOP именно класс является как бы атомом функционала.
    Но... если вам всё же таки очень надо, то можно это сделать при помощи рефлексии:
    Хорошей практикой является использовать всегда protected вместо private.
    Пишете себе такую вот утилиту:
    class PHPUnitUtil
    {
      public static function callMethod($obj, $name, array $args) {
            $class = new \ReflectionClass($obj);
            $method = $class->getMethod($name);
            // $method->setAccessible(true); // если PHP старше 8.1.0
            return $method->invokeArgs($obj, $args);
        }
    }


    И используете ее в тестах
    $returnVal = PHPUnitUtil::callMethod(
                    $this->object,
                    '_nameOfProtectedMethod', 
                    array($arg1, $arg2)
                 );


    Есть ещё вариант.
    // Оригинальный класс
    class Foo {
      protected function stuff() {
        // secret stuff, you want to test
      }
    }
    
    // Класс для тестов
    class SubFoo extends Foo {
      public function exposedStuff() {
        return $this->stuff();
      }
    }
    Ответ написан
    3 комментария
  • Можно ли конвертировать/сохранить динамически сгенерированную js страницу в статичный html-файл?

    Есть банальные расширения для браузера
    https://chromewebstore.google.com/detail/save-page...
    https://chromewebstore.google.com/detail/webscrapb...

    А так же целое десктопное приложение и ещё одно расширение для браузера
    https://github.com/webrecorder/webrecorder-desktop
    https://chromewebstore.google.com/detail/webrecord...
    Ответ написан
    Комментировать
  • Чем занимаются Middle Frontend разработчики?

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

    Т.е. если вы в объявлении пишете, что ищете миддла, то вы сразу обговариваете категорию его зарптаты в вашей компании. И когда вы его наймёте, он не будет сильно сокрушаться, когда узнает, что сеньоры получают больше него.
    Ответ написан
    Комментировать
  • Как создавать, принимать и обрабатывать socket?

    1. Вебсокеты - это сложновато.
    2. Вебсокеты на PHP - вдвойне сложно. Проблема в том, что PHP задуман как скриптовый язык, т.е. скрипт выполняется заканчивает свою работу. А вебсокет - это постоянное соединение, т.е нам надо, чтобы программа постоянно крутилась в фоне. Вебсокеты можно реализовать на PHP, но, как персонально мне кажется, проще будет выучить Go )) , или же, как в ответе уважаемого Артём , сделать сервер на ноде.
    3. Если ваш чат не такой супер-функциональный, как чат в мессенджерах, то вместо вебсокетов можно обойтись SSE (Server Sent Events). SSE так же требует постоянного соединения, но всё работает через HTTP, и это ну прямо намного проще. Единственный недостаток - это то, что SSE работает только в одну сторону: от сервера в браузер. Т.е. запросы из браузера можно получать обычным POST запросом, а отдавать обратно информацию уже через SSE.

    С SSE есть два пути:
    1. Написать сервер самому, используя какую-то простую библиотеку вроде этой https://github.com/hhxsv5/php-sse
    2. Но я бы сделал ещё проще. Есть такой великолепный проект под названием Mercure https://mercure.rocks
    Это отдельный сервис на Go, задача которого как раз поддерживать SSE соединение и отправлять сообщения в браузеры. Сервис сидит в фоне, а браузеры подписываются на события через EventSource буквально в три строчки, как описано тут https://mercure.rocks/docs/getting-started
    Прелесть этого в том, что для того, чтобы отправить сообщение всем браузерам из кода на PHP, вам надо просто сделать обычный POST запрос на специальный адрес этого сервиса Mercure с телом самого сообщения и его id. Т.е. вам не надо делать никаких долгоживущих процессов на PHP, всё будет работать как раньше.

    Т.е. подытожим:
    - Браузеры пользователей подписываются на события в Mercure
    - Пользователь 1 отправляет текстовое сообщение обычным POST запросом на обычный PHP сайт.
    - PHP сайт получает этот POST запрос, определяет, что его надо отправить Пользователю 2, и отправляет соответствующее сообщение обычным POST запросом в сервис Mercure
    - Mercure отправляет сообщение Пользователю 2 через SSE, на которые он подписан.
    - Сообщение появляется у него на страничке
    Ответ написан
    5 комментариев
  • Где искать верстальщиков и бекендеров?

    На этот вопрос нет чёткого ответа.
    1. Связи - вот главный рецепт успеха в IT. Это лучший способ найти исполнителя.
    2. Если связей нет, то гарантированный, но дорогой и неприятный способ - это заключение контракта с какой-то галерой. Тут главное прописать все обязательства и ответственность сторон. Требовать исполнения, но и самому исполнять.
    3. Остальные способы как раз и сопряжены с теми рисками, что вы описали. Вы лишь должны принять эти риски, заложить их в сроки проекта, и не ждать чуда из места, где его не может быть. Что могу посоветовать - если нашли толкового исполнителя, то берегите его, заплатите вовремя и столько, сколько договаривались, не требуйте крупных бесплатных доработок. Такой исполнитель - большая редкость, и это добавка в список ваших связей, и в следующий раз вы начнёте уже с п.1...
    Ответ написан
    Комментировать
  • Как получить переменную из callback php?

    Можно использовать замыкание. Тут фишка в том, что надо использовать в замыкании не обычную строковую переменную, а объект, потому что строковая переменная будет передана в виде копии, и не получится её изменить.
    В коде я заменил класс Client на его мок.

    class Client {
        public function miniTicker(array $callbacks) {
            foreach ($callbacks as $key => $callback) {
                $conn = 'aaaaa';
                $msg = 'msg-'.$key;
                $callback($conn, $msg);
            }
        }
    }
    
    class Message {
        public array $messages = [];
    
        public function addMessage(string $msg) {
            $this->messages[] = $msg;
        }
    }
    
    $message = new Message();
    
    $callbacks = [
        'message' => function ($conn, $msg) use ($message) {
            $message->addMessage($msg);
            
        },
        'ping' => function ($conn, $msg) use ($message) {
            $message->addMessage($msg);
        }
    ];
    
    $client = new Client();
    $client->miniTicker($callbacks);
    var_dump($message->messages);


    В результате в конце у нас выводятся все сообщения
    https://onlinephp.io/?s=tVK7boQwEOyR-IctkDDSkR8gR4...
    Ответ написан
    5 комментариев
  • Как предотвратить бесконечную загрузку страницы при отправке post запроса?

    Использовать SSE (Server Sent Events). Это на порядок проще, чем вебсокеты, но мощь практически такая же.
    Вот неплохая статья на английском.
    https://blog.stackademic.com/real-time-communicati...

    Кстати, библиотека HTMX позволяет это обрабатывать и без написания Javascript
    https://htmx.org/extensions/server-sent-events/
    Ответ написан
    Комментировать
  • Есть ли сейчас необходимость в HTML5Shiv и Modernizr?

    Вы должны отталкиваться от того, кем являются ваши пользователи.

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

    Если же это обычные люди, сидящие в интернете, то, скорей всего они используют Chrome или Microsoft Edge. Эти браузеры постоянно обновляются в фоне, и перед внедрением новых фич вам просто нужно периодически заходить на https://caniuse.com/ и ориентироваться на последние 2 версии этих браузеров. Safari может стать проблемой, если ваши пользователи часто покупают Маки. Safari - это, к большому сожалению, новый IE6, который тормозит индустрию...

    Самый лучший способ - это собрать информацию. Если у вас уже есть какой-то сайт для вашей аудитории, то там и собирайте статистику. Исходя из этой статистики принимайте решение. Охватывать все 100% не стоит, лишняя трата времени, денег, нервов. Оно не окупается. Каким процентом пользователей вы можете пренебречь - это всегда индивидуальное решение, но убедить руководство, что такое решение надо принять, всегда надо, потому что вы потом закопаете проект в этой обратной совместимости и потенциальных багах и уязвимостях, идущих с ней в пакете...
    Ответ написан
    6 комментариев
  • Есть сервера, которые стоит написать именно на Java, а не на Node?

    Выскажу свою личную точку зрения:
    1. Изучаем, каким будет трафик сервиса на старте. Если это замена уже работающему высоконагруженному сервису, либо вы на 200% уверены, что нагрузка прямо сразу будет высокой и дальше на 200% точно уверены, что нагрузка будет расти, не выбирайте ни ноду ни Java. Берите, например, Go. Он гораздо быстрее ноды, там даже стандартная библиотека уже имеет готовые решения для всего нужного REST, и есть куча прекрасных сторонних библиотек и фреймворков.
    2. А вот если ваш проект новый, вы не знаете, сколько у вас будет пользователей, какая будет нагрузка, то не надо даже думать: берите то решение, которым вы владеете, и с помощью которого вы сможете быстро и дёшево собрать первую версию. Если это даже PHP, то пусть он и будет. С огромной вероятностью ваш сервис будет всё равно переделан и переписан позже, поэтому, чем меньше вы потратите времени и денег в самом начале, тем быстрее выйдете на рынок, и тем больше сэкономите первоначальных инвестиций. А когда проект начнёт приносить прибыль, вот тогда при помощи уже этой прибыли будете решать проблемы производительности
    Ответ написан
    Комментировать
  • Есть ли смысл учить jquery?

    1. Выучить JS
    2. Поверхностно ознакомиться с jQuery
    3. Написать собственную микро-jQuery в учебных целях - реально поможет со всем разобраться.
    4. Использовать jQuery, если надо быстро клепать лендинги. Использовать чистый JS в более сложных проектах.

    Без знания JS не стоит браться за jQuery, потому что не захочется учить сам JS, а это вызовет огромные проблемы, когда нужно будет сделать что-то посложней. Сам когда-то давно начал с jQuery, и потом пришлось в авральном режиме изучать JS, много заказов потерял
    Ответ написан
    3 комментария
  • Кнопка - переключатель на jQuery?

    Вот идея кастомного чекбокса на CSS без всякого JS.
    https://codepen.io/vitiok78/pen/pmbyzE
    Ответ написан
    Комментировать