Ответы пользователя по тегу PHP
  • Как можно установить время неответа на CURLOPT_WRITEFUNCTION?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Вы решаете задачу потокового получения данных разовым запросом к камере.

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

    Под капотом оно работает как опросник на уровне операционной системы, который с некой частотой проверяет информацию в ячейке памяти.

    Так как вы делаете тоже можно, но ваш вызов надо заворачивать в

    while (true) {
      // > запрос (сам по себе займет несколько секунд, если повезет - меньше секунды, таймауты в этом случае нужны чтобы при проблемах сети, но когда все устройства работают - немножко подождать, секунду-полторы, а не 20)
    
      // где-то тут брать значение счетчика microtime(true) и писать функцию считающую разницу по вашим критериям, будь это 20 сек с последнего запроса или 20 сек с последних полученных данных
    
      usleep(1); // подождать минимум 1 микросекунду (1 кадр), позволив этому ядру проверить другие ожидающие задачи операционной системы, чтобы процессор не задымился от 100% нагрузки в случае если запрос перестанет происходить
      // usleep можно ставить и больше, например 1*1E5 или 100 000, это 100 мс, но в принципе операционке достаточно 1 кадр, она все равно вернется только после того как закончит проверку всех устройств, т.е. по факту пройдет не 1 мкс, а "минимум 1 мкс".
    }


    но правильно, это все таки подключится сокет соединением на порт камеры.

    И нет, этот скрипт не нужно потом запускать из браузера. Он запускается из командой строки/total_commander вызовом "php index.php", что приведет к запуску окошка в котором он работает. Из браузера что-то с while (true) запустишь и оно рано или поздно сляжет по php execution time.
    Ответ написан
  • Как лучше реализовать возможность передать \Closure, чтобы запустить его не-блокирующим способом?

    gzhegow
    @gzhegow Автор вопроса
    aka "ОбнимиБизнесмена"
    Раз нет ответа отвечу сам. Видимо промиз. Он как раз и есть мост между параллелью и синхроном. И коль скоро деферед дает отложенный запуск и позволяет проверять состояние то пожалуй он лучше еще. Пора уже пср щикам написать интерфейс на дефер и промиз
    Ответ написан
  • Как запустить Gulp из Php?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Из PHP этого делать не нужно, вы все равно не получите потока данных, только поток отчетов.

    Напишите "npm init", и в файле package.json сделайте секцию "scripts", потом запускайте из консоли перед установкой проекта на новую машину "npm run my_script_that_runs_gulp".

    То есть проект оборачивают в контейнеры, чтобы это автоматизировать, а не заставляют язык программирования делать всё, тем более чтобы это запустить все равно придется открыть консоль и вызвать команду с php, или пройти по ссылке, чтобы веб сервер сделал это для вас.

    Способ есть, для этого надо искать в доке как выдать на выход поток самих данных из функций галпа, который все равно сделан на node, перенаправить их в stdout, и мы можем подписаться на поток данных зачем-то и что-то с ними делать, но обычно это не нужно, т.к. галп это и есть обертка для потоков на node js.
    Ответ написан
  • Middleware пример архитектуры для цикла запрос - контроллер - ответ, да?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    мидлвар это понятие "обернуть" действие (в данном случае контроллер), чтобы что-то сделать до него или после. в нем нет ничего магического.

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

    общая идея - вызывается метод контроллера, вокруг которого обернуто N мидлваров, каждый из которых что-то делает и либо останавливает цепь, либо вызывает ->next() чтобы передать следующему вплоть до самого действия
    Ответ написан
    4 комментария
  • Есть способ выдергивать JS обьекты/JSON из тегов script в HTML документе средствами PHP?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    да.
    1. $html = file_get_contents('https://bel.vkusvill.ru/shops/'); // получаем сорс
    2. preg_match_all('~' . preg_quote('<script>.+</script>', '/') . '~', $html); // ищем все теги script
    3. циклом проходимся, берем нужный.
    Ответ написан
  • Как удалять файлы с сервера по условию, что они не используются в текущий момент?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    А вот что выглядит вкусным
    https://github.com/jack-theripper/yandex

    Сначала я думал что это жесткий REST-api, в котором есть "дай список", "закачай", "отдай" и "удали". Но там лежит вкусная папка Stream.... где есть метод "считать несколько байт прямо с диска".

    Вот если они продолжат в архиве класть 5 видео, а не в папке, то этот функционал вам недоступен и вы в тупике. Но если это будут видеофайлы, то вы можете открывать соединение с яндекс диска через страницу на вашем сайте, где заголовками отдавать что "получаемый файл есть видео, и content-length неизвестен". В теории подрубившись плеером к этому стриму вы внезапно сможете считывать его по чуть-чуть, в результате будете ограничиваться уже толщиной канала и оперативной памятью, куда будут временно выгружаться данные по кускам, а не жестким диском.

    Но я не проверял, работает ли это вообще, а с видео давно бы уже пора мне научиться работать.

    По сути это вытесняющий кеш и будет как сказал Ипатьев. Но это будет кеш который в моменте хранит только например 8килобайт на юзера.

    А если вы как и сказали - подключите сюда еще сокеты (не веб-сокеты, а просто сокеты, tcp например), то вы еще и предотвратите отдачу целого фильма в скрипте даже если пользователь перестал смотреть. Вы просто в шаге цикла while () сможете проверять - есть ли кому контент слать. И если некому то прекращаете чтение.
    Ответ написан
    1 комментарий
  • Как сделать кнопку которая загружала бы фотографии с пк в папки на сервере?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Простейшая реализация
    <form type="multipart/form-data">
    <input type="file" multiple="multiple" />
    <button type="submit" />
    </form>


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

    Задача лютой сложности для тех, кто все это не знает, хотя кажется "загрузить картинки".

    Без знаний простейшая реализация - "дайте доступ на сервер, я вам картинки закачаю и на сайте выведу, разово". В менее запущенных случаях "делаем скрипт, в который можно отправить зип архив с картинками", это проще, но если им самим разрешить это делать - они запорют.

    Есть мааааленькая вероятность, что ваш старый код уже работает и нужно только какую-то строку исправить. Проверяйте удачу!
    Ответ написан
    9 комментариев
  • Когда стоит начинать учить фреймворки?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Мое мнение - этот этап переходный. В эру микросервисов чем меньше дредноут - тем лучше. Раньше казалось "будем писать на ларавель - всегда найдем специалистов по ларавелю". Некоторые и сегодня так думают. Другие - следуют мысли "как хочешь так пиши, а вот тесты должны пройти". А те кто ещё хитрее и вовсе сделают тебя виноватым за выбор одного из фреймворков, причем если все будет работать - то молодцы будут они, а если ты не справился - то дурак ты, вот и решай - быть тебе с фреймворками или головой шевелить.

    ООП, композер и пакеты - наш выбор. Дредноут где "всё включено" и без бутылки водки ничего нельзя отключить потому что "оно так настроено" - уже нет.

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

    Столкнуться с ними стоит. Но вот надеятся что автоматическая штука включающая всё что нужно - это решение - это этап развития, который пройти нужно, а потом забыть.
    Ответ написан
    2 комментария
  • Как задать условие "если url начинается с my.site/me/*, то..." в php?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Я наизусть сейчас не вспомню как она там пишется, но в ларе есть функция которая на вход регулярку принимает и возвращает да/нет.

    Помоему url()->is($regex) или $route->is($regex), гуглите
    Ответ написан
    Комментировать
  • Как лучше работать в postgresql и php с временными зонами?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    1) Сначала в консольке там есть timezone + dpkg-reconfigure, там гуглим как сделать UTC
    2) потом в приложении date_default_timezone_set() тоже ставим в UTC, и все новые даты (new \DateTime) у вас будут создаваться в UTC.
    3) не забываем, что таймзона есть и в большинстве СУБД. Это бы всё да тестировать как одно на другое влияет, дескать приводит или не приводит, но для начала можно тупо везде это выставить.

    * Я предполагаю что если передать со своей таймзоной в БД - оно сохранит верно, а вот если не передать ничего то пустая дата создастся в указанной таймзоне, что при запросе выдаст например 00.00.0000 00:00:00+02:00 вместо нуля по UTC, тоже касается любителей сравнивать с NOW() или проставлять по дефолту CURRENT_TIMESTAMP(), они скорее всего будут работать по настройке.

    На практике я не встречал тех, кто упарывается в таймзону и в UTC. Попробовал когда-то в это топить - дали по шапке "у нас так не принято в компании". Каво? Некоторые ставят принудительно Europe/Moscow только в пхп и думают что все сделали (ведь на сервере время вполне может быть например Amsterdam, и что самое интересное - таймзона при сборке пхп из исходников шьется вовнутрь и может быть вообще другая, и тут уже каша начинается, ты не знаешь и не можешь это исправить) и потом с этим долбятся, потому чтоб поменять в системе - надо контейнеры делать, а девопсом 90% из них не является, а контейнеры они понимают только на словах, а еще это надо просчитывать на что повлияет, а они боятся, и может даже правильно... Короче. Вам нужно понять принцип как её устанавливать, а не пытаться затребовать у всех UTC. Но если вы с начала проект делаете и сами собираете окружение - то поставить не лишне.

    В итоге конвертировать их придется только при выводе в таймзону пользователя. Для этого пишем какой-то класс Calendar и там метод formatDate(), он на вход может принимать таймзону, которую вам пользователь заранее аяксом передал и вы её положили в сессию например или в кеш на 15 минут.

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

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

    Если же сеттером - то "к этой таймзоне нужно конвертировать". Все бы хорошо, если бы не третий неявный параметр - date_default_timezone_get(), ведь сеттер отталкивается от него, что не всегда очевидно. То есть вы вроде пытались сделать UTC, а в итоге получили разницу между временем сервера и переданной датой, особенно понимая, что сама дата изначально в тексте могла содержать временную зону и получили неожиданный результат.

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

    Иммутаблы это ересь для тех, кто пока ещё не умеет работать с датами или не понимает ООП.

    Разница между иммутаблом и не иммутаблом в том, что первый по результатам любого действия возвращает другой объект с датой, чтобы вы случайно не изменили старую. Если вы понимаете, что времядата это объект, то вы этого не сделаете. Точно так же как вызывая какой-нибудь $config->set(); вы понимаете что вы меняете конфиг, а не создаете новый. Вполне можно использовать clone/new чтобы создать несколько дат перед тем как начать их менять.
    Ответ написан
    2 комментария
  • Возможно ли добавить use переменные после объявления анонимной функции?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Процесс, который вы хотите называется "функции высшего порядка"

    // функция "высшего" порядка - что в ней высшего - надо спросить у того кто придумал, высший человек наверное
    
    $fnPow = function ($x, $y) {
      return pow($x, $y);
    };
    
    $fnPowExtended = function () use ($fnPow, $b, $c) {
      var_dump($b);
      var_dump($c);
      return $fnPow($b, $c);
    };
    
    $fnPowExtended(2, 3);
    // 2
    // 3
    // 8


    Таким образом чтобы прокинуть что-то в уже созданную функцию вам нужно создать новую функцию и прокинуть туда существующую и что-то ещё. Более того, вы можете прокинуть функцию саму в себя, чтобы сделать рекурсию.

    $fnRecursion = function () use (&$fnRecursion) {
      $fnRecursion(); // infinite recursion here
    }


    Я полагаю что ваш интерес вызван желанием создать функцию bind()/call()/apply(), как в javascript. В ПХП этим путем не пошли, т.к. ООП все же хоть и дороже в разработке, но понижает порог входа новых людей в проект. Решение спорное, т.к. в ООП надо уметь, а функционалка может быть лишь бы было. И понимая что "старый код не трогать, а заменять" это вроде не так уж плохо. Но в пхп часто старый код именно трогают, доделывают, подпиливают. Функционалка усложняет процесс понимания "что происходит", поэтому ей редко пользуются. К тому же в пхп до недавнего времени вообще короткой записи не было, и писать function () use () {}, и потом переживать, что там чото с памятью может быть и пересылом часто сложнее, чем нажать CTRL+N в IDE и создать новый класс.

    bind() должна бы выглядеть примерно так в PHP (но ей здесь никто не будет пользоваться):

    /**
         * bind
         * копирует тело функции и присваивает аргументы на их места в переданном порядке
         * bind('is_array', [], 1, 2) -> Closure of (function is_array($var = []))
         *
         * @param null|object $newthis
         * @param callable    $func
         * @param mixed       ...$arguments
         *
         * @return \Closure
         */
        public function bind(?object $newthis, callable $func, ...$arguments) : \Closure
        {
            if (! is_string($func)) {
                $bind = $arguments;
    
            } else {
                // string
                $bind = [];
    
                $rf = new \ReflectionFunction($func);
    
                $requiredCnt = $rf->getNumberOfRequiredParameters();
    
                while ( $requiredCnt-- ) {
                    $bind[] = null !== key($arguments)
                        ? current($arguments)
                        : null;
    
                    next($arguments);
                }
    
                $func = \Closure::fromCallable($func);
            }
    
            if (null !== $newthis) {
                if (! $func instanceof \Closure) {
                    $func = \Closure::fromCallable($func); // throws exception if not possible
                }
    
                $func->bindTo($newthis); // throws exception if not possible
            }
    
            $result = static function (...$args) use ($func, $bind) {
                $bind = array_replace(
                    $bind,
                    array_slice($args, 0, count($bind))
                );
    
                return call_user_func_array($func, $bind);
            };
    
            return $result;
        }


    Почему она такая "странная"? Потому в php есть еще одна проблема. Созданные функции (не безымянные, вот только не помню - кажется только встроенные, свои - не такие строгие) требуют строгое число аргументов на своих местах. Если вы передадите больше или меньше - они ломаются и не работают. Рефлексия считывает "а скока надо" и передает ровно столько, на остальное забивает.

    ===

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

    Чуть позже в python поняли, что можно не только готовые объекты заворачивать, но и декорировать любую функцию уже на этапе описания. На псевдокоде это выглядит так:

    [send_telegram] // use result to call new function
    [send_email] // use result to call new function
    [push_event] // use result to call new function
    function register() {
      // do some
    }


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

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

    1) Я стараюсь не увлекаться функциями, потому что у них проблемы с "сериализацией" - сохранить их в файл или передать по сети проблематично. Вы буквально передадите номер строки в коде, который завтра может быть другой и вторая сторона должна иметь точно такой же код, это ненадежно.

    2) Функции работают с памятью несколько по особенному. То есть если не писать перед функцией слово `static`, что означает "не хранить внутри $this того места где её создали", можно получить интересную картинку если эту функцию вызовут в рекурсии. Оригинальный класс, который для неё $this, накопив данные и начав копировать эту функцию в момент того как вы пишете $a = function () {}, будет каждому экземпляру копировать данные этого объекта. И случайно в коде выполнив циклом 300 раз $a = function () {} вы 300 раз скопируете данные, которые возможно представляли собой "много текста" и ушатаете память.

    С функциями нужно быть осторожным. Чем реже, тем лучше. Но это не значит что они плохие. Так например прослушку постоянного процесса в скрипте, который никогда не завершится с возможностью подключать свои действия сильно проще написать на функциях-обработчиках. Хотя ООП рекомендовал бы использовать имена классов и фабрику их создающую, гарантируя что конфиг будет содержать текст а не объекты.

    Не уверен, что понимаю как работает ядро яваскрипт, но что-то мне посказывает, что там есть общий скоуп и ничего никуда не копируется, а просто берется то что есть либо везде, либо конкретно здесь, т.к. передали. В пхп у каждой функции свой скоуп. С одной стороны это обрезает руки, с другой стороны не позволяет совершить глупых ошибок по типу "вывести то, чего тут может и не быть".
    Ответ написан
    Комментировать
  • Почему не срабатывает команда artisan php artisan make:model Flight -a в Laravel?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    На вашем линуксе не установлено расширение ext-dom.
    Какого черта мэйкер его хочет - а болт его знает. Искать надо.
    Ответ написан
    Комментировать
  • Как соотнести каждый элемент строки массива с каждым элементом других строк этого массива?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    На пхп из коробки сложновато, вы говорите об операции "product" которая является частью комбинаторики.

    Вот у меня класс есть, где я это из python портировал:
    https://github.com/6562680/support/blob/main/src/X...

    Но мне кажется, вам будет сложно разобрать что там написано поэтому я вам простой код напишу под вашу задачу:
    $arr = [
    	['aa', 'bb', 'cc'],
    	['dd', 'ee', 'ff', 'gg'],
    	['hh', 'ii'],
    ];
    
    function _array_product(array $pools) {
        $result = [ [] ];
    
        foreach ( $pools as $pool ) {
            $resultCurrent = [];
    
            foreach ( $result as $x ) {
                foreach ( $pool as $y ) {
                    $resultCurrent[] = array_merge($x, [ $y ]);
                }
            }
    
            $result = $resultCurrent;
        }
    
        foreach ( $result as $item ) {
            yield $item;
        }
    }
    
    foreach (_array_product($arr) as $val) {
    	var_dump($val);
    }
    Ответ написан
    2 комментария
  • Как сформировать через рекурсию многомерный массив?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    function _array_set(array &$array, array $fullpath, $value) : void
    {
        if (! $fullpath) {
            throw new InvalidArgumentException('The `fullpath` should be not-empty');
        }
    
        $last = array_pop($fullpath);
    
        $valueRef =& $array;
        while ( null !== ( $k = key($fullpath) ) ) {
             $valueRef =& $valueRef[ $fullpath[ $k ] ];
    
             next($fullpath);
        }
    
        $valueRef[ $last ] = $value;
    }
    
    $array = [];
    _array_set($array, [ 1, 2, 3 ], 'abc');
    var_dump($array[1][2][3]); // 'abc'
    Ответ написан
    Комментировать
  • Как написать чат на php?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Чат это хранилище переписки и способ их доставки.

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

    Но в пхп есть работа с сокетами используя команды stream_*, чтобы подключить обоих участников (подписать) к третьему серверу и он принудительно присылал ожидающим сообщения обновления как только они придут на сервер.

    Если это будет консоль двух клиентов и консоль сервера то столкнешься с проблемами на windows, где у cmd.exe нельзя писать в консоль и одновременно слушать соединение с сервером, только по-очереди, на линуксе - можно. В смысле и там и там по-очереди, просто винда не умеет до завершения того как ты печатаешь быстро переключаться между "послушать сокет" и "послушать ввод юзера" - слушает ввод юзера пока enter не нажмешь.

    Если будешь делать морду на html, будешь использовать либо периодический опросник с "морды" клиента на javascript к серверу через асинхронные запросы (ajax), либо будешь применять пакет для javascript socket.io и протокол веб-сокетов, чтобы уменьшить задержку между получением с "времени опроса" до "как только пришло сразу показать".
    Ответ написан
    2 комментария
  • Как заставить IDE воспринимать данное выражение как указанный обьект Class'а?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    /** @var MyClass $theCache */
    $theCache = i()->app->cache;


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

    Когда это поймет начальник?
    Действительно. Кстати, а зачем ему это понимать? Всё работает, что вы тут лодку раскачиваете. Это происходит в России? Нет. В США, в Канаде, в Украине, в Беларуси и в России тоже. Везде. Линия границ проходит не по странам, а по способу получения прибыли - одни получают деньги за свою работу, а другие - за чужую. Вот кто за чужую - готов говорить что белое это черное. А если упрямишься - лишают работы, должен молчать и кланяться.
    Ответ написан
  • Перебирая SimpleXML файл как многомерный массив, он выдает только первый массив останавливаясь на нем?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Осторожнее с SimpleXML.
    Он очень непривычным способом обходит по дереву разметки.
    А ещё удаление или перезапись через него делать "одно удовольствие".
    Помните, что ещё есть класс DOM, который часто используют в спарке.
    Ну вот такие мы пыхари лентяи, нормальный пакет для работы с XML хрен кто написал.
    Можно попробовать симфонийский кроулер, но он вроде как под HTML писался, хотя под капотом использует DOM, а значит в теории умеет в XML.
    Ответ написан
    Комментировать
  • Поддерживает ли PHP асинхронность на уровне ядра языка программрования?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Чтобы сделать пример асинхронки на коленке, не вдаваясь в детали, нужно завернуть действие в генератор и перед каждой строкой кода писать "yield <строка кода>", чтобы код останавливался и передавал управление наружу. В этом случае собрав пачку генераторов и используя форич чтобы в КАЖДОМ ШАГЕ двигать КАЖДЫЙ ГЕНЕРАТОР на один шаг вперед - можно получить асинхронное выполнение.

    Если чуть глубже то yield на самом деле стоит писать перед теми операциями, что делаются долго, но при этом не то, что они тяжелые, а они предполагают ожидание чего-то. Например, отсылка почты сама по себе происходит быстро, а вот пока подключишься к серверу - это висим. Вот эти самые нетяжелые но долгие операции имеют время простоя, которое можно куда-то еще применить, пока ждем, если написать свою функцию mail(), которая открывает соединение и шлет что-то серверу, то есть по тому самому SOLID не сразу отсылает емейл а делает это в пару этапов, между которыми будут запускаться "шаги" из других генераторов.

    Но оно не будет параллельное в полном смысле (одновременно делаться не будет, просто будет более грамотное управление простоями).

    А вот блокирующие функции, например, функция sleep() она по умолчанию блокирующая, то есть вызвав её мы будем висеть сколько-то секунд. Она блокирующая не потому, что она "родилась такой", а потому что в ней внутри не сделаны передача управления наружу в каждом тике. Поэтому пишут так как еще в яваскрипте показывали - ставят таймер на 1 секунду к примеру (а лучше на так называемое "время тика"), и в каждом шаге проверяют - "столько-то секунд с момента запуска таймера прошло уже?" и если прошло то двигают генератор дальше, если нет - продолжают ждать.

    Это создает некую иллюзию асинхронного кода, но это не совсем то же самое что сделать pcntl_fork(), который в конечном итоге будет делать действительно в двух разных процессах (программах) и ему будет люто наплевать что делается в соседней. А затем родитель, породивший все форки просто вешает ожидалку всех детей до состояния "пока закончилось", тем самым получается нечто вроде Promise.all(tasks).

    Как итог pcntl_fork() - это переброс ответственности за опрос потомков на саму прогу php и на железо компьютера вместо кода, написанного на php, где каждая команда под капотом будет выполнять множество машинных вызовов, протупливать и так далее. Когда железо следит за этим получается НАМНОГО быстрее, задействуется больше ресурсов компьютера и т.д. Но в действительности там тоже нет прям вот "одновременного" с точки зрения момента времени, но есть "пока есть свободный исполнитель возьми это на себя", что действительно является одновременностью с точки зрения промежутка времени.

    Есть и прикольная новость. То что в винде до сих пор этого нет (хотя помнится вместе с PowerShell уже как-то вкрутили через три села и корчи), то это значит что если вы подымаете эту тему, то ваш уровень примерно "майкрософт". Можете запихнуть это в глотку рекрутеру, который будет говорить что вы "не имеете опыта в высоконагруженных распределенных системах" и улыбаться тому, что она едва умеет в эксель.

    ====

    Немножко практики - "когда без асинхронки не обойтись". Еще пару лет назад я был уверен что в пхп асинхронка не нужна вообще. Ну дескать - язык такой, нет здесь асинхронных задач.
    А вот и нет. Просто асинхронность у пхп разработчиков берет на себя Nginx + PHP-FPM или Апач. Это его задача на каждый запрос подымать процесс и делать его отдельно.
    Когда система ТЯЖЕЛЕЕТ и не может справляться с поставленными задачами потому что Nginx имеет время ожидания, и скрипты запущенные из апача висящие в браузере (например) часами - это ересь и бред, или когда буквально не хватает ресурсов одного компьютера и всё глючит, а нагрузка шкалит под 90%, задаешься тем, что нужно МАСШТАБИРОВАТЬ приложение. Это значит что операции требующие много времени нужно выбросить на другую машину. Сразу такой "как же это сделать". Начинаешь читать про БРОКЕРЫ СООБЩЕНИЙ. Редисы (rpush, lmove), Раббиты (ampq, тормознутый как старое пердало), Кафки (event sourcing из коробки на компах с 384гб оперативы - у вас такого нет), Натсы (к которым не найдешь пхпшной обертки нормальной). И тут выясняется следующее. Что когда из пыхи ты стрельнул сообщением в брокер, а кто-то, кто на него подписался сообщение получил, то он делает его СИНХРОННО, одно за другим. И нет там апача который заботливо на каждое сообщение подымает для тебя новый процесс. И вот тут ты задумываешься как же сделать так, чтобы пришедшие сообщения делались не одно за одним, а сразу десяток. И понимаешь - как хорошо, когда асинхронка уже есть, приручаешь pcntl_fork() и делаешь ручками. В этот момент происходит отсев разработчиков на "пыха дерьмо" и "пыха может всё". Вот первые уходят в GoLang или долбятся с NodeJs и прикручивают, а другие понимают что в пыхе есть другие преимущества, потерять которые - дороже.

    Кое-что про Pthreads и почему его "забыли". Его не забыли. Просто pthreads подымал разные задачи от начала до конца. То есть в каждом процессе требовалось произвести инициализацию того же фреймворка например. Это дорого и тяжело. В отличие от форка, который в нужный момент просто отпочковывается в другую задачу сохраняя всё, что уже было сделано. Это лучше, чем стартовать целые скрипты заново.
    Ответ написан
    1 комментарий
  • Как записать в JSON число только с ДВУМЯ цифрами после точки?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Вам программа подсказывает что вы неверно работаете с сущностью "бабло".
    Бабло должно быть строкой или интом.
    Вы делаете из него флоат и получаете ровно то, с чем борятся говоря "бабло должно быть строкой".

    1) Функции связанные с деньгами это отдельный класс в приложении который использует для их расчета функции bcmath, умеющие считывать произвольное число знаков до и после запятой и считать число не взирая на разряд.

    2) Для работы с деньгами используют библиотеку phpmoney где большая часть нужных вам вещей уже завернута, есть парсер и форматтер, поддерживаются валюты и с гемором но можно даже создавать свои. К сожалению, парсинг валют с сайта банков вы скорее всего будете писать сами, т.к. предложенный вариант парсит их из какого-то источника, который не учитывает ситуацию в вашей стране, но сама поддержка переводов валюта-валюта есть.

    3) Для работы с деньгами дописывают функции "округление в большую сторону и округление в меньшую сторону с учетом копейки в последнем разряде", их в пхп нет, они считаются "не математическими", как и вся экономика основаны на "кто кому чего должен" а не "сколько будет". Так округление 1.0005 до двух знаков равно 1.00, тогда как экономика считает что 1.01. И тут тоже два пути. Если вы выставляете клиенту цену, то это 1.01 (копейку содрать с клиента), а если клиент пополняет баланс, то это округление в меньшую сторону - на баланс зачисляется 1.00 (снова содрать копейку). Экономика очень подлая хрень. Она экономит всё. Но не за счет себя, а за счет того, кто платит. И вы еще спрашиваете почему "бизнес это благо", потому что те кто им занимаются грабят остальных средь бела дня (если даже в программировании вопрос копейки, то что в маркетинге - я боюсь даже представить, цена из воздуха, хайп и лексусы) и никто еще и доказать этого не может. Везде бумага "сам согласился и подписал".

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

    Как и в экономике. Кто делает - тот платит. Кто не делает - тот выигрывает. В общем - мобилизация не случайность. Медитируйте. Желательно с книгой Ленина.
    Ответ написан
    24 комментария
  • Как подключить browser-sync при работе на open-server?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Я обычно отдельно вебпаки не настраиваю, больно это сложно для меня. Я беру компонент "symfony/encore", пишу класс, который работает с манифестом, и там в энкоре уже есть как watch, так и listen.

    Не то чтобы это правильно, но это просто чуть быстрее, чем вдуплять чего там яваскриптеры (у которых стандарты программирования (читай: последовательность мыслей) или возводятся в абсолют до тайпскрипта или вообще отсутствуют) позволили конфигурировать и как это в компоновке с вебпаком и npm варится.
    Ответ написан
    Комментировать