• Как реализовать десериализацию иерархии вложенных объектов с помощью Symfony Serializer?

    @sgidlev
    Я смог решить через JMS serializer.

    /**
         * @var CustomerShipmentRequest $shipment
         * @Assert\Valid
         * @Assert\NotBlank(message="Поле 'shipment' обязательно.")
         * @Serializer\Type("Type\Common\Models\Customer\CustomerShipmentRequest")
         */
        private CustomerShipmentRequest $shipment;


    И сама десериализация

    // Сериализуем данные в объект
                /** @var CustomerRequestModelInterface $customerRequest */
                $customerRequest = SerializerBuilder::create()->build()->deserialize(
                    $jsonData,
                    $requestModel,
                    'json'
                );


    И есть способ через Симфони

    $encoder = [new JsonEncoder()];
            $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
            $normalizer = [new ArrayDenormalizer(), new ObjectNormalizer(null, null, null, $extractor)];
            $serializer = new Serializer($normalizer, $encoder);
            $result = $serializer->deserialize($jsonData, CustomerRequestModel::class,'json');
    Ответ написан
    Комментировать
  • ООП. Как избежать передачи флаг как аргумента функции?

    @sgidlev Автор вопроса
    Моё решение сейчас такое (на примере обработки класса сотрудника управляющей компании):

    Сервис сотрудника управляющей компании (методы, которые обрабатываются из контроллера)
    ManagementEmployeeService
    <?php
    declare(strict_types=1);
    
    namespace App\Feature\Management\Service;
    
    use App\Application\Model\Response\IdResponse;
    use App\Feature\Management\Entity\ManagementEmployee;
    use App\Feature\Management\Mapper\ManagementEmployeeMapper;
    use App\Feature\Management\Mapper\ManagementMapper;
    use App\Feature\Management\Model\Employee\ManagementEmployeeDetails;
    use App\Feature\Management\Model\Employee\ManagementEmployeeRequest;
    use App\Feature\Management\Repository\ManagementEmployeeRepository;
    use App\Feature\User\Mapper\UserMapper;
    
    readonly class ManagementEmployeeService
    {
        public function __construct(
            private ManagementEmployeeRepository    $employeeRepository,
            private ManagementEmployeeUpsertService $upsertService
        )
        {
        }
    
        public function getEmployee(int $id): ManagementEmployeeDetails
        {
            $employee = $this->employeeRepository->getById($id);
    
            return ManagementEmployeeMapper::mapEmployeeDetails($employee)
                ->setUser(UserMapper::mapUser($employee->getUser()))
                ->setManagement(ManagementMapper::mapManagement($employee->getManagement()));
        }
    
        public function deleteEmployee(int $id): void
        {
            $employee = $this->employeeRepository->getById($id);
            $this->employeeRepository->removeAndCommit($employee);
        }
    
        public function createEmployee(ManagementEmployeeRequest $request): IdResponse
        {
            $employee = $this->upsertService->createUpsert((new ManagementEmployee()), $request);
            $this->employeeRepository->saveAndCommit($employee);
    
            return new IdResponse($employee->getId());
        }
    
        public function updateEmployee(int $id, ManagementEmployeeRequest $request): void
        {
            $employee = $this->upsertService->updateUpsert($this->employeeRepository->getById($id), $request);
            $this->employeeRepository->saveAndCommit($employee);
        }
    
    }


    Сервис, который позволяет выбрать нужный метод по обработке данных (создание или обновление)
    ManagementEmployeeUpsertService
    <?php
    declare(strict_types=1);
    
    namespace App\Feature\Management\Service;
    
    use App\Feature\Management\Entity\ManagementEmployee;
    use App\Feature\Management\Model\Employee\ManagementEmployeeRequest;
    use App\Feature\Management\Model\Employee\Upsert\AbstractManagementEmployeeUpsert;
    use App\Feature\Management\Model\Employee\Upsert\ManagementEmployeeUpsertManager;
    
    readonly class ManagementEmployeeUpsertService
    {
        public function __construct(
            private ManagementEmployeeUpsertManager $upsertManager)
        {
        }
    
        public function createUpsert(ManagementEmployee $employee, ManagementEmployeeRequest $request): ManagementEmployee
        {
            return $this->upsert($this->upsertManager->getCreateUpsert(), $employee, $request);
        }
    
        public function updateUpsert(ManagementEmployee $employee, ManagementEmployeeRequest $request): ManagementEmployee
        {
            return $this->upsert($this->upsertManager->getUpdateUpsert(), $employee, $request);
        }
    
        public function upsert(AbstractManagementEmployeeUpsert $upsert, ManagementEmployee $employee, ManagementEmployeeRequest $request): ManagementEmployee
        {
            return $upsert->fill($employee, $request);
        }
    
    }


    Сервис-менеджер, который позволяет выбрать конкретный класс по обработке данных
    ManagementEmployeeUpsertManager
    <?php
    declare(strict_types=1);
    
    namespace App\Feature\Management\Model\Employee\Upsert;
    
    readonly class ManagementEmployeeUpsertManager
    {
        public function __construct(
            private CreateManagementEmployeeUpsert $createUpsert,
            private UpdateManagementEmployeeUpsert $updateUpsert
        )
        {
        }
    
        /**
         * @return CreateManagementEmployeeUpsert
         */
        public function getCreateUpsert(): CreateManagementEmployeeUpsert
        {
            return $this->createUpsert;
        }
    
        /**
         * @return UpdateManagementEmployeeUpsert
         */
        public function getUpdateUpsert(): UpdateManagementEmployeeUpsert
        {
            return $this->updateUpsert;
        }
    
    
    }


    Базовый метод обработки данных, к которому обращаются уже конкретные классы
    ManagementEmployeeUpsert
    <?php
    declare(strict_types=1);
    
    namespace App\Feature\Management\Model\Employee\Upsert;
    
    use App\Feature\Management\Entity\ManagementEmployee;
    use App\Feature\Management\Model\Employee\ManagementEmployeeRequest;
    use App\Feature\Management\Repository\ManagementEmployeeRepository;
    use App\Feature\User\Exception\UserIsAlreadyHiredException;
    
    readonly class ManagementEmployeeUpsert
    {
        public function __construct(private ManagementEmployeeRepository $employeeRepository)
        {
        }
    
        public function isUserNotChanged(ManagementEmployee $employee, ManagementEmployeeRequest $request): bool
        {
            return ($employee->getUser() && $employee->getUser()->getId() === $request->getUserId());
        }
    
        public function isUserHired(ManagementEmployee $employee, ManagementEmployeeRequest $request): void
        {
            if ($this->employeeRepository->findByUser($employee->getUser())) {
                throw new UserIsAlreadyHiredException();
            }
        }
    
        public function fill(ManagementEmployee $employee, ManagementEmployeeRequest $request): ManagementEmployee
        {
            $employee->setFired($request->isFired());
    
            if ($request->getPosition() !== null) {
                $employee->setPosition($request->getPosition());
            }
    
            if ($request->getParentId() !== null) {
                $employee->setParentId($request->getParentId());
            }
    
            if ($request->getDescription() !== null) {
                $employee->setDescription($request->getDescription());
            }
    
            if ($request->getData() !== null) {
                $employee->setData($request->getData());
            }
    
            return $employee;
        }
    }


    Абстрактный класс, от которого наследуются конкретные классы по обработке данных
    AbstractManagementEmployeeUpsert
    <?php
    declare(strict_types=1);
    
    namespace App\Feature\Management\Model\Employee\Upsert;
    
    use App\Feature\Management\Entity\ManagementEmployee;
    use App\Feature\Management\Model\Employee\ManagementEmployeeRequest;
    
    abstract class AbstractManagementEmployeeUpsert
    {
        abstract public function fill(ManagementEmployee $employee, ManagementEmployeeRequest $request): ManagementEmployee;
    }
    Ответ написан
  • Как сравнить время маршрутов на автомобиле, общественном транспорте и пешком, и построить самый быстрый?

    @sgidlev Автор вопроса
    Сделал вот так, думаю можно лучше, но не придумал как:
    /* =========== Прокладываем самый быстрый маршрут до ближайшего магазина =========== */
        var routes_array = [];
    
        //Проходимся по каждому маршруту и добавляем их в массив routes_array
        var PromiseRoute = new Promise(function (resolve, reject) {
            var test;
            getRouteLength(startPoint, destPoint, 'auto').then(
                result => {
                    console.log("Fulfilled: " + result);
                    //routes_array.push(result);
                    routes_array.push(result);
                    resolve(routes_array);
                }
            );
    
        }).then(function (result) {
            console.log(result);
            return getRouteLength(startPoint, destPoint, 'masstransit').then(
                result => {
                    console.log("Fulfilled: " + result);
                    //routes_array.push(result);
                    routes_array.push(result);
                    return routes_array;
                }
            );
        }).then(function (result) {
            console.log(result);
            return getRouteLength(startPoint, destPoint, 'pedestrian').then(
                result => {
                    console.log("Fulfilled: " + result);
                    routes_array.push(result);
                    return routes_array;
                }
            );
        });
    
        var FastestRouteTime,
            FastestRouteLength,
            FastestRouteTimeText,
            FastestRouteLengthText;
    
        //Смотрим обобщенный результат
        PromiseRoute.then(
            result => {
                FastestRoute = result[0].Route;
                FastestRouteTime = result[0].RouteTime;
                FastestRouteLength = result[0].RouteLength;
                FastestRouteTimeText = result[0].RouteTimeText;
                FastestRouteLengthText = result[0].RouteLengthText;
    
    
                for (var i = 0, l = result.length; i < l; i++) {
                    //Ищем самый быстрый маршрут
                    if (result[i].RouteTime > 0 && result[i].RouteTime < result[0].RouteTime) {
                        FastestRoute = result[i].Route;
                        FastestRouteTimeText = result[i].RouteTimeText;
                        FastestRouteLengthText = result[i].RouteLengthText;
    
                    }
                }
    
                console.log('FastestRouteTime: ', FastestRouteTime);
                console.log('FastestRouteLength: ', FastestRouteLength);
                $('#route-time').html(FastestRouteTimeText);
                $('#route-length').html(FastestRouteLengthText);
                myMap.geoObjects.add(FastestRoute); //Добавляем самый быстрый маршрут
            }
        );
        /* =========== Прокладываем самый быстрый маршрут до ближайшего магазина =========== */
    
    
        /* =========== Функция для поиска самого быстрого маршрута до ближайшего магазина  =========== */
        function getRouteLength(startPoint, destPoint, rMode) {
            multiRoute = new ymaps.multiRouter.MultiRoute({
                referencePoints: [
                    startPoint,
                    destPoint
                ],
                params: {
                    routingMode: rMode,
                    avoidTrafficJams: true,
                    results: 1,
                }
            }, {
                   // Автоматически устанавливать границы карты так, чтобы маршрут был виден целиком.
                    boundsAutoApply: true
                });
    
            return new Promise(function (resolve, reject) {
                multiRoute.model.events.add("requestsuccess", function () {
                    var routes = multiRoute.model.getRoutes();
                    var minLength = -1;
                    var routeLength = -1;
                    var routeTime = -1;
                    var routeLengthText;
                    var routeTimeText;
    
                    for (var i = 0, l = routes.length; i < l; i++) {
                        //let routeLength =  multiRoute.model.getRoutes().properties.get('distance').value / 1000;
                        routeLength = routes[i].properties.get("distance").value;
                        routeLengthText = routes[i].properties.get("distance").text;
                        routeTime = routes[i].properties.get("durationInTraffic").value;
                        routeTimeText = routes[i].properties.get("durationInTraffic").text;
                        if (minLength < 0 || routeLength < minLength) {
                            minLength = routeLength;
                        }
                        console.log("Длина маршрута " + (i + 1) + ": " + routes[i].properties.get("distance").text);
                        console.log(routeLengthText);
                        console.log("Время маршрута " + (i + 1) + ": " + routes[i].properties.get("durationInTraffic").text);
                        console.log(routeTimeText);
                    }
                    resolve({
                        Route: multiRoute,
                        RouteTime: routeTime,
                        RouteLength: routeLength,
                        RouteLengthText: routeLengthText,
                        RouteTimeText: routeTimeText,
                    });
                });
            });
        }
    
        /* =========== ! Функция для поиска самого быстрого маршрута до ближайшего магазина  =========== */
    Ответ написан
    Комментировать
  • Как поменять места поля в форме в Yii?

    @sgidlev Автор вопроса
    Решение оказалось зарыто в админке.
    Ответ написан
    Комментировать