• Как произвести валидацию данных на стороне сервера в Magento 2?

    @ipokos
    какие данные нужно валидировать?
    Пример:
    Zend_Validate::is($yourRequestData->getEmail(), 'EmailAddress')
    Ответ написан
    1 комментарий
  • Как правильно работать с двумя источниками данных почти одного типа сущности?

    @AlexndrNovikov
    Solution Architect in Spiral Scout
    Ну зачем же дублировать поля
    Оставить одну таблицу products с n полей (общих)
    Добавить отдельную таблицу-маппер products <=> language (сначала предложил вариант с доп полем в самом products, но может быть ситуация когда один продукт есть на двух рынках)
    например со структурой product_id language
    Добавить таблицу extra_fields с полями product_id field_name value - получаем бесконечную масштабируемость разных полей для любого продукта
    favourite_products и users оставляем в прежней схеме
    Ответ написан
    1 комментарий
  • Какие сервисы perfomance metrics/monitoring вы можете посоветовать для приложения на PHP?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    Для мониторинга естественно Sentry, для профилирования - Blackfire
    Ответ написан
    Комментировать
  • Рационально ли внедрять зависимости в класс через DI-контейнер, обходя при этом стороной конструктор и сеттеры?

    @Fantyk
    web developer
    Нет, не так. Суть DI в управлении зависимостями, когда я смотрю конструктор - я должен видеть от чего зависит код. Ваш вариант практически не отличается от использования глобальных переменных/сервис локатора.
    Все современные контейнеры позволяют забиндить интерфейс с реализацией, плюс автовайринг. Для вас, как программиста, даже проще сразу инжектить нужные вам классы, чем просить их у контейнера.


    Принцип инверсии зависимостей (англ. dependency inversion principle, DIP):
    Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

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

    @Flying
    В целом это считается плохой практикой. Приведу ссылку на соответствующий кусок из документации DI контейнера в Symfony: https://symfony.com/doc/current/components/depende...

    Доставая зависимости непосредственно из контейнера вы лишаете себя массы преимуществ внедрения зависимостей:
    • Страдает тестируемость класса т.к. вы не можете подменить сервисы на нужные вам во время тестов
    • Вы лишаете себя возможности валидации целостности графа зависимостей в случае если используется компилируемый контейнер (как, например, в Symfony)
    • Вы привносите в класс излишнюю информацию о названиях конкретных сервисов которые вы достаёте из контейнера
    • Вам потребуется дополнительно проверять есть ли каждый из сервисов в контейнере и что же именно вы достали из контейнера (через instanceof)


    Уверен что есть и другие факторы, это то что пришло на ум в первую очередь.
    Ответ написан
    Комментировать
  • Какой поисковый движок выбрать для базы наименований(товаров, документов, etc.)?

    Sanasol
    @Sanasol
    нельзя просто так взять и загуглить ошибку
    Может быть есть другие, более оптимальные решения?

    вы и назвали самые оптимальные и быстрые решения.
    Там конфиги на пару десятков строк и всё готово.

    А со сфинксом вообще на sql диалекте можно разговаривать, что довольно удобно.
    Ответ написан
    Комментировать
  • Есть ли возможность реализовать автовайринг хэндлеров для команд Tactician в Symfony 4?

    myrkoxx
    @myrkoxx
    developer
    Делал как -то так: https://github.com/thephpleague/tactician-bundle#2...

    Вот мой services.yaml:

    services:
        # default configuration for services in *this* file
        _defaults:
            autowire: true      # Automatically injects dependencies in your services.
            autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
            public: false       # Allows optimizing the container by removing unused services; this also means
                                # fetching services directly from the container via $container->get() won't work.
                                # The best practice is to be explicit about your dependencies anyway.
    
        # makes classes in src/ available to be used as services
        # this creates a service per class whose id is the fully-qualified class name
        App\:
            resource: '../src/*'
            exclude: '../src/{Request,Entity,Migrations,Tests,Kernel.php}'
    
        App\Console\:
            resource: '../src/Console'
            public: true
            tags: ['console.command']
    
        App\Command\:
            resource: '../src/Command'
            tags:
              - { name: tactician.handler, typehints: true }
    
        League\Tactician\CommandBus: '@tactician.commandbus'


    Собственно теперь все Command находяться в папке src/App/Command, и можно больше не париться. Вот пример использования:

    class CreateCliRequest extends ContainerAwareCommand
    {
        /**
         * @var CommandBus
         */
        private $commandBus;
    
        public function __construct(?string $name = null, CommandBus $commandBus)
        {
            parent::__construct($name);
    
            $this->commandBus = $commandBus;
        }
    
        protected function configure()
        {
            $this
                ->setName('create:cli:req')
                ->addArgument('name', InputArgument::REQUIRED)
                ->setDescription('Some command');
        }
    
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $request = new CreateRequest(12, $input->getArgument('name'));
    
            $result = $this->commandBus->handle($request);
    
            $output
                ->writeln('<info>' .$result . '</info>');
        }
    }
    Ответ написан
    5 комментариев
  • Что выведет скрипт?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    4 раза выведет последний ключ массива (тобиш троечку). Как-то не сильно интересная задачка...
    Ответ написан
    Комментировать
  • Почему контейнер с MySQL не хочет подхватывать enviroment переменные из docker-compose.yml?

    Root пароль устанавливается только при "первом запуске" контейнера. Если файлы с данным mysql уже существуют (в вашем случае тут - "./database"), то эта переменная будет игнорироваться.

    Соответственно решением будет изменение пароля вручную либо удаление существующих файлов mysql (с последующим запуском контейнера с нужным вам паролем в MYSQL_ROOT_PASSWORD).

    Удаление контейнеров и образов бесполезно, т.к. директория с данными бд монтируется в контейнер с хост машины.
    Ответ написан
    1 комментарий
  • Как грамотно реализовать выборку из MySQL базы в такой ситуации?

    longclaps
    @longclaps
    SQL не годится для этой задачи.
    Знаете пхп - пишите на пхп, вот псевдокод:
    любимые = [a, b, c]
    нелюбимые = [d, e, f]
    function menu(лимит){
        result = []
        while питательность(result) < лимит{
            if random() > 0.3 // число взято наобум
                продукт = случайный(любимые)
            else
                продукт = случайный(нелюбимые)
            if  продукт не в result
                добавить продукт в result
        }
        выбросить из result последнее
        return result
    }

    Учтите, если суммарная калорийность всех продуктов меньше лимита, код зациклится
    Ответ написан
    3 комментария
  • Как сформулировать запрос к БД для выборки по диапазону дат?

    @gill-sama
    Что значит пересекает? полное вхождение или частичное?
    select * from apartment_dates where date_from beetwen '2017-07-05'::date and ' 2017-07-15'::date or date_to '2017-07-05'::date and ' 2017-07-15'::date -- частичное
    select * from apartment_dates where date_from beetwen '2017-07-05'::date and ' 2017-07-15'::date and date_to '2017-07-05'::date and ' 2017-07-15'::date --полное
    С - включтельно
    ПО - исключтельно
    Ответ написан
    1 комментарий
  • Как правильно организовать внедрение зависимостей в Yii2?

    qonand
    @qonand
    Software Engineer
    Вы не совсем правильно понимаете задачи контейнера зависимостей и принципы его работы. Поэтому рекомендую ознакомиться с документацией.
    Суть контейнера в том что Вы настраиваете конфигурации компонентов находящихся в нем, а так же зависимости компонентов друг от друга, а уже сам контейнер разбирается как создать объект на основе всех этих данных и со всеми зависимостями. Вы по сути дела только написали лишний код, который реализован в контейнере по умолчанию.

    Возьмем например Ваш объект репозитория, его достаточно зарегистрировать в контейнере так
    Yii::$container->setSingleton('common\domain\Entities\User\Profile\Interfaces\Repository', // указываем интерфейс
        [ // указываем конфигурацию класса реализующего этот интерфейс
            'class' => 'common\infrastructure\Entities\User\Profile\Repository' 
        ], 
        [ // указываем какие данные необходимо передать в конструктор, в частности - экземпляр класса UserProfile
            Instance::of('common\models\ActiveRecord\UserProfile')
        ]
    );


    Контейнер соответственно сам проинжектит в объекты использующие common\domain\Entities\User\Profile\Interfaces\Repository объект common\infrastructure\Entities\User\Profile\Repository

    Сервис регистрируется аналогично:
    Yii::$container->setSingleton('common\domain\Entities\User\Profile\Interfaces\Service',
        [
            'class' => 'common\application\User\Profile\Service',
        ],
        [
            Instance::of('common\domain\Entities\User\Profile\Interfaces\Repository')
        ],
    );


    При создании сервиса, контейнер найден в своих данных объект соответствующий common\domain\Entities\User\Profile\Interfaces\Repository создаст его и проинжектит в сервис
    Ответ написан
    Комментировать
  • Как лучше ассоциировать модель и файлы/изображения относящиеся к ней?

    Screamie
    @Screamie
    Full-stack разработчик
    На мой взгляд лучше всего подойдет связующая таблица. И не нужно создавать запись с null при сохранении модели, на тот случай если у модели не будет прикрепленного файла, что бы не плодить пустые записи в БД.

    Структура БД может быть такой

    resource
    -----------
    id:PK
    name
    description

    resource_file
    ---------------
    resource_id:PK
    file_id:PK

    file
    ---------------
    id:PK
    path
    description

    И создать индексы для всех таблиц и внешние ключи для resource_file.resource_id и resource_file.file_id.

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

    qonand
    @qonand
    Software Engineer
    ох что-то Вы не понятное пытаетесь построить. Судя по вопросу у Вас набор паттернов а не архитектура. Что Вы хотите получить в итоге? слоенную архитектуру? так она так не строиться. DTO - это объект для передачи данных, он не хранит бизнес-логики, репозиторий и Active Record как правило не используются совместно. В общем судя из постановки задачи могу сказать что Вы не совсем понимаете как строить подобную архитектуру, поэтому рекомендую Вам вначале почитать про слоеную архитектуру (например у того же Фаулера), про модель предметной области, про DDD, а потом уже переходить к практике. Для начала можете пробежаться для начала по этим статьям:
    статья 1
    статья 2
    статья 3
    статья 4
    Ответ написан
    2 комментария
  • Как подменить реализацию в стороннем компоненте?

    @H_Kamol
    full stack developer
    Еще можно сделать так:

    1. Расширьте класс вендора. Создайте класс App\CartItem extends Gloudemans\Shoppingcart\CartItem
    2. Переопределите нужный метод в созданном классе.
    3. Используйте свой созданный/расширенный класс в нужных местах.
    Ответ написан
    1 комментарий
  • Как оптимизировать экшен подтверждения аккаунта по токену?

    qonand
    @qonand
    Software Engineer
    Как еще можно отрефакторить данный метод?

    1. Насколько понимаю у Вас логика (ну либо какая-то ее часть) находиться в контроллере. Это не правильно с точки зрения MVC, контроллер не место для логики.
    2. Сейчас у Вас в контроллере каша из кода, которая очень трудно читается и воспринимается. Поэтому рекомендую почитать например https://refactoring.guru/ru для понимая основных проблем кода и способов их решения
    Ответ написан
    Комментировать
  • Как произвести валидацию модели до сохранения при использовании паттерна Repository?

    mitaichik
    @mitaichik
    Репозиторий (хранилище) должен содержать логику сохранения/поиска/восстановления объектов. Валидация - это как бы не его задача. В энтерпрайз фреймворках для этого создаются отдельные сущности.

    Что касается Yii - то в нем ActiveRecord несет несколько обязанностий: это и сущность с бизнес-логикой, и валидатор, и репозиторий, и жизненный цикл и т.п. Вы вынесли логику хранения в репозиторий, хорошо. Теперь вам нужно выносить логику валидации куда-то.

    Но, с другой стороны, почему бы не пользоваться функционалом фреймворка и не оставить обязанность валидации в модели? Какие-то суперсложные валидаторы можно вынести в отдельные классы валидаторов.

    Я это все к тому, что если вы все это хотите выносить, и идти против архитектуры фреймворка (что не так-то просто), то зачем использовать Yii? Может лучше сразу взять фреймворк который более подходит к вашей архитектуре?
    Ответ написан
    2 комментария
  • Как произвести валидацию модели до сохранения при использовании паттерна Repository?

    Deroy
    @Deroy
    Senior Developer, Software Architect
    при использовании паттерна репозиторий вам стоит перестать думать о модели которая путешествует через систему, как о месте где должна случаться валидация входных данных. Такой подход получил распространение благодаря RAD-framework'ам (Yii и ему подобные) - упрощенка цель которой - быстрая скорость разработки.

    Если смотреть на архитектуру с точки зрения "чистоты", то:

    Модель которая путешествует через всю систему должна содержать в себе только доменную логику, или не содержать ее вовсе (т.е. по факту являться Value-object'ом).

    Валидация входных данных описывается отдельной моделью - моделью реквеста - и содержит в себе логику валидации/маппинга/и пр.

    т.е. более менее стандартный подход со стороны расширяемости, надежности, тестируемости и гибкости приложения к последующим изменениям - это иметь валидацию/парсинг входных данных отдельно для каждого случая (например отдельно для вебформ и отдельно для JSON/XML/etc API, конечно фрагменты могут быть переиспользованы, наследованы или примешаны и т.д.), модели - отдельно, работу со стораджом отдельно.

    Последнее вы уже сделали = репозиторий как раз оно.

    Так что ваше предположение - верно.
    Ответ написан
    Комментировать