Ответы пользователя по тегу Symfony
  • Как работать с кастомной сериализацией/нормализацией?

    glaphire
    @glaphire Автор вопроса
    PHP developer
    Огромное спасибо BoShurik за комментарий о пакете symfony/property-info
    Решение проблемы несериализуемых вложенных элементов внутри объекта:
    Установить все пакеты
    symfony/serializer
    symfony/property-access
    symfony/property-info
    phpdocumentor/reflection-docblock


    Внутри класса, где есть свойство - массив объектов, прописать аннотацию
    <?php
    
    namespace App\Pagination;
    
    use App\Entity\NearEarthObject;
    
    class PaginatedCollection
    {
        /**
         * @param NearEarthObject[] $items
         */
        private $items;
        ...


    Внутри метода, где происходит сериализация, прописать:
    $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
            $converter = new CamelCaseToSnakeCaseNameConverter();
            $normalizers = [
                new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d']),
                new ArrayDenormalizer(),
                new ObjectNormalizer(null, $converter, null, $extractor),
            ];
            $encoders = [new JsonEncoder()];
    
            $serializer = new Serializer($normalizers, $encoders);
            $serializedPaginatedCollection = $serializer->serialize($paginatedCollection, 'json');


    Итоговый контроллер
    <?php
    
    namespace App\Controller;
    
    use App\Entity\NearEarthObject;
    use App\Pagination\PaginationFactory;
    use App\Repository\NearEarthObjectRepository;
    use Doctrine\ORM\EntityManagerInterface;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
    use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
    use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\Serializer\Encoder\JsonEncoder;
    use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
    use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
    use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
    use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
    use Symfony\Component\Serializer\Serializer;
    
    class NearEarthObjectController extends AbstractController
    {
        private EntityManagerInterface $entityManager;
        /**
         * @var PaginationFactory
         */
        private $paginationFactory;
    
        public function __construct(EntityManagerInterface $entityManager, PaginationFactory $paginationFactory)
        {
            $this->entityManager = $entityManager;
            $this->paginationFactory = $paginationFactory;
        }
    
        /**
         * @Route("/neo/hazardous", name="neo_hazardous", methods={"GET"})
         */
        public function hazardousAction(Request $request, ObjectNormalizer $objectNormalizer)
        {
            /**
             * @var NearEarthObjectRepository $nearEarthObjectRepository
             */
            $nearEarthObjectRepository = $this
                ->entityManager
                ->getRepository(NearEarthObject::class);
    
            //TODO: add getting is_hazardous=1
            $queryBuilder = $nearEarthObjectRepository->findAllQueryBuilder();
    
            $paginatedCollection = $this
                ->paginationFactory
                ->createCollection($queryBuilder, $request, 'neo_hazardous');
    
            $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
            $converter = new CamelCaseToSnakeCaseNameConverter();
            $normalizers = [
                new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d']),
                new ArrayDenormalizer(),
                new ObjectNormalizer(null, $converter, null, $extractor),
            ];
            $encoders = [new JsonEncoder()];
    
            $serializer = new Serializer($normalizers, $encoders);
            $serializedPaginatedCollection = $serializer->serialize($paginatedCollection, 'json');
    
            return new Response($serializedPaginatedCollection, 200, [
                'Content-Type' => 'application/json',
            ]);
        }
    }


    Источники:
    Issue на github, который показывает решение
    The Symfony Serializer: a great, but complex component

    UPD. Еще раз спасибо BoShurik за уточнения - если изначально поставить symfony/serializer-pack, то все пакеты будут установлены сразу, аннотация @param NearEarthObject[] $items не нужна, а кусок
    $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
            $converter = new CamelCaseToSnakeCaseNameConverter();
            $normalizers = [
                new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d']),
                new ArrayDenormalizer(),
                new ObjectNormalizer(null, $converter, null, $extractor),
            ];
            $encoders = [new JsonEncoder()];
    
            $serializer = new Serializer($normalizers, $encoders);
            $serializedPaginatedCollection = $serializer->serialize($paginatedCollection, 'json');
    
            return new Response($serializedPaginatedCollection, 200, [
                'Content-Type' => 'application/json',
            ]);


    сводится к
    return $this->json($paginatedCollection);
    и сериалайзер выполняет всю работу автоматически
    Ответ написан
  • Как правильно сериализовать коллекцию элементов с данными пагинации?

    glaphire
    @glaphire Автор вопроса
    PHP developer
    Нужно было имплементировать JsonSerializable в классе PaginatedCollection, чтобы сериализатор начал с этим классом работать
    Ответ написан
    Комментировать
  • На какой версии symfony делать новый проект?

    glaphire
    @glaphire
    PHP developer
    Многие популярные пакеты для симфони уже адаптированы под 5.1, можно писать на ней сразу
    Ответ написан
    Комментировать
  • Symfony, у кого есть хорошая практика написания unit-тестов на codeception?

    glaphire
    @glaphire
    PHP developer
    Symfonycasts: testing with a bite - отличный вводной курс, написан для phpunit, но т.к. codeception написан поверх phpunit то легко адаптировать. Проект там для SF 3.3.
    Ответ написан
    1 комментарий
  • Codeception организация тестирования приемочных тестов?

    glaphire
    @glaphire Куратор тега PHP
    PHP developer
    следует создать ещё одну бд в которой продублировать таблицы и подготовить для них фикстуры

    так обычно и поступают, для работы с реальными данными их все равно придется создавать, в промежутках хранить эту привязку и после тестов все вычищать, фикстуры и тестовая бд явно лучше и безопаснее, главное данные хорошо подготовить
    Ответ написан
  • Как работать в symfony env в продакшне?

    glaphire
    @glaphire
    PHP developer
    В самой документации написано, что нет преимущества проброса env через сервер по сравнению с .env файликом на проде

    Most Symfony applications read their configuration from environment variables. While developing locally, you'll usually store these in .env and .env.local (for local overrides). On production, you have two options:

    Create "real" environment variables. How you set environment variables, depends on your setup: they can be set at the command line, in your Nginx configuration, or via other methods provided by your hosting service.
    Or, create a .env.local file just like your local development (see note below)
    There is no significant advantage to either of the two options: use whatever is most natural in your hosting environment.

    https://symfony.com/doc/current/deployment.html#b-...
    Ответ написан
  • Как осуществить пере адресацию после авторизации на ранее запрашиваемый ресурс?

    glaphire
    @glaphire
    PHP developer
    В классе LoginFormAuthenticator в методе onAuthenticationSuccess написать:
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
        {
            if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
                return new RedirectResponse($targetPath);
            }
    
            return new RedirectResponse($this->router->generate('app_homepage'));
        }

    Предварительно добавить в этот класс трейт TargetPathTrait.
    Урок по этой теме на symfonycasts
    UPD. Нашла документацию на этот пример
    Ответ написан
  • Как решить ошибку с SCRAM_SHA_1(MongoDB+Symfony4)?

    glaphire
    @glaphire
    PHP developer
    На гитхабе есть обсуждение, что нужно доустановить
    Ответ написан
    Комментировать
  • Как в symfony/panther задать папку для скачивания файлов?

    glaphire
    @glaphire Автор вопроса
    PHP developer
    Нашла ответ на свой вопрос :)
    1. Panther это хорошо, но тонкая настройка хрома там сейчас не реализована. Переписала на php-webdriver.
    2. На wiki весьма скудные примеры, как добавлять настройки хрому, через setExperimentalOptions() настраиваются почти все параметры, даже если это настройки профиля.
    3. Правильный ответ я нашла с помощью stackoverflow: ccылка
    Упрощенно код выглядит так:
    <?php
    
    use Facebook\WebDriver\Chrome\ChromeOptions;
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    use Facebook\WebDriver\Remote\RemoteWebDriver;
    
    class ParserService
    {
        private $webdriver;
    
        public function __construct()
        {
            $host = 'http://localhost:4444';
            $options = new ChromeOptions();
            $options->setExperimentalOption("prefs", [
                "download.prompt_for_download" => false,
                "download.directory_upgrade" => true,
                "safebrowsing.enabled" => true,
                "download.default_directory" => "/path/to/dir",
            ]);
            $caps = DesiredCapabilities::chrome();
            $caps->setCapability(ChromeOptions::CAPABILITY, $options);
            $this->webdriver = RemoteWebDriver::create($host, $caps);
        }
    }
    Ответ написан
    Комментировать
  • Symfony 4: как отключить кеширование классов и всего такого в var/cache?

    glaphire
    @glaphire
    PHP developer
    В dev окружении кеш перегенеривается на каждое изменение затрагиваемого кода, емнип. Контейнер кешируется, чтобы экономить ресурсы при генерации такого довольно сложного класса. Остальной кеш по аналогии - для экономии ресурсов.
    https://symfony.com/doc/current/components/depende...
    Ответ написан
    5 комментариев
  • Как сделать интернационализацию дат?

    glaphire
    @glaphire
    PHP developer
    4. KnpTimeBundle, в SymfonyCasts его показывали и использовали

    В остальном надо вертеть Intl Extension - в Symfony основная документация по настройке локали, дальше надо догугливать свои случаи и настройки под них
    Ответ написан
  • Как установить symfony на vagrant (homestead)?

    glaphire
    @glaphire
    PHP developer
    Странно, что Вы от рута инсталите, по стектрейсу композер теряет права на удаление файла, у Вас точно не меняется ничего в процессе развертывания проекта?
    Ответ написан