Задать вопрос
  • Можно ли программно создать DTO и провалидировать его?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Бывают разного рода задачи, когда строятся DSL и приходится динамически создавать правила и объекты
    Все зависит от ситуации и выбранного решения в реакцию на нее

    Валидация ответов в данном случае будет зависеть от того, какой тип при создании вопроса будет выбран/сконструирован. Вот под эти правила и нужно вам делать валидацию, кажется тут не будет конечных ДТО, только промежуточные
    Ответ написан
    Комментировать
  • Как добавить синтаксический сахар, связанный с оператором в php?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Проблема 0: В PHP нет перегрузки операторов и магических методов как в Пайтоне под такое дело

    Вариант 1: Условно функциональный
    Можно например так (если конечно вам подойдет)
    $a() - $b()

    Тогда надо просто __invoke() реализовать в каждом из классов

    Плюс такого, что в $a или $b может быть не только класс, но callable
    <?php
    
    class N {
        private int $n;
        public function __construct(int $n = 0) {
            $this->n = $n;
        }
    
        public function __invoke(): int {
            return $this->n;
        }
    }
    
    $a = new N(5);
    $b = fn() => 100;
    
    var_dump($a() - $b()); // -95


    И даже на лету передавать аргументы, например мультипликатор:
    <?php
    
    class N {
        private int $n;
        public function __construct(int $n = 0) {
            $this->n = $n;
        }
    
        public function __invoke(int $multiplier = 1): int {
            return $multiplier * $this->n;
        }
    }
    
    $a = new N(5);
    $b = fn(int $multiplier = 1) => $multiplier * 100;
    
    var_dump($a(100) - $b()); // 400
    sandbox.onlinephpfunctions.com/code/331eef7f9ad530...
    А можно передавать еще callable :) Крч вот вариант функциональный очень гибкий
    Или наоборот в конструкторе зашить мультипликатор, а сами числа передавать на лету, по-разному можно сделать

    Вариант 2: Value Object
    Можно посомтреть как сделан интерфейс например у объекта DateTime и увидеть, как работает diff() (разница времени) и можно сделать похожий интерфейс

    <?php
    
    interface NumericInterface {
        public function add(Numeric $second): NumericInterface;
        public function toInt(): int;
    }
    
    class Numeric implements NumericInterface {
        private $n;
        
        public function __construct($n = 0) {
            $this->n = $n;
        }
    
        public function add(Numeric $second): self {
            return new self($second->n +  $this->n);
        }
        
        
        public function toInt(): int {
            return $this->n;
        }
    }
    
    $num1 = new Numeric(10);
    $num2 = new Numeric(18);
    
    $result = $num1->add($num2)->toInt();
    
    var_dump($result); // 28
    Ответ написан
    1 комментарий
  • Как запустить процесс в изолированном окружении?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Может вам подойдут LXC контейнеры? на базе которых раньше и строились докер-контейнеры
    Видел работу напрямую с ними в одной из компаний для стендов (и прода в т.ч)

    Если вас смущает, что поднимается на ядре еще одна ОС, то можно поднимать без нее, собирая Docker from scratch — абсолютно пустой image без ничего... и например в нем поднимать свой статический бинарь (например на Golang или на C++)
    https://habr.com/ru/post/460535/
    Ответ написан
    Комментировать
  • Как оповестить пачку горутин о завершении работы?

    Maksclub
    @Maksclub Автор вопроса
    maksfedorov.ru
    Сработал такой вариант со SO с применением еще канала, который не позволит завершить выполнение main()

    func main() {
        forever := make(chan struct{})
        ctx, cancel := context.WithCancel(context.Background())
    
        go func(ctx context.Context) {
            for {
                select {
                case <-ctx.Done():  // if cancel() execute
                    forever <- struct{}{}
                    return
                default:
                    fmt.Println("for loop")
                }
    
                time.Sleep(500 * time.Millisecond)
            }
        }(ctx)
    
        go func() {
            time.Sleep(3 * time.Second)
            cancel()
        }()
    
        <-forever
        fmt.Println("finish")
    }


    Src: https://stackoverflow.com/questions/6807590/how-to...

    Вариант 2: Можно через WaitGroup завершить или через отдельную горутину с буферезированным каналом (на число горутин-воркеров)
    Ответ написан
    Комментировать
  • Как в Doctrine, в DBAL указать PDO::ATTR_PERSISTENT => true?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Ентити-менеджер использует один объект Connection, Connection использует объект PDO, всегда везде одно подключение и работает во всем жизненном цикле приложения, в этом и суть работы (ну в том числе) DI контейнера — отдавать один и тот же объект и не плодить их. То есть на жизненный цикл приложения все и так работает

    Тесты функциональные? Может плодится много http запросов в разных процессах? Но если и так — то все равно процессы разные и объекты PDO разные, так что ваша настройка не сработает, тк просто сами приложения будут разные...

    Для таких случаев в Codeception есть такая штука как persistService, по идее сервис (в вашем случае EntityManager, если через него работаете, или Connection, если через DBAL работаете) должен один идти через эту штуку единый, даже если разные http запросы
    https://codeception.com/docs/modules/Symfony#persi...

    Крч, раскройте немного деталей ваших тестов и ситуации, может я все не туда пишу
    Ответ написан
  • Как заставить работать 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
    maksfedorov.ru
    Возьмите готовое решение guzzle — это http клиент
    Вот у него есть готовое решение: https://guzzle3.readthedocs.io/http-client/client....
    Ответ написан
    Комментировать
  • Почему Codeception Acceptance тесты иногда проходит тесты иногда нет ??

    Maksclub
    @Maksclub
    maksfedorov.ru
    Почему codeception selenium морочит голову
    Или она должна не работать
    Или должна работать

    Или должна то работать, то не работать... при текущей реализации вашего кода

    Причины гейзенбагов

    Также посмотрите это видео про Flacky тесты
    Андрей Солнцев — Flaky tests или статья, если неугодно смотреть видео: https://habr.com/ru/company/jugru/blog/416757/

    Вот ссылка на тайминг, почему они бывают и как делать профилактику, чтобы их не было: https://youtu.be/jLG3RXECQU8?t=2156
    Ответ написан
  • Как обратиться к свойству объекта заведомо не зная этого свойства?

    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',
    // ]
    Ответ написан
  • Entity в bunlde как реализовать relation без зависимостей?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Нужна ли связь на уровни доктрины associations mapping?
    Что-то мне подсказывает, что на самом деле — нет; и достаточно связи на уровне id(uuid) между сущностями

    Пример на отдаленную тему и одновременно на эту — про потребность НЕ связывать сущности почем зря

    60657ae9b337d223246268.png
    Ответ написан
  • Как использовать Doctrine для сохранения связанных сущностей?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Persistence by Reachability: Cascade Persist
    There are additional semantics that apply to the Cascade Persist operation. During each flush() operation Doctrine detects if there are new entities in any collection and three possible cases can happen:

    • New entities in a collection marked as cascade: persist will be directly persisted by Doctrine.
    • New entities in a collection not marked as cascade: persist will produce an Exception and rollback the flush() operation.
    • Collections without new entities are skipped.

    https://www.doctrine-project.org/projects/doctrine...

    /**
     * @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"})
     */
     private $articles;
    Ответ написан
    Комментировать
  • Как решить проблему с маршрутом?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Роуты /search/{region}/{city} и /search — разные роуты

    Я бы остановился на варианте с query параметрами и резолвил бы их в параметры контроллера таким образом:

    https://stackoverflow.com/questions/33982299/symfo...

    Пример экшна
    /**
     * @Route("/search")
     * @ParamConverter("region", converter="querystring")
     * @ParamConverter("city", converter="querystring")
     */
    public function index(string $region,  string $city) 
    {
      return new Response(print_r($name, true));
    }


    class QueryStringConverter implements ParamConverterInterface
    {
        public function supports(ParamConverter $configuration) 
        {
            return 'querystring' == $configuration->getConverter();
        }
    
        public function apply(Request $request, ParamConverter $configuration) 
        {
            $param = $configuration->getName();
            if (!$request->query->has($param)) {
                return false;
            }
            $value = $request->query->get($param);
            $request->attributes->set($param, $value);
        }
    }
    Ответ написан
  • Какая выгода компаниям "растить" джуниоров внутри себя?

    Maksclub
    @Maksclub Куратор тега Карьера в IT
    maksfedorov.ru
    Там, куда мидлы не пойдут:
    - говно-проекты
    - всякие битриксы
    - дикое легаси
    - низкие зп
    - там где на самом деле не очень сложные технологии и уровень джунов с парой месяцев вникания вполне годится, то есть компании могут утилизировать именно такой уровень
    - рыщут среди "джунов" тех, которые мидлы, просто этого не знают

    Не везде факторы работают осознанно (то есть это не заговор и не злодеи), а просто примерно в компании понимают, что эти джуны — то, что им почему-то и нужно или даже единственное доступное
    Ответ написан
    2 комментария
  • Как сделать переадресацию на свою страничку после логирования?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Вам не обязателен id в урле
    Тк после аутентификации /user и будет у каждого своя. Id пользователя будет в сессии (если это обычный браузерный сценарий, а не api)

    Напишите по документации аутентификацию, роут /user закройте для неаутентифицированных

    Вот пример:
    Ответ написан
    Комментировать
  • Как спроектировать фреймворк?

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

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Ассерты ничего не возвращают
    Ответ написан
    Комментировать
  • Как создать разные классы под разные роли в Spring Security?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Для системы аутентификации и авторизации не нужно никаких доп.сущнсотей и классов, обслуживающих их
    разным ролям нужны сильно различающиеся наборы полей

    Не нужно, это др сущности (абстракции), а для проверки роли и авторизационных кредденшнлов вам достаточно класса User

    Дальше уже работайте со своими админами (Admin), покупателями (Customer) и прочее, у которых только будет userId и только... То есть сервис по работе с покупателем будет с ним и работать, а попадет исполнение кода туда, когда вы вызовете метод контроллера, который с этой логикой и работает, и перед этим спросит права у юзера :)

    User — это про права и роли, потому абстрактно так и называется он :)
    Ответ написан
    1 комментарий
  • Есть ли способ получить id entity сразу после создания?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Сгенерируйте UUID например в конструкторе при создании новой сущности и все
    Зачем призывать ORM для такой простой обязанности? Зачем OBJECT RELATION MAPPIN (вздумайтесь только от термина) для генерации id?

    Тем более вижу, что в number он уже юзается

    затем сохраняю это через CrudRepository, получается в объект Policy теперь есть id

    Id в вашем способе появляется во время persist, именно тогда в UoW генерируется Id (делая лишний запрос в БД), предлагаю не делать как это привыкло большинство, а делать так, как привыкли делать, думая о хороше дизайне — в конструкторе генерируйте
    Ответ написан
  • Чем array_walk лучше foreach?

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