Ответы пользователя по тегу PHP
  • Как заставить работать Guzzle асинхронно?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Во время работы с Async Guzzle вам нужен вызов $curl->tick(), чтобы он мог продолжить работу. wait() под капотом делает именно это

    Вот даже есть пример, как интегрировать курл с реакт-пхп и там есть этот тик, который делает движение
    https://gist.github.com/psampaz/7f2aad5d1d54eeeec8...

    use GuzzleHttp\Client;
    use GuzzleHttp\Handler\CurlMultiHandler;
    use GuzzleHttp\HandlerStack;
    use Psr\Http\Message\ResponseInterface;
    
    $curl = new CurlMultiHandler;
    $handler = HandlerStack::create($curl);
    $client = new Client(['handler' => $handler]);
    
    $p = $client
        ->getAsync('http://google.com')
        ->then(
            function (ResponseInterface $res) {
                echo 'response: ' . $res->getStatusCode() . PHP_EOL;
            },
            function (\Exception $e) {
                echo $e->getMessage() . PHP_EOL;
            }
        );
    
    while ($p->getState() === 'pending') {
        $curl->tick();
        // sleep(1);
    }
    echo 'bottom' . PHP_EOL;


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

    Опишите изначальную задачу, которую преследуете

    UPD после выяснения задачи:

    Задача: рассылать почту, не задерживая клиента
    Типовое решение: Выполнить fastcgi_finish_request и сделать после него отправку почты. То есть после выполнения данной функции идет разрыв с сервером, то есть браузер прогрузится до конца! Но сам скрипт еще поработает до того, как все сделает (и браузер об этом не узнает).

    Можете сообщение записать в БД, а после fastcgi_finish_request всю очередь вычесать и отправить
    Ответ написан
    3 комментария
  • Как обратиться к свойству объекта заведомо не зная этого свойства?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Семантика у задачи плохая очень (каталог в каталоге, у каталога товар? один? :)
    Но в целом вот на коленке как достать значения вложенной глубины

    <?php
    
    $catalog = new stdClass();
    $catalog->product = new stdClass();
    $catalog->product->item = 'Short';
    $catalog->product->model = 'Adidas';
    
    $catalogPaths = ['product.item', 'product.model'];
    
    
    function extractValuesByPath(object $obj, array $paths) {
        return array_reduce($paths, function(array $values, string $pattern) use($obj) {
            $values[] = extractPathValue($obj, $pattern);
            return $values;
        }, []);
    }
    
    function extractPathValue($obj, $pattern) {
        $paths = explode('.', $pattern);
        
        foreach($paths as $path) {
            if (!property_exists($obj, $path)) {
                // Можно нулл вернуть или к пример `undefined $path`
                throw new InvalidArgumentException('Нет такого свойства во входящих данных!');
            }
        
            $obj = $obj->$path;
        }
        
        return $obj;
    }
    
    $res = extractValuesByPath($catalog, $catalogPaths);
    var_dump($res);
    // [
    //       'Short',
    //       'Adidas',
    // ]
    Ответ написан
  • Как спроектировать фреймворк?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Фреймворк от начала и до конца (с пайплайнами, мидлварями и контейнером):
    https://youtube.com/playlist?list=PLE20id3DjfFnio1...
    Ответ написан
    5 комментариев
  • Как сохранить результат проверки assertFileEquals в codeception в отдельный файл?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Ассерты ничего не возвращают
    Ответ написан
    Комментировать
  • Чем array_walk лучше foreach?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Если сама функция array_walk может быть не интересной, то ее рекурсивная версия куда вкуснее, тк работает с вложенными массивами
    Ответ написан
    Комментировать
  • Можно ли в DTO указывать методы isName, isLimit?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Геттеры в ДТО только для типизации, так это просто структура
    Вообще с 7.4 можно юзать паблик поля
    Ответ написан
  • Не корректная работа json_decode?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.

    A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string. A string is very much like a C or Java string.

    A number is very much like a C or Java number, except that the octal and hexadecimal formats are not used.

    https://www.json.org/json-en.html

    Ну это не считая привычных всем массивов и объектов

    Если предположить, что скаляры были бы не доступны, то нельзя было бы делать массив скаляров:
    [
       "aaa",
       "bbb",
       "1234"
    ]
    Ответ написан
    Комментировать
  • Гидрация сущности из запроса. Что использовать?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Используйте Symfony Serializer Component, а именно встроенные ObjectNormalizer или GetSetMethodNormalizer, раз решили через сеттеры/геттеры с сущностями работать

    $obj = $this->normalizer->denormalize($data, YourEntity::class);
    Ответ написан
    2 комментария
  • Чем отличается такой код?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Помимо удобства, if else без раннего возврата управления может усложнить программу, тк может понадобиться следить за состоянием результата

    https://refactoring.guru/ru/replace-nested-conditi...
    Ответ написан
    Комментировать
  • Создание структуры по методу cqrs?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Вполне понятная и логичная структура. Скажем так — простая, логичная и популярная.
    Ответ написан
    Комментировать
  • Логика в геттере возможна ли?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Нет

    Геттеры могут быть в транспортных классах и иногда в инфраструктурных/библиотечных.

    Иначе это нарушение инкапсуляции: открывают доступ к тому, что закрыли. Как и сеттеры — дают доступ к тому, что закрыто, но на запись.
    Крч чит, хотя соответствуют определению инкапсуляции и дату-хиддингу

    Геттеры повышают связанность системы из-за открытой доступности данных модуля/класса, именно возможностью заюзать знания о состоянии, что в средних и больших, а иногда и в простых, на ровном месте усложняет код
    Ответ написан
    Комментировать
  • Что такое атрибуты в языке программирования?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Это аналоги аннотаций (которые есть уже в PHP через библиотеки типа Doctrine Annotations)
    5f2e640b82f02855914596.png

    и которые в свою очередь аналоги Java Annotations
    5f2e64693dc84892539290.png

    Тк в PHP это реализовывалось отдельным парсингом определенно оформленных комментариев — стало по сути отдельным языком и получило популярность в Symfony и др инструментах — решили внедрить как в Java нативно на уровне языка.

    Аннотации/атрибуты нужны для того, чтобы можно было писать логику в аспектно-ориентированном стиле, подробнее.
    То есть некоторая логика, которая выполняется несколько отдельно (декорирует и/или меняет поведение или ещё как-то иначе улучшает программу).
    Это очень выразительный, удобный способ для использования, хотя иногда и сложный для того, чтобы разобраться в кишках работы того или иного инструмента. Более подробно: Wiki: Аннотация (Java)
    Ответ написан
    1 комментарий
  • Как собрать массив определённого ключа другого массива?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    <?php
    
    // Ваши данные в упрощенном виде (без мусора)
    $array = [
        'numbers' => [
            [
                'numbers' => [
                    [
                        'formattedValue' => 111,
                    ],
                    [
                        'formattedValue' => 3333,
                    ],
                    [
                        'formattedValue' => 5555,
                    ],
                ],
            ],
            [
                'numbers' => [
                    [
                        'formattedValue' => 200111,
                    ],
                    [
                        'formattedValue' =>  2003333,
                    ],
                    [
                        'formattedValue' =>  2005555,
                    ],
                ],
            ],
        ],
    ];
    
    // Найдет все значения во всех вложенных элементах с нужным ключом
    // и сделает это рекурсивно — то есть во всех массивах и их детях.
    function searchValues(array $arr, string $search, array $res = []): array {
        array_walk_recursive($arr, function($value, $key) use (&$res, $search) {
            if ($key === $search) {
                $res[] = $value;
            }
        });
    
        return $res;
    }
    
    // Ищем в нашем массиве все значения с ключом `formattedValue` 
    // и складываем найденные значения в пустой массив (по дефолту), 
    // но можно передать 3-м параметром и имеющийся массив, тогда значения туда добавятся.
    $result = searchValues($array, 'formattedValue')
    
    var_dump($result);

    sandbox.onlinephpfunctions.com/code/d91d34104073f8...
    Ответ написан
    Комментировать
  • Какую опцию использовать для json_encode, чтобы он не экранировал слеш?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    JSON_UNESCAPED_SLASHES
    Ответ написан
    Комментировать
  • Выборка и сравнение данных массива PHP?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Сделал на примере массивов, можно на объекты переделать :)

    В одну итерацию (если, конечно, я правильно понял задачу): родитель и дети лежат плоско и для одного уровня вложенности. Если есть вложенности, то код будет немного по-другому выглядеть.

    <?php
    
    $data = [
        [
            'id' => 4,
        ],
        [
            'id' => 1,
            'start' => 1,
            'end' => 50,
            'parent_id' => 4,
        ],
        [
            'id' => 1,
            'start' => 10,
            'end' => 50,
            'parent_id' => 4,
        ],
        [
            'id' => 1,
            'start' => 5,
            'end' => 100,
            'parent_id' => 4,
        ],
    ];
    
    
    function aggregateExtremumBorders(array $elements) {
        return array_reduce($elements, function($res, $element) {
            if (!isset($element['parent_id'])) {
                return $res;
            }
            
            $parentId = $element['parent_id'];
            $parent = $res[$parentId] ?? ['id' => $parentId, 'min' => null, 'max' => null];
    
            $parent['min'] = min($parent['min'], $element['start']) ?: $element['start'];
            $parent['max'] = max($parent['max'], $element['end']) ?: $element['end'];
            
            $res[$parentId] = $parent;
            
            return $res;
        }, []);
    }
    
    var_dump(aggregateExtremumBorders($data));

    sandbox.onlinephpfunctions.com/code/7b43e0e4d8cf9d...
    Ответ написан
    1 комментарий
  • Удалили пакет из packagist и github, как работать с composer дальше?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    • Или запушить код в свой репозиторий и сделать пакажист-пакет (или не делать)
    • Или перенести код из папки vendor выше в проект и добавить неймспейс в composer.json


    PS: если репа нежелательна и ее могут удалить, то если выбрали первый вариант, то размещайте его в приватной репе и подключайте через https://getcomposer.org/doc/05-repositories.md#loa...
    Ответ написан
  • Закон Деметры и Doctrine?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    то как быть с ситуацией, когда в некоторых модулях должны производиться сложные выборки с фильтрами, агрегацией, затрагивающие сущности (entity) других модулей?


    Для решения задач в другом модуле/домене нет необходимости иметь сущности др проекта/модуля/бандла. Пример в модуле доставки
    • не нужно знать ВСЕ о товаре и логике его сбора, нужно знать размеры и название
    • в этом модуле не нужно знать и о заказе все — только адрес, время. История его обработки и статусы (все это есть в агрегате/сущности Заказ), влияние акций и промо — это знать не нужно, но оно есть!... передавая сущность куда-то вы передаете знания и связываете разные модули
    • не нужно знать о пользователе много, кроме телефона, имени и адреса


    Потому вы можете из БД выбирать только необходимые данные конкретному модулю. Этакие проекции по потребностям. Это есть соблюдение закона Деметры — вы не лезете в другой модуль, вы лезете в инфраструктуру (вселенную), которая даст вам ровно те знания и состояние, которые нужны . То есть за своими данными.. Более того эти знания могут собираться различными способами и не обязательно из реляций доставаться, а могут быть агрегированные в NoSQL виде к примеру.

    Крч для одного модуля вы получаете некоторые проекции/данные, которые в этом модуле вы даже не скажете — откуда они пришли, тк нет этих знаний — из персистенс-слоя и все...
    Ответ написан
    Комментировать
  • Что за мистика с условием при дробных числах?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    А в чем подвох? Почему без round не работает?


    Нормально и инженерно: по ссылке в этом ответе Не могу понять почему работает последняя исключения?
    Познавательно и просто (в самом начале видео про эту ошибку как раз): Опасные ошибки, которые мы не замечаем
    Ответ написан
    Комментировать
  • Вычесть две даты и получить время Carbon?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    зачем через getTimestamp() вычисляете diff, когда есть методы diff() у даты?!

    и почему из диффа (разницы) вы создаете время
    допустим разница будет 10 секунд, если для 10 секнуд вы время будете создавать, тогда выдавать вам будет как 10 секунд от начала отсчета (полуночи 1 января 1970 года)

    Решения:
    Считать разницу через difference

    $date1 = Carbon::createMidnightDate(2016, 1, 5); // <-- тут любой способ создания объекта
    $date2 = Carbon::createMidnightDate(2017, 3, 15);
    
    echo $date1->diffInDays($date2);                   // 435
    echo $date1->diffInWeekdays($date2);               // 311
    echo $date1->diffInWeekendDays($date2);            // 124
    echo $date1->diffInWeeks($date2);                  // 62
    echo $date1->diffInMonths($date2);                 // 14
    echo $date1->diffInQuarters($date2);               // 4
    echo $date1->diffInYears($date2);                  // 1

    https://carbon.nesbot.com/docs/#api-difference
    Ответ написан
    Комментировать