• Как использовать Jms Serializer с Doctrine с настройкой Lazy?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Аннотация @Accessor

    /** @Accessor(getter="getName") */
    private $name;
    
    public function getName()
    {
         return $this->name;
    }

    При вызове указанного геттера произойдет вызов и запрос. Соответственно lazy вернет результат.

    Если yaml, то в той же доке указано как задать аксессор.
    Не забудьте почистить кеш (не всегда чистится консольной командой, удалите папку jms - когда с 3й работал, то были такие глюки) .


    А вообще, если пишите с нуля, то знайте — от JMS Serializer все уходят в сторону Symfony Serializer
    В контейнере уже должен быть у вас сервис @serializer сразу после установки компонента и можно просто заинжектить через SerializerInterface в конструкторе
    Ответ написан
    5 комментариев
  • Как реализовать облачное хранилище?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Для облачного хранилищ нужно облако (логично, судя по названию)
    Потому нужно создать это самое облако -- начните с OpenStack (на вики)
    PHP SDK: https://github.com/php-opencloud/openstack

    Посмотрите в сторону Swift (на вики)из OpenStack
    https://www.openstack.org/software/releases/train/...

    не работал с данным стеком
    Ответ написан
    Комментировать
  • Как в spring вернуть лист объектов?

    Maksclub
    @Maksclub
    maksfedorov.ru
    @Repository
    class ShipRepository {
     
        @PersistenceContext
        private EntityManager entityManager;
     
        @Override
        public List<Ship> findLimitedTo(int limit) {
            return entityManager.createQuery("SELECT s FROM Ship s ORDER BY s.id",
              Ship.class).setMaxResults(limit).getResultList();
        }
    }
    Ответ написан
    1 комментарий
  • Как при выполнении Carbon->addDays(int) не обновлять состояние?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    We also provide CarbonImmutable class extending DateTimeImmutable. The same methods are available on both classes but when you use a modifier on a Carbon instance, it modifies and returns the same instance, when you use it on CarbonImmutable, it returns a new instances with the new value.

    https://carbon.nesbot.com/docs/


    CarbonImmutable при изменении данных создает новый обьект, не меняя старый. Так как работает на основе DateTimeImmutable:
    https://www.php.net/manual/ru/class.datetimeimmuta...
    Ответ написан
    1 комментарий
  • В Rust стрелочка -> в объявлении функции foo()->i32{ для красоты?

    Maksclub
    @Maksclub
    maksfedorov.ru
    носит чисто декоративный характер или как то помогает парсеру?

    Скорее лексеру обнаружить нужные токены/лексемы

    В данном докладе язык PHP, но не пугайся! Кирилл Несмеянов очень наглядно и доступно показал как в целом устроены парсеры и лексеры некого абстрактного языка:
    https://youtu.be/zZTv7HMxKXI?t=16074
    Ответ написан
  • Как добавить в ассоциативный массив значение attributes() эллемента xml?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Когда вы превращает документа в SimpleXMLElement, то каждая дочернаяя нода тоже таковой становится и у нее также есть свой набор атрибуттов $element->attributes()
    Итоговый код

    <?php
    
    $string = <<<XML
    <offer id="130" available="true" >
    <url>http://api.loc/index.php?route=product/product&amp;path=3899&amp;product_id=130</url>
    <price>850</price>
    <currencyId>UAH</currencyId>
    <categoryId>3899</categoryId>
    <delivery>true</delivery>
    <stock_quantity>100</stock_quantity>
    <name>Босоножки 82BLUE р. 27 17,5 см Синий</name>
    <vendor>(производитель не указан)</vendor>
    <barcode>200</barcode>
    <param name="Размер обуви">46</param>
    <param name="Размер стельки">19</param>
    </offer>
    XML
    ;
    
    $xml = new SimpleXMLElement($string);
    
    $params = [];
    // Все ноды с тегом param ушли в массив, каждый из из которых  SimpleXMLElement
    foreach($xml->param as $param) {
        // а также @attributes, в котором все атрибуты текущего элемента, достаем тот, что name
        $paramName = $param->attributes()['name'];
        $params[(string) $paramName] = (string) $param;
    }
    
    var_dump($params);
    // [
    //     "Размер обуви"   => string(2) "46"
    //     "Размер стельки" => string(2) "19
    // ]


    UPD: Чтобы руками все не писать и не гадать, какой параметр пришел каким по счету (а могут прийти в одной выгрузке в разном порядке из-за того, что у одного товара просто не указан один из параметров, то предлагаю сделать так:

    1. Завести карту всех соответствий
    $featuresMap = [
        'Размер обуви' => 'size',
        'Размер стельки' => 'stelka',
    ];

    2. И уже динамически собирать с каждого элемента по этой карте параметры
    foreach($xml->param as $param) {
        $paramName = $param->attributes()['name'];
        $paramAlias = $featuresMap[(string) $paramName]
        $params[$paramAlias] = (string) $param;
    }


    И тогда вам нужно будет только расширять свою карту соответствий, а код цикла всегда будет оставаться одним и тем же. Ну добавив пару проверок и например транслитерировать новые значения, добавляя их в БД, и карту уже брать из той же БД.
    Ответ написан
  • Как в типизированных свойствах задать массив типа?

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

    class Bar
    {
        /** @var ArrayCollection|Bar[] */
        public ArrayCollection $props;
    }


    Для решения вашей задачи нужен еще один виток развития языка :)

    НЕсуществующий код!
    class ArrayCollection<T>
    {
        public getElement(): <T>;
        public addElement(<T> $element): void;
    }
    
    class Bar
    {
        public ArrayCollection<Bar> $barCollection;
    }


    Единственное, можно свои коллекции прокачать на проверку типа при создании объекта этой коллекции
    Ответ написан
    Комментировать
  • Что за Undefined offset?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    У вас дампится все отлично — если увидите, на скрине вверху есть слово login
    Очевидно код срабатывает еще раз, там где нет метода и крашится, тк в новый раз этих данных нет...

    Чтобы это узнать, перед получением $s сделайте:
    dd(get_class($event->getController()));
    И покажите полный вывод ВСЕХ значений...

    Вообще потратьте время и поставьте xDebug, вы бы все поняли в течение 2 секунд что и куда прилетает и почему...

    Если выбрали дебаг как раньше на коленке, то у симфы есть функция dump(), все вызовы которой выводятся в панеле разработчика!
    Ответ написан
  • Как спарсить этот JSON?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    <?php
    
    $jsonProducts = '[
      {
        "market_name": "T-shirts",
        "size": "M"
      },
      {
        "market_name": "T-shirts",
        "size": "L"
      }, 
      {
        "market_name": "Jacket",
        "size": "M"
      }, 
      {
        "market_name": "Jeans",
        "size": "XL"
      }
    ]';
    
    $jsonPrice = '{
        "data": [
            {
              "updated_at": 1576048969000,
              "prices": {
                "last": 5300
              },
              "name": "Jacket"
            },
            {
              "updated_at": 1576048969000,
              "prices": {
                "last": 2000.12
              },
              "name": "T-shirts"
            }
        ]
    }';
    
    $products = json_decode($jsonProducts, true);
    $price = array_column(json_decode($jsonPrice, true)['data'], 'prices', 'name');
    
    $result = array_map(function($item) use ($price) {
        $product              = new \stdClass();
        $product->market_name = $item['market_name'];
        $product->size        = $item['size'];
        $product->price       = $price[$item['market_name']]['last'] ?? null;
        
        return $product;
    }, $products);
    
    $result = json_encode($result, JSON_PRETTY_PRINT);
    
    var_dump($result);
    // [
    //     {
    //         "market_name": "T-shirts",
    //         "size": "M",
    //         "price": 2000.12
    //     },
    //     {
    //         "market_name": "T-shirts",
    //         "size": "L",
    //         "price": 2000.12
    //     },
    //     {
    //         "market_name": "Jacket",
    //         "size": "M",
    //         "price": 5300
    //     },
    //     {
    //         "market_name": "Jeans",
    //         "size": "XL",
    //         "price": null
    //     }
    // ]


    sandbox.onlinephpfunctions.com/code/935656788a07af...
    Ответ написан
  • DI: как инстанциировать реализацию интерфейса с кастомным значением параметра конструктора?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Используйте фабрику:

    - В конфиге контейнера
    // регайте ваш интерфейс, но ссылаясь на метод фабрики,
    // которая и произведет ваш сервис
    \App\Writer\WriterInterface::class => DI\factory('\App\Writer\TextWriterFactory::create'),

    - Код фабрики:
    class TextWriterFactory implements WriterFactoryInterface
    {
        public function __construct(Settings $settings, DataConverter $dataConverter)
        {
            $this->settings = $settings;
            $this->dataConverter = $dataConverter;
        }
    
        public function create(string $filePath): WriterInterface
        {
            return new TextWriter($this->settings, $this->dataConverter, $filePath);
        }
    }


    Источник: php-di.org/doc/php-definitions.html#factories
    Ответ написан
  • Как переписать preg_replace_callback()?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Callback можно задавать как
    Как массив объекта и его метода: [$obj, 'myCallbackMethod']
    Для статического метода: [MyClass::class, 'myCallbackMethod']
    Другой способ для статического метода: 'MyClass::myCallbackMethod'

    Пример для вас:
    <?php
    
    class TestListener
    {
      //   сигнатуру тут лишнюю для простоты примера просто убрал
      public function onContentPrepare(&$row) {
    
        $row->text = preg_replace_callback('|{gold}|', [$this, 'insertgold'], $row->text);
      } 
    
      public function insertgold(array $matches)
      {
          return $matches[0] . 'Called';
      }
    }
    
    
    // Example
    $string = new stdClass();
    $string->text = 'TestText with gold  and gold ';
    
    $listener = new TestListener();
    $listener->onContentPrepare($string); 
    var_dump($string->text ); //TestText with goldCalled  and goldCalled
    Ответ написан
  • Чем представлена абстракция (принцип ООП) в Java?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Абстракция — ключевое явление в ООП

    Сам класс — уже абстракция чего-то, когда я создаю класс Product, то это абстракция некоторых объектов моей системы, что их отличает от всего внутреннего мира системы уже как минимум названием (и потом интерфейсом и поведением, описанным в классе).

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

    Также мы можем абстрагировать некий функционал от привязки к конкретному типу. И создать функционал над абстрактным (обобщенным) типом — дженерики (параметрический полиморфзм).

    Наследование, инкапсуляция и полиморфизм — ключевые способы для создания абстракции.
    • Полимофризм — создаем или интерфейс или абстрактный класс, что очертит границы абстракции и уже в конкретных реализациях абстракцию "материализуем". Или создаем некий класс, который работает с любым типом, но строго указанным при создании объекта (параметрический полиморфизм)
    • Наследование — похожее поведение у ряда классов выносим в абстракцию (родительский класс, абстрактный класс)
    • Инкапсуляция — очищаем абстракцию, отдав наружу только публичный интерфйес (границы абстракции), все остальное (не относящиеся к нашей абстракции) прячем
    Ответ написан
    Комментировать
  • Как разрулить конфликт зависимостей composer?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Если под 3 версию не хватает адаптеров, то нужно:
    • либо доработать адаптеры под 3-ю версию и внести в клад в опенсорс,
    • либо сделать форк 2 версии для самой библиотеки и для common, адаптировать common (форк) под работу с symfony/http-foundation 4 версии, выложить на Packagist и затянуть к себе уже свой форк


    Приходилось как-то пару раз мутыжиться со вторым способом... гемморно, но нужно было
    Может так статься, что адаптер форкнуть будет проще
    Ответ написан
    9 комментариев
  • Что является связующим звеном между backend и frontend?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Связующее звено — веб-сервер

    Как правило это Nginx, но может быть и голый сервер на том языке, на котором сделан бекенд.
    Работает по принципу запрос-ответ. Например сделал запрос через GET/POST, не важно — через AJAX (JS) или напрямую, запрос попадает на бекенд и обрабатывается, летит ответ и вы с ним работаете.

    Также браузеры поддерживают протокол вебсокет.
    Ответ написан
    23 комментария
  • Как решить проблему с set(), get()?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Вывести откуда? Если из бд, то посмотрите в сторону active record и data mapper (repository) — лучше последний. Есть уже готовые интерфейсы: JPA

    Сеттеры и геттеры переменных вам ничем не помогут, тк дают доступ к свойствам вашей бизнес-сущности (и вообще делают его структурой) , а вот как они заполнятся — дело не данного обьекта (кроме Active Record паттерна), ровно как и вывод коллекции этих объектов, и точно не сортировкой заниматься.
    Ответ написан
    Комментировать
  • Как асинхронно выполнить скирпт php?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Возьмите любой асинхронный фреймворк на php:
    RoadRunner
    ReactPHP

    С помощью него запускайте свой воркер
    И результат через веб-сокет отдавайте на клиент
    Ответ написан
    Комментировать
  • Почему PHP требует Apache или Nginx чтобы работать в docker контейнере?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    какой смысл использовать Apachе или Nginx содержащий образ? Разве нельзя работать с контейнером содержащим только php?

    Разве нельзя работать с контейнером содержащим только php?

    Можете. Вы можете поставить PHP-CLI контейнер и работать с ним без веб-сервера конечно же
    FROM php:7.1-cli
    Что позволит вам запускать консольные команды (композер туда же)

    Если ставите PHP-FPM контейнер, то понятное дело вам нужен веб-сервер (гуглите принцип работы с Fast CGI).
    Нужен, если вы хотите общаться с приложением через HTTP
    FROM php:7.1-fpm
    Ответ написан
    1 комментарий
  • Как правильно писать глубокие интеграционные тесты?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Эти тесты функциональные строят обычно на фикстурах:
    - загружается состояние системы (например БД) до необходимого, например загружается категория КА и товар ТА
    - поднимается приложение или достаточное число сервисов для теста
    - проводится тест (например добавляется товар дублер товар ТА и система должна ругнуться или удаляется товар, которого нет, например товар ТБ)

    И так для каждого кейса — для него подгоняется состояние. Необходимо, чтобы тест все же должен быть относительно изолированным. Для некоторых тестов состояние одно и инструкции его поднятия будут одинаковы. Кроме того это быстро и проще.
    Для скорости тестов обычно берут in memory БД — это еще одна важная причина использовать сложные хорошие ORM, которые могут работать и с примитивными базами в памяти и с полноценными, отделяя код и работу с данными. Разница во времени по сравнению с реальным БД сильно выше.

    Вообще эти тесты сложные и потому их число как правило сильно меньше простых юнитов... Кроме того иногда уже имеет смысл делать это через приемочные (браузерные) тесты
    Ответ написан
  • Зачем в catch делать throw?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    try {
        $this->initDBConnect();
    } catch (\Exception $e) {
        // Тут залогировали
       $this->logger->error('Некоторое сообщение', [некоторые данные]);
    
        // тут выкинули дальше
        // или throw new MyAnyException, 
        // а не просто дальше выкидывать тоже самое
        throw $e; 
     }


    Для чего бросать дальше
    Например идет процесс оплаты товара, в клиенте выкинулось исключение... мы в слое работы с АПИ платежки поймали исключение и залогировали, но выкинули дальше, чтобы наша система выше поймала, откатила транзакцию и плюнула ошибкой уже своей для слоя выше
    Ответ написан
    3 комментария
  • В каких случаях при разработке сайта на PHP лучше использовать не MVC (и его подобия), а какой-нибудь другой подход?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Об архитектуре нужно обязательно почитать Робкрта Мартина: Чистая архитектура
    Ответ написан
    Комментировать