Ответы пользователя по тегу Symfony
  • Как правильно в Symfony десериализовать Request в DTO, а последний потом в сущность?

    Как человек, который в своё время так переусложнял код, что потом сам не понимал, что и где в проекте происходит, посоветую вам использовать самый лучший принцип на свете - "KISS"

    Поэтому, ничего сложного пока не выдумывайте, поверьте, вы всегда сможете потом всё усложнить)))

    Я бы сделал так:

    • В контроллере сериализуем JSON в DTO ( можно вообще вот так https://symfony.com/blog/new-in-symfony-6-3-mappin... )
    • Далее создаёс сервис, который будет нашим маппером, и который будет иметь 2 метода "fromDtoToEntity" и "fromEntityToDto", и он будет заниматься всеми преобразованиями туда-сюда.
    • В этом маппере пишем наитупейшую логику, как вы и писали $user-setAge($DTO->getAge());
    • Отдаём клиенту ответ из контроллера


    Этот вариант максимально прозрачен и сильно сэкономит вам время при дебаге, потому что вы в два клика сможете найти всю логику.
    Ответ написан
    9 комментариев
  • Почему не срабатывает ссылка подтверждения регистрации в Symfony 6?

    private VerifyEmailHelperInterface $verifyEmailHelper,


    Вам на будущее: было бы неплохо, чтобы вы показывали нам чуть больше кода, чтобы не приходилось подключать дедуктивный метод для нахождения улик.

    Судя по запятой в конце строчки, свойство $verifyEmailHelper объявляется сразу в конструкторе. А "Constructor property promotion" появился только в версии PHP 8.0

    Поэтому, если версия PHP ниже, появляется подобная ошибка.
    Ответ написан
    1 комментарий
  • Как сделать авторизацию по двум таблицам в Symfony?

    Разные категории пользователей в Symfony лучше всего организовать при помощи ролей.

    Основная таблица users будет содержать всех ваших пользователей, это проще всего. Там же и будет поле с ролями.

    Для дополнительных полей другой категории пользователей лучше всего создать отдельную таблицу, которая будет связана с основной через связь one-to-one либо one-to-many по id пользователя (посмотрите уроки по Doctrine).

    Однако, если пользователей с этими дополнительными полями будет подавляющее большинство, то можно не усложнять, а смело создавать эти поля в основной таблице users.

    Очень советую досмотреть полностью уроки с symfonycasts.com. Они великолепны, и там точно всё необходимое должно быть.
    Ответ написан
    2 комментария
  • Какой аналог itemOperations в api-platform 3 версии?

    Сам ещё не ставил третью версию, но одним глазом посмотрел документацию, и вроде как они тупо по названию классов в аргументе options ориентируются. В принципе, это логично, если подумать. Но не очевидно.
    #[ApiResource(
        operations: [
            new Get(), // item
            new Put(), // item
            new Patch(), // item
            new Delete(), // item
            new GetCollection(), // collection
            new Post() // collection
        ],
    )]
    Ответ написан
  • Как работать с slug в Symfony?

    В services.yaml вставил

    App\Entity\Page:
    autowire: true

    1. Уберите это.

    2. Используйте атрибут MapEntity, чтобы явно указать, на какое поле мапить параметр 'slug'

    <?php
    
    namespace App\Controller;
    
    use App\Entity\Page;
    use App\Repository\PageRepository;
    use Symfony\Bridge\Doctrine\Attribute\MapEntity;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Attribute\Route;
    
    class PageController extends AbstractController
    {
        // ...
    
        #[Route('/{slug}', name: 'show-page')]
        public function show(
            #[MapEntity(mapping: ['slug' => 'slug'])] Page $page
        ): Response
        {
            return $this->render('/page/show.html.twig', [
                'slug' => $page->getSlug(),
                'page' => $page,
            ]);
        }
    }
    Ответ написан
  • Symfony каталог товаров с динамичной фильтрацией?

    Самое простое решение в данном случае - использовать в базе данных дополнительное поле с типом данных JSON, в котором и хранить объект с такими дополнительными характеристиками. Т.е. мы тут как бы совмещаем функционал нашей SQL базы данных с функционалом документных NoSQL баз.
    И доктрина и сами современные SQL базы позволяют искать данные по JSON.

    Более традиционный вариант - это создание двух таблиц. Первая таблица options_list будет содержать список самих характеристик. Поля могут быть, например:

    id - код характеристики,
    name - наименование характеристики

    Во второй таблице options_values будут храниться уже сами значения характеристик.
    И у неё будут поля:

    id - код значения характеристики,
    product_id - код товара из таблицы products (или как там у вас), для которого создается характеристика. FOREIGN KEY,
    option_id - код самой характеристики из таблицы options_list. FOREIGN KEY,
    value - значение характеристики 
    Ответ написан
  • Как правильно разрабатывать symfony приложение локально?

    Я использую для локальной разработки docker compose.
    В его конфигурационном файле собираю все нужные контейнеры (PHP, MySQL, Rabbit, Mongo и т.д.) в сеть. Для PHP делаю два контейнера из разных образов:
    Один из образа php-fpm, это сам сервер.
    Второй из образа php-cli, он используется как раз для всех консольных команд. Именню в него устанавливаю Composer.
    Для того, чтобы не писать для запуска консольных команд постоянно это заклинание "docker compose run ...", я делаю Makefile, в котором прописываю часто-используемые команды.
    И, набрав "make cc" на самом деле запускаю "docker-compose run --rm php-cli bin/console c:c"
    Чтобы это всё работало без необходимости постоянно перезапускать docker-compose, я файлы проекта пробрасываю внутрь контейнеров не копированием, а через вольюм, и когда я буду их менять, они будут меняться и внутри контейнера. Так же подключаю прямо внутрь контейнера .env файл, чтобы все переменные окружения туда пробросились.
    Я вам прямо закину кучу файлов из одного из своих старых проектов, может накопаете там идей каких-то для себя:
    1. docker-compose.yml
    version: '3.8'
    services:
      # Поднимаю сразу реверс-прокси, чтобы пробросить всё наружу на нужный мне порт.m
      nginx:
        build:
          context: ./.docker/nginx
          dockerfile: Dockerfile.dev
        volumes:
          - ./:/app
        depends_on:
          - php-fpm
        ports:
          - "8080:80"
    
      php-fpm:
        build:
          context: ./.docker/php
          dockerfile: Dockerfile.fpm-dev
          args:
            IMAGE_ENV: dev
        volumes:
          # Вот тут вся магия) Мы просто подключаем файлы проекта в виде вольюма
          # Т.е. имеем доступ ко всем файлам и изнутри и снаружи контейнера. 
          # Внутри контейнера файлы будут видны по пути /app
          - ./:/app
        environment:
          # Даже XDEBUG можно пробросить для IDE
          XDEBUG_CONFIG: 'discover_client_host=true client_host=127.0.0.1 log_level=0 client_port=9003'
          PHP_IDE_CONFIG: "serverName=Docker"
        env_file:
          - .env.local
        depends_on:
          - mysql
    
      # Делаю отдельный контейнер для комманд-лайн утилит, 
      # чтобы не проще запускать консоль Symfony. Мне так удобнее.
      # Здесь будет всё практически как и у php-fpm, только без самого php-fpm процесса
      php-cli:
        build:
          context: ./.docker/php
          dockerfile: Dockerfile.cli-dev
          args:
            IMAGE_ENV: dev
        volumes:
          - ./:/app
          - composer:/root/.composer/cache
        environment:
          XDEBUG_CONFIG: 'discover_client_host=true client_host=127.0.0.1 log_level=0 client_port=9003'
          PHP_IDE_CONFIG: "serverName=Docker"
        env_file:
          - .env.local
        depends_on:
          - mysql
    
      mysql:
        build:
          context: ./.docker/db
          dockerfile: Dockerfile
        volumes:
          - mysql:/var/lib/mysql
        env_file:
          - .env.local
        environment:
          MYSQL_ROOT_HOST: '%'  # needs to be enclosed with quotes
        ports:
          - "6603:3306"
    
    # Тут ещё два дополнительных вольюма. Один для кэша composer, а второй для файлов базы данных, чтобы она не убивалась при перезапуске наших контейнеров. Убивать мы её будем только сознательно. если нам надо её очистить.
    volumes:
      composer:
      mysql:


    2. Все три докерфайла
    Файлы с конфигурациями, которые будут копироваться внутри докерфайлов, кидать не буду, у вас всё своё будет в любом случае.

    Dockerfile.dev - для nginx.
    # Образ Nginx
    FROM nginx:alpine
    
    # Копируем файл с настройками
    COPY ./task/default.conf /etc/nginx/conf.d/default.conf
    
    # Устанавливаем рабочую директорию
    WORKDIR /app


    Dockerfile.fpm-dev - для сервера php-fpm
    # Образ php-fpm
    FROM php:8.2-fpm
    
    ARG IMAGE_ENV
    
    # Устанавливаем нужные пакеты и расширения
    RUN apt-get update && apt-get install -y -qq libpq-dev unzip libxml2-dev libicu-dev libonig-dev zlib1g-dev libpng-dev librabbitmq-dev \
        && docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd && docker-php-ext-install pdo_mysql && \
        docker-php-ext-configure intl && docker-php-ext-install intl && \
        pecl install xdebug amqp && rm -rf /tmp/pear && docker-php-ext-enable xdebug amqp && \
        rm -rf /var/lib/apt/lists/*
    
    # Use the default development configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
    
    # Копируем файл с настройками xdebug
    COPY ./php.d/${IMAGE_ENV}/default.ini /usr/local/etc/php/conf.d/default.ini
    COPY ./php.d/${IMAGE_ENV}/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
    
    
    # Создаем пользователя app, чтобы не работать под рутом
    RUN adduser --disabled-password --gecos '' --uid 1000 app
    USER app
    
    # Устанавливаем рабочую директорию
    WORKDIR /app


    Dockerfile.cli-dev - это наш консольный php для запуска консольных команд. Тут практически то же самое, плюс тот самый Composer, ради которого это всё и писалось)
    # Образ php-cli
    FROM php:8.2-cli
    
    ARG IMAGE_ENV
    
    # Устанавливаем нужные пакеты и расширения
    RUN apt-get update && apt-get install -y -qq git unzip libpq-dev libxml2-dev libicu-dev librabbitmq-dev && \
        docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd && docker-php-ext-install pdo_mysql && \
        docker-php-ext-configure intl && docker-php-ext-install intl && \
        pecl install xdebug amqp && rm -rf /tmp/pear && docker-php-ext-enable xdebug amqp && \
        rm -rf /var/lib/apt/lists/*
    
    # Use the default development configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
    
    # Копируем файл с настройками xdebug
    COPY ./php.d/${IMAGE_ENV}/default.ini /usr/local/etc/php/conf.d/default.ini
    COPY ./php.d/${IMAGE_ENV}/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
    
    # Качаем и устанавливаем composer
    RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/bin --filename=composer --quiet
    
    # Если всё же будете работать в контейнере под рутом, то заставляем composer работать под рутом
    # ENV COMPOSER_ALLOW_SUPERUSER 1
    
    # Создаем пользователя app, чтобы не работать под рутом
    RUN adduser --disabled-password --gecos '' --uid 1000 app
    USER app
    
    # Устанавливаем рабочую директорию
    WORKDIR /app


    3. И далее звезда шоу - Makefile с кучей разных скриптов, облегчающих жизнь.
    make init - чистая сборка проекта, тут можно очищать базу и загружать в нее фикстуры
    make up - просто запуск проекта, без очистки, перед началом обычного рабочего дня.
    make down - остановка проекта
    make cc - очистка кэша Symfony.
    И т.д. и т.п.
    # Если надо подключить shell переменные, то создаём тут же ..env.local файл и делаем.
    include .env.local
    export
    
    # Поддержка возможности запускать шелл-скрипты
    SHELL:=/bin/bash
    
    # Кэш
    c: cache-clear cache-warmup
    cc: cache-clear
    cw: cache-warmup
    cache-clear:
    	docker-compose run --rm php-cli bin/console c:c
    cache-warmup:
    	docker-compose run --rm php-cli bin/console c:w
    
    up: docker-up
    down: docker-down
    restart: docker-down docker-up
    init: docker-down init-common
    reset: docker-down-clear init-common
    init-common: clear docker-pull docker-build docker-up app-init
    test: test
    test-coverage: test-coverage
    test-unit: test-unit
    test-unit-coverage: test-unit-coverage
    
    # Если в контейнере другой пользователь, то будут ошибки доступа при редактировании файлов.
    # Поэтому надо сделать chown и chmod для папки var (кэш и логи)
    chown:
    	sudo chown -R 1000:1000 . # Тут указываем свои данные пользователя с хоста
    	sudo chmod -R 777 ./var/
    
    docker-up:
    	docker-compose up -d
    
    docker-down:
    	docker-compose down --remove-orphans
    
    docker-down-clear:
    	docker-compose down -v --remove-orphans
    
    docker-pull:
    	docker-compose pull
    
    docker-build:
    	docker-compose build
    
    app-init: composer-install app-wait-db app-migrations ready
    
    clear:
    	docker run --rm -v ${PWD}:/app --workdir=/app alpine rm -f .ready
    
    ready:
    	docker run --rm -v ${PWD}:/app --workdir=/app alpine touch .ready
    
    test:
    	docker-compose run --rm php-cli php bin/phpunit
    
    test-coverage:
    	docker-compose run --rm php-cli php bin/phpunit --coverage-clover var/clover.xml --coverage-html var/coverage
    
    test-unit:
    	docker-compose run --rm php-cli php bin/phpunit --testsuite=unit
    
    test-unit-coverage:
    	docker-compose run --rm php-cli php bin/phpunit --testsuite=unit --coverage-clover var/clover.xml --coverage-html var/coverage
    
    composer-install:
    	docker-compose run --rm php-cli composer -V
    	docker-compose run --rm php-cli composer install
    
    app-create-db:
    	docker-compose run --rm php-cli ./bin/console doctrine:database:create
    
    app-wait-db:
    	#docker-compose exec lkui-mysql mysqladmin --user=root --password=password ping --silent --wait=60 &> /dev/null
    	#sleep 20
    	until docker-compose exec -T mysql mysqladmin ping -u root -P ${MYSQL_TCP_PORT} -p${MYSQL_ROOT_PASSWORD} | grep "mysqld is alive" ; do >&2 echo "MySQL is unavailable - waiting for it... " ; sleep 5 ; done
    
    app-migrations:
    	docker-compose run --rm php-cli ./bin/console doctrine:migrations:migrate --no-interaction
    
    app-fixtures:
    	docker-compose run --rm php-cli ./bin/console doctrine:fixtures:load --no-interaction
    
    migration:
    	docker-compose run --rm php-cli ./bin/console make:migration
    
    migrate:
    	docker-compose run --rm php-cli ./bin/console doctrine:migrations:migrate #--no-interaction
    
    fixtures:
    	docker-compose run --rm php-cli ./bin/console doctrine:fixtures:load
    Ответ написан
    2 комментария