Ответы пользователя по тегу Symfony
  • Doctrine, как задать значение даты по умолчанию?

    @Flying
    Просто проинициализируйте это поле в конструкторе или в обработчике @PrePersist lifecycle event.
    Ответ написан
    Комментировать
  • Правильно ли указывать foreach в репозитории в Symfony?

    @Flying
    Вам стоит взглянуть на различные режимы гидраторов в Doctrine. В частности в вашем случае вы, скорее всего захотите использовать scalar hydration по результатам выборки одного столбца. Вместе с этим режимом очень хорошо работает array_column(), так что ваш метод мог бы выглядеть примерно вот так (в примере идёт выборка столбца email из entity User):
    public function getEmails()
    {
        return array_column($this->getEntityManager()
            ->createQuery('select u.email from User u')
            ->getResult(\Doctrine\ORM\Query::HYDRATE_SCALAR), 'u_email');
    }

    или, если вам, к примеру, необходима связь между id и email:
    public function getEmails()
    {
        return array_column($this->getEntityManager()
            ->createQuery('select u.id, u.email from User u')
            ->getResult(\Doctrine\ORM\Query::HYDRATE_SCALAR), 'u_email', 'u_id');
    }
    Ответ написан
    Комментировать
  • Как выложить проект на Symfony 4 на сервер?

    @Flying
    Подробный ответ на ваш вопрос есть в документации Symfony. Также обратите внимание на то что публичный каталог проекта можно поменять, как это делается - описано здесь.

    В целом конечно использовать для Symfony проектов хостинги с фиксированной структурой каталогов - не лучшая идея, к примеру не все из них дают нормальный доступ к консоли. По возможности лучше использовать VPS.
    Ответ написан
    1 комментарий
  • Как выполнить команду программно и автоматически ответить на вопросы?

    @Flying
    Если речь идёт о частном случае данной команды - то ответ довольно прост и легко ищется в исходных текстах. Вот как проверяется возможность запуска команды миграции, как видно - здесь используется метод canExecute(), посмотрев в который можно заметить что он контролируется флагом --no-interaction. Более того, банально вызвав help по этой команде можно было бы увидеть ответ на свой вопрос написанный прямым текстом:
    Or you can also execute the migration without a warning message which you need to interact with:
    
        bin/console doctrine:migrations:migrate --no-interaction


    Если же речь идёт об общем подходе к тому как запускать консольные команды которые требуют пользовательского ввода - то здесь ответ довольно находится в документации Symfony. Если посмотреть в исходные тексты ConsoleTester о котором говорится в этом разделе, то видно что основная идея - использование специального input'а. Таким образом решение становится довольно простым:
    1. Получаем и клонируем Kernel
    2. Создаём новый консольный Application
    3. Создаём и конфигурируем ArrayInput
    4. Запускаем приложение с нужным нам input'ом

    Весь основной код для этого можно, очевидным образом, подсмотреть в bin/console самой Symfony.
    Ответ написан
    2 комментария
  • Как резолвит пути Symfony 4?

    @Flying
    Этот путь (а точнее множество путей) указывается в MicroKernelTrait::configureRoutes(). Если быть более точным - то этот trait определяет метод для конфигурирования роутинга, а реальный код (в его стандартном виде) является частью Symfony Flex recipe для symfony/framework-bundle, посмотреть его можно в соответствующем репозитории.

    Если ваш проект создан из symfony/skeleton и, соответственно, использует Symfony Flex, то этот код находится в src/Kernel.php вашего проекта и добавлен он туда именно через recipe.
    Ответ написан
  • Контроль доступа в symfony, не совсем понимаю тебя?

    @Flying
    Symfony - это в первую очередь framework для обработки HTTP запросов и поэтому многие компоненты по-умолчанию "заточены" именно под этот сценарий.

    В конечном итоге вся Symfony Security построена вокруг понятия "токена" (TokenInterface) и большинство частей Security компонента достаточно абстрактны для того чтобы из них можно было собрать весьма разнообразные схемы разделения прав доступа.

    Вам необходимо определить для себя что означает "привязка привилегии к функционалу" с точки зрения кода приложения. Вы планируете оставить это разделение прав доступа на уровне "пускать / не пускать по определённому route" или вы будете в сервисах приложения вызывать что-то подобное Security::isAllowed()? Symfony по-умолчанию реализует первый подход, но ничто не мешает вам организовать собственную реализацию основных компонентов. Если вам нужен ACL (а именно так называется "привязка привилегии к функционалу") - то эта функциональность вынесена в отдельный ACL bundle в Symfony 4, скорее всего именно она вам и нужна.

    По поводу связки role = privilegy - нет, в общем случае это не так. Необходимо разделять процессы аутентификации (в результате которого подтверждается валидность пользователя и определяются его роли) и авторизации (в результате которого определяется может ли аутентифицированный пользователь получить доступ к тому или иному ресурсу).

    Если говорить о работе Symfony Security в контексте обработки HTTP запроса - то аутентификация производится в процессе прохождения запроса через т.н. firewalls, их задача - каким-либо образом определить что это за пользователь и сформировать token. Процесс авторизации построен вокруг т.н. voters которые "голосуют" за/против/воздержался по вопросу "пускать/не пускать", в документации есть целый ряд примеров. Надеюсь факт того что voters могут быть произвольными и иметь любую собственную логику - довольно очевиден. К примеру тот же ACL bundle как раз реализует voter который принимает решение о доступе на основе ACL list'а (который, конечно же, может находиться и в базе данных), но в целом это частный случай.
    Ответ написан
    1 комментарий
  • Как правильнее реализовать код обработки AJAX запроса от разных сущьностей к одному контроллеру?

    @Flying
    В зависимости от реальных потребностей вашего приложения можно посмотреть в сторону использования наследования entities. К примеру возможно ваши "category, faq, article" являются частными случаями общей логической сущности Content, в этом случае можно было бы запрашивать репозиторий именно для базовой entity и дальше у вас не будет разделения логики работы с теми же тегами.

    Кроме того ничто не мешает вам вынести код работы с тегами в отдельный сервисный класс (назовём его TagSearchService), сделать для каждого типа "category, faq, article" отдельные actions в их контроллерах которые будут обращаться к сервисному классу с разными (и в этом случае заранее известными) параметрами. Т.е., проще говоря, в каком-нибудь CategoryController::search() вы могли бы вызвать TagSearchService и передавать ему Category::class вместо того чтобы полагаться на приходящие извне данные. Если переходить на такую схему - то разные классы для элементов форм (CategoryType и FaqType в вашем примере) тоже естественным образом заменяются на один класс (какой-нибудь TagSearchType) т.к. между ними не остаётся различий. Кроме того не нужно будет передавать извне имя класса - по-моему это плохая идея в любом случае.

    Если развивать эту идею дальше - то логично вырисовывается интерфейс TaggableInterface для entities которые могут иметь теги. Это естественным образом приводит к возможности в compiler pass собрать список таких entities и передать их в TagSearchService. Возможно потребуется для каких-то целей :)

    Далее, по поводу фильтрации тегов. Всё-таки при построении запросов мы ведём речь о DQL, так что есть ненулевой шанс (хотя доказать это я и не могу, надо пробовать) что вытаскивать id из тегов не нужно, достаточно передать массив самих entities в notIn(). Если же это и не так - код можно переписать с использованием array_map(), возможно это сделает его понятнее. Также findOneBy(['id' => $entityId]) очевидным образом меняется на EntityManager::find() что несколько проще выглядит.

    Насчёт идеи вытягивать именно id тегов - вряд ли в этом есть особый смысл если только у вас не очень нагруженное приложение.
    Ответ написан
  • Есть ли хорошие курсы по Symfony?

    @Flying
    Есть официальная учебная платфома у SensioLabs, правда недешёвая.
    Ответ написан
    Комментировать
  • Как сделать связь одного поля таблицы с несколькими сущьностями (entity)?

    @Flying
    Вы уже используете DiscriminatorMap который является правильным решением в данной задаче. Вам ничто не мешает теперь иметь в наследуемых классах отдельные свойства содержащие связи с конкретными entities, специфичными для каждого конкретного типа пункта меню. Вы также вполне можете объявить getEntity() / setEntity() в классе MenuItem абстрактными, а в дочерних классах реализовывать их. Конечно типы на уровне языка вам будет не задать, но никто не будет вам мешать использовать PHPDoc для создания type hints.
    Ответ написан
    1 комментарий
  • Слои приложения в Symfony?

    @Flying
    То что описано в пункте про "атомарные операции" больше всего похоже на методы в entity repository в Doctrine.
    • Если эти операции специфичны для каких-то конкретных entity - можно реализовывать прямо в методах соответствующих репозиториев
    • Если они общие для всех entities - то проще всего вынести их в промежуточный абстрактный repository и наследовать остальные custom repositories от него
    • Если они общие для части entities - можно, к примеру, определить дополнительные интерфейсы, показывающие какие операции применимы к каким entities (у меня, например, зачастую используется ActivitableInterface для entities для которых есть флаг isActive) и дальше либо реализовать промежуточный абстрактный класс репозитория и наследовать custom repositories от него либо вынести эти операции в traits и подключать по мере необходимости.



    Про "команды" не очень понятно, это про класс Command из symfony/command? Если да - то там есть раздельная инициализация через initialize(), туда передаётся OutputInterface и если сильно нужно - можно там вызвать некий отдельный сервис. Если не хочется прокидывать сервис вручную в каждую команду - можно автоматизировать это через setter + compiler pass либо через аннотицию @required
    Ответ написан
    2 комментария
  • Symfony 4 - Best Practices for Reusable Bundles в чём смысл, и как всё таки создать bundle?

    @Flying
    Очевидно вы имеете в виду вот эту статью в документации Symfony.

    Если прочитать текст более внимательно - то там не сказано что bundles теперь запрещены или не приветствуются. Речь идёт о том что bundles стоит использовать в том случае если вы хотите оформить часть своего кода в отдельный package который можно использовать и в других проектах. Основное же приложение теперь не стоит оформлять в виде bundle, а можно писать напрямую. Предлагается не складывать в /src кучу разных bundles, а иметь один общий код приложения, зависимый только от внешних packages (пусть даже написанных вами) которые устанавливаются через Composer.

    Т.е. к примеру структура кода подобная Sylius теперь не считается хорошей практикой.

    Думаю что одна из причин такого изменения - переход на Symfony Flex и автоматизированную поддержку регистрации / конфигурации bundles через recipes.
    Ответ написан
    Комментировать
  • Есть ли примеры готовой регистрации через соц. сети в Symfony?

    @Flying
    knpuniversity/oauth2-client-bundle является интеграцией league/oauth2-client в Symfony. Последняя в свою очередь является слоем абстракции для целого ряда адаптеров для сервисов предоставляющих аутентификацию по протоколу OAuth2
    Ответ написан
    1 комментарий
  • Symfony 4.2, какая производительность autowiring'а через @required аннотацию?

    @Flying
    Поскольку контейнер в Symfony компилируемый - на runtime производительность это не влияет никак. Если хотите проверить - загляните в то во что превращается код создания вашего сервиса в контейнере, всё это лежит в var/cache, там будет обычный setLogger($this->get('logger')) или что-нибудь типа этого.
    Ответ написан
    Комментировать
  • Как правильно прописать свой service.yaml в бандле в Symfony4?

    @Flying
    Это описано в документации Symfony. Вкратце, есть два пути - через подключение конфигурационного файла непосредственно (рекомендуется только для "внутренних" конфигурационных файлов) и через написание bundle extension (как раз рекомендуется для bundles). Если у вас именно внешний по отношению к приложению bundle - то пишите bundle extension, там есть всё необходимое для подключение файлов конфигураций.
    Ответ написан
    1 комментарий
  • Как сделать вложенный запрос в Doctrine DQL?

    @Flying
    Возможно вам стоит обратить внимание на готовую реализацию деревьев для Doctrine? Есть также интеграция для этого пакета в Symfony. Это позволит вам не изобретать велосипед, а использовать готовое, проверенное и весьма популярное решение освободив время от написания и поддержки своей реализации для других задач.
    Ответ написан
    Комментировать
  • Как реализовать Autocomplete в Symfony 3?

    @Flying
    Можно для начала копать в сторону поиска на packagist'е :) Например pugx/autocompleter-bundle
    Ответ написан
    Комментировать
  • Как в Symofny 4 запустить выполнение cron для консольной комманды?

    @Flying
    Укажите полный путь к исполняемому файлу php, например /usr/local/php или где он у вас расположен.
    Ответ написан
  • Как лучше организовать сущности в Doctrine?

    @Flying
    Если список типов у вас статический - замените EntryType на наследуемые entities через discriminator map, количество запосов это не снизит, но снизит количество join'ов и таблиц. Вот здесь можно подробнее почитать про него на русском.

    А вообще судя по задаче у вас основная работа идёт не на уровне строк таблиц, а на уровне их анализа, Doctrine в этом случае - не лучшее решение т.к. задача больше про построение запросов, а не про удобную работу с сильно связанными данными. Тот же Excel с этим справится гораздо лучше :)
    Ответ написан
  • Как в Symfony 4 перевести текст внутри entity?

    @Flying
    Поскольку entities по определению должны быть очень лёгкими объектами - здесь можно рассмотреть несколько вариантов решения:
    1. Наиболее корректным будет вариант использования Doctrine event listener'а который будет слушать событие postLoad и производить локализацию. Что именно и как локализовывать - можно решить несколькими путями:
      1. Дать entity самой решать как это сделать и позволить event listener'у просто передавать ей объект-переводчик (Translator в случае Symfony). Чтобы понять надо ли передавать переводчик - стоит определить отдельный интерфейс, какой-нибудь TranslatableEntityInterface
      2. Указать event listener'у что переводить, к примеру через кастомные аннотации, решение более сложное, но более гибкое

    2. Можно дать возможность entity дёргать какой-нибудь известный и доступный ей метод из которого она будет получать объект-переводчик, к примеру это может быть какой-нибудь StaticTranslatorProvider со статическим методом getTranslator(). В целом не очень хорошая идея, но работать будет
    3. Можно не трогать entities вообще, а запрашивать локализацию непосредственно во внешнем коде. В целом плохой вариант, но тоже возможный
    Ответ написан
    Комментировать