Задать вопрос
  • Версионность API в Symfony?

    IgorPI
    @IgorPI Автор вопроса
    Максим Федоров, Это понятное дело.

    Но что если в версии 2 нам это ненужно, а в 1 версию ломать не следует.
  • Версионность API в Symfony?

    IgorPI
    @IgorPI Автор вопроса
    При последующих мажорных версияъ, например больше не планируется использование сущности User, а предположим что вместо User это будет Account

    User и Account кардинально различаться.

    Как мы понимаем это таблицы в базе данных.

    users
    accounts

    Если требуется исключить сущность в следующем релизе.
    Тут вполне резонный вопрос.
    Зачем нам нужна таблица users в версии v2?
  • Версионность API в Symfony?

    IgorPI
    @IgorPI Автор вопроса
    tommy-vercetti, Отличное дополнение.
  • Версионность API в Symfony?

    IgorPI
    @IgorPI Автор вопроса
    Предположим, а что если проект кардинально изменит ряд своих модулей.
    Или концепция поменяется.

    Что тогда?

    Эта модель перестанет отвечать требованиям, даже если мы нормальные ребята.
  • Версионность API в Symfony?

    IgorPI
    @IgorPI Автор вопроса
    Максим Федоров,

    Да, это рассматриваем, тоже.
    Наверное это самый первый вариант, который пришёл в голову.
    Нам он показался простым, но надёжным.

    В аннотации имени класса можно указать прификс.

    Спасибо.
  • Как обнулить или объединить миграции и оставить одну?

    IgorPI
    @IgorPI
    Просто нужно установить DoctrineMigrationsBundle
    И всё сразу встанет на места свои.
  • Как обнулить или объединить миграции и оставить одну?

    IgorPI
    @IgorPI
    Александр Владимирович,

    doctrine:migrations:dump-schema

    Для этого следует установить

    composer require doctrine/doctrine-migrations-bundle "^3.0"
  • ЧПУ Opencart на больших объемах данных?

    IgorPI
    @IgorPI Автор вопроса
    Максим Федоров,

    на кой на каждый запрос 2млн записей обрабатывать?

    Этот вопрос себе уже задавал.
    Само решение не предназначено для большого объема данных.

    Самое забавное, что у моих коллег таким образом работает 200 сайтов.
    Я немного обескуражен.

    Я не хочу вдаваться в подробности, видно что это не верный подход.

    Когда они загрузили 2 мл. данных, они столкнулись с серьёзной проблемой.
    Сейчас они обратились ко мне за поиском решения проблемы.

    В голову нечего не приходит, кроме как выкинуть этот модуль.

    Может кусками как-то по 200-300-500? И складывать? Это типа отчета?

    На момент запроса мы не знаем сколько нужно достать данных для формирования ЧПУ.

    Итог.
    Решили не использовать это решение.
  • Как восстановить файл диска виртуальной машины для докера (Hyper-V)?

    IgorPI
    @IgorPI Автор вопроса
    Я пробовал его монтировать как виртуальный диск, в Управление компьютером > Управление дисками

    Получаю ошибку

    5e8a3e40c519b445898585.png
    5e8a3e7dbb162226792264.png

    Пробовал его расширить или конвертировать в VHD.
    Конвертация успешная, но результат не меняется.

    Дело в том, что этот диск созданный докером / hyper-v и когда все работало, так же был примонтирована папка с другого тома.
    Возможно это как то повлияло на его структуру.

    Я уже не надеюсь, что этот диск закрутится в докере, да и не нужно, мне нужно достать некоторые данные из него.

    Да, хранение данных в докере не лучшая идея.
    Эти данные были в работе и по завершению я планировал их извлечь и сохранить, но не успел, сбой произошёл раньше.
  • Почему anime.js не работает по клику во vuejs?

    IgorPI
    @IgorPI
    Или так

    <button type="button" class="testClick" @click="() => { testClickGo().restart() }">+</button>
  • Как организовать резервирование несколько машин?

    IgorPI
    @IgorPI
    А разве нельзя подключить как сетевые диски?
    Я думаю это максимально просто.
    Настроить планировщик, что бы в определенное время выполнял архивацию.
  • Можно ли пометить файлы в windows так, чтобы потом их найти в интернете по этой метке?

    IgorPI
    @IgorPI
    Добавлю, как минимум, если вы подпишите электронной подписью вы можете подать в суд за использование или подделку вашей интеллектуальной собственности.

    Ну это если вы официально выполните все процедуры.
    Крипто-Про Российский монополист в сфере криптографических документов.

    Если я нечего не путаю.
  • Оптимизация запросов mysql?

    IgorPI
    @IgorPI
    Кирилл Несмеянов,

    Игорь, это в каких таких случаях нельзя избежать запросов в циклах? За всю мою практику не сталкивался с такими.


    Я часто использую ORM в своих проектах, моя цель абстрагироваться от SQL это имеет косвенное отношение к вопросу.

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

    Обратите внимание на пример.
    Сколько нужно выполнить запросов в базу данных что бы построить такое дерево?
    Каждый объект представляет собой отдельную таблицу.

    spoiler

    {
      "requestId": "1574271202704349-1790775956-vla1-4335",
      "title": "Роснефть",
      "description": "Респ. Ингушетия, Назрановский, г. Назрань, ул. Осканова, пересечение с улицей Ахриева",
      "address": "Респ. Ингушетия, Назрановский, г. Назрань, ул. Осканова, пересечение с улицей Ахриева",
      "coordinates": [
        44.776723,
        43.234627
      ],
      "bounds": [
        [
          44.7277515,
          43.17685945
        ],
        [
          44.8256945,
          43.29233945
        ]
      ],
      "displayCoordinates": [
        44.776723,
        43.234627
      ],
      "businessImages": {
        "logo": {
          "urlTemplate": "https://avatars.mds.yandex.net/get-altay/1372264/2a00000165190266461a9953f91cc8bf1dbf/%s"
        }
      },
      "ratingData": {
        "ratingCount": 8,
        "ratingValue": 2.5999999046325684,
        "reviewCount": 1
      },
      "photos": {
        "count": 1,
        "urlTemplate": "https://avatars.mds.yandex.net/get-altay/492546/2a0000015dcb6c8e9d7d54123542adc27f92/%s",
        "items": [
          {
            "link": [],
            "urlTemplate": "https://avatars.mds.yandex.net/get-altay/492546/2a0000015dcb6c8e9d7d54123542adc27f92/%s"
          }
        ],
        "panoramas": []
      },
      "logId": "dHlwZT1iaXpmaW5kZXI7aWQ9MTU0ODY1MzM5OQ==",
      "type": "business",
      "id": "1548653399",
      "shortTitle": "Роснефть",
      "additionalAddress": "",
      "fullAddress": "Респ. Ингушетия, Назрановский, г. Назрань, ул. Осканова, пересечение с улицей Ахриева",
      "postalCode": "",
      "chain": {
        "id": "2069930360",
        "name": "Роснефть",
        "seoname": "rosneft"
      },
      "addressDetails": {
        "locality": "Назрань"
      },
      "phones": [
        {
          "number": "8 (800) 200-10-70",
          "type": "phone",
          "extraNumber": "",
          "info": ""
        },
        {
          "number": "8 (800) 500-25-45",
          "type": "phone",
          "extraNumber": "",
          "info": ""
        }
      ],
      "categories": [
        {
          "name": "АЗС",
          "class": "gasstation",
          "seoname": "gas_station",
          "pluralName": "АЗС",
          "id": "184105274"
        }
      ],
      "status": "open",
      "workingTimeText": "ежедневно, круглосуточно",
      "workingTime": [
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ],
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ],
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ],
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ],
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ],
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ],
        [
          {
            "from": {
              "hours": 0,
              "minutes": 0
            },
            "to": {
              "hours": 0,
              "minutes": 0
            }
          }
        ]
      ],
      "currentWorkingStatus": {
        "isOpenNow": true,
        "text": "Круглосуточно",
        "shortText": "24 ч"
      },
      "tzOffset": 10800,
      "businessLinks": [],
      "socialLinks": [
        {
          "href": "http://vk.com/rosneftru",
          "name": "ВКонтакте",
          "type": "vkontakte"
        },
        {
          "href": "http://www.facebook.com/RosneftRu",
          "name": "Facebook",
          "type": "facebook"
        },
        {
          "href": "http://www.twitter.com/RosneftRU",
          "name": "Twitter",
          "type": "twitter"
        },
        {
          "href": "https://vk.com/azk_rosneft",
          "name": "ВКонтакте",
          "type": "vkontakte"
        },
        {
          "href": "https://www.instagram.com/rosneft_official/",
          "name": "Instagram",
          "type": "instagram"
        }
      ],
      "urls": [
        "http://www.rosneft-azs.ru/",
        "http://www.rosneft.ru/",
        "https://www.rn-card.ru/"
      ],
      "features": [
        {
          "id": "fuel",
          "value": [
            "Супер-ДТ",
            "Евро-ДТ",
            "ДТ",
            "АИ-98",
            "АИ-95",
            "АИ-92",
            "ДТ ЕВРО-5",
            "АИ-98+"
          ],
          "name": "топливо",
          "type": "enum"
        }
      ],
      "businessProperties": {
        "snippet_show_title": "short_title",
        "snippet_show_category": "no_category",
        "snippet_show_address": "short_address",
        "snippet_show_photo": "logo",
        "snippet_show_work_hours": "today_work_hours",
        "snippet_show_bookmark": "show_bookmark",
        "snippet_show_verified": "show_verified",
        "snippet_show_rating": "no_rating",
        "snippet_show_subline": [
          "fuel"
        ],
        "snippet_show_eta": "show_eta",
        "snippet_show_geoproduct_offer": "show_geoproduct_offer",
        "detailview_show_claim_organization": "show_claim_organization",
        "deatailview_show_feedback_button": "show_feedback_button",
        "detailview_show_reviews": "show_reviews",
        "detailview_show_add_photo_button": "show_add_photo_button"
      },
      "seoname": "rosneft",
      "geoId": 1092,
      "uri": "ymapsbm1://org?oid=1548653399",
      "uriList": [
        "ymapsbm1://org?oid=1548653399"
      ],
      "references": [
        {
          "id": "1748486148",
          "scope": "nyak"
        }
      ],
      "sources": [
        {
          "id": "yandex",
          "name": "Яндекс",
          "href": "https://www.yandex.ru"
        }
      ],
      "analyticsId": "1",
      "region": {
        "id": 1092,
        "hierarchy": [
          225,
          11012,
          1092
        ],
        "name": "nazran",
        "bounds": [
          [
            44.720411999999996,
            43.16748320176417
          ],
          [
            44.80887,
            43.283915201764174
          ]
        ],
        "names": {
          "ablative": "",
          "accusative": "Назрань",
          "dative": "Назрани",
          "directional": "",
          "genitive": "Назрани",
          "instrumental": "Назранью",
          "locative": "",
          "nominative": "Назрань",
          "preposition": "в",
          "prepositional": "Назрани"
        },
        "longitude": 44.764641,
        "latitude": 43.225727,
        "zoom": 13
      },
      "breadcrumbs": [
        {
          "name": "Карты",
          "type": "root",
          "url": "https://yandex.ru/maps/"
        },
        {
          "name": "Назрань",
          "type": "region",
          "url": "https://yandex.ru/maps/1092/nazran/",
          "region": {
            "center": [
              44.764641,
              43.225727
            ],
            "zoom": 13
          }
        },
        {
          "name": "АЗС",
          "type": "search",
          "url": "https://yandex.ru/maps/1092/nazran/category/gas_station/"
        },
        {
          "chain": {
            "id": "2069930360",
            "name": "Роснефть",
            "seoname": "rosneft",
            "center": [
              44.776723,
              43.234627
            ]
          },
          "name": "Роснефть",
          "type": "chain",
          "url": "https://yandex.ru/maps/1092/nazran/chain/rosneft/2069930360/"
        }
      ]
    }



    Например ORM не всегда может достать данные за один запрос, да и не всегда это нужно.
    Опять же, речь не об ОРМ, а о том что можно, а чего нельзя.

    Спасибо.
  • Оптимизация запросов mysql?

    IgorPI
    @IgorPI
    В некоторых случаях нельзя избежать запросов в цикле или скажем так. Нельзя выбрать за один запрос.

    Полагаю Вам
    Нужно воспользоваться "джоинами"

    Ваша задача тривиальна.
  • Symfony, Argument resolver используется по назначению?

    IgorPI
    @IgorPI Автор вопроса
    Максим Федоров,

    Предлагаю вынест ив отдельный вопрос


    Да, возможно.
    Я думаю что вопрос актуальный.
    Вопрос будет заключиться в том, какова практика резольверов в области валидации.
  • Событие для сущности перед её обновлением?

    IgorPI
    @IgorPI Автор вопроса
    Максим Федоров, Точно.

    Опять в точку.
    Об этом я не подумал.

    Вот полный код листенера

    <?php
    
    
    namespace App\Listeners\Category;
    
    
    use App\Entity\CategoryProduct;
    use Doctrine\ORM\Event\PreFlushEventArgs;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\RequestStack;
    
    /**
     * Class SaveImageInListener
     * @package App\Listeners\Category
     */
    class SaveImageInListener
    {
        private array $white_mime_list = [
            "image/jpeg" => "jpeg",
            "image/jpg" => "jpg",
            "image/png" => "png",
        ];
        private $images_directory;
        /** @var Request|null */
        private ?Request $request;
        /** @var bool */
        private bool $computed;
    
        /**
         * SaveImageInListener constructor.
         * @param RequestStack $requestStack
         * @param $images_directory
         */
        public function __construct(RequestStack $requestStack, $images_directory)
        {
            $this->images_directory = $images_directory;
            $this->request = $requestStack->getCurrentRequest();
            $this->computed = false;
        }
    
    
        /**
         * @param CategoryProduct $entity
         * @param PreFlushEventArgs $eventArgs
         * @return string
         */
        public function save(CategoryProduct $entity, $eventArgs)
        {
            if ($this->computed === false) {
                if ($this->support()) {
                    foreach ($this->white_mime_list as $mmt => $ext) {
                        if ($mmt == $this->getMimeType()) {
                            $file_name = sprintf("%s-%s.%s", md5($this->getImageContentBase64()), uniqid(), $ext);
                            $relative_path = sprintf("/sale_point_%s/categories/%s", $entity->getSalePoint()->getId(), $file_name);
                            $absolute_path = sprintf("%s%s", $this->images_directory, $relative_path);
    
                            if (!is_dir(dirname($absolute_path))) {
                                mkdir(dirname($absolute_path), 0777, true);
                            }
    
                            // Удаление предыдущей версии файла, если это обновление
                            if (is_file($this->images_directory . $entity->getImage()))
                                @unlink($this->images_directory . $entity->getImage());
    
                            $entity->setImage($relative_path);
    
                            $this->computed = true;
                            $eventArgs->getEntityManager()->getUnitOfWork()->computeChangeSets();
    
                            @file_put_contents($absolute_path, base64_decode($this->getImageContentBase64()));
                        }
                    }
                }
            }
        }
    
        /**
         * @return bool
         */
        private function support()
        {
            if ($this->request->get("image", false)) {
                return true;
            }
            return false;
        }
    
        /**
         * @return mixed
         */
        private function getImageContentBase64()
        {
            $request_image = $this->request->get("image", false);
            return $request_image["content"];
        }
    
        /**
         * @return mixed
         */
        private function getMimeType()
        {
            $request_image = $this->request->get("image", false);
            return $request_image["mime_type"];
        }
    }


    Этот слушатель специально сделан для загрузки изображения.
    В цикле не планируется модификация.

    А если и будет, то там есть условие

    ...
    if ($this->support())
    ...


    Оно контролирует.

    Но я понял в чем моя ошибка.

    Спасибо.
  • Symfony, Argument resolver используется по назначению?

    IgorPI
    @IgorPI Автор вопроса
    В первом случае, если админ авторизовался, то он может скомпрометировать запрос и подставить ID продукта из другой торговой точки, тем самым поменять значение.
    А этого не хочется.