Nano Hash - криптовалюты, майнинг, программирование

Symfony — внедрить репозиторий доктрины в службу

в соответствии с Как внедрить репозиторий в службу в Symfony2 ? это как

acme.custom_repository:
    class: Doctrine\ORM\EntityRepository
    factory: ['@doctrine.orm.entity_manager', getRepository]
    arguments:
        - 'Acme\FileBundle\Model\File'

но я получаю исключение

Недопустимая служба "acme.custom_repository": класс "EntityManager5aa02de170f88_546a8d27f194334ee012bfe64f629947b07e4919__CG__\Doctrine\ORM\EntityManager" не существует.

Как я могу сделать это в Symfony 3.4?

Обновить:

EntityClass на самом деле является допустимым классом FQCN (также использовал ссылку на копирование на phpstorm, чтобы быть уверенным), просто переименовал его, потому что в нем есть название компании :). все равно обновил.

решение

решение от BlueM работает отлично. Если вы не используете автопроводку, вот определение службы:

Acme\AcmeBundle\Respository\MyEntityRepository:
    arguments:
        - '@Doctrine\Common\Persistence\ManagerRegistry'
        - Acme\AcmeBundle\Model\MyEntity # '%my_entity_class_parameter%'


Ответы:


1

Поскольку вы используете Symfony 3.4, вы можете использовать гораздо более простой подход, используя ServiceEntityRepository. Просто реализуйте свой репозиторий, пусть он extend класс ServiceEntityRepository, и вы можете просто внедрить его. (По крайней мере, при использовании автоматического связывания — я не использовал это с классической конфигурацией прямого внедрения, но предположил, что это также должно работать.)

Другими словами:

namespace App\Repository;

use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;

class ExampleRepository extends ServiceEntityRepository
{
    /**
     * @param ManagerRegistry $managerRegistry
     */
    public function __construct(ManagerRegistry $managerRegistry)
    {
        parent::__construct($managerRegistry, YourEntity::class);
    }
}

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

Одно предостережение (которое в равной степени относится и к тому, как вы пытаетесь внедрить репозиторий): если соединение Doctrine сброшено, вы получите ссылку на устаревший репозиторий. Но ИМХО, это риск, который я принимаю, так как иначе я не смогу напрямую инжектить репозиторий..

08.03.2018
  • Вы также должны быть немного осторожны, если вам случится использовать несколько менеджеров сущностей. Если один и тот же класс сущностей принадлежит более чем одному менеджеру, вы не можете предсказать, какой менеджер в конечном итоге будет использоваться. 08.03.2018
  • Как я могу использовать репозиторий сейчас? Можете ли вы расширить этот ответ? 22.10.2018
  • Типичное использование: внедрение конструктора. Просто определите «public function __construct(ExampleRepository $repo) { }» в своем коде, и зависимость будет разрешена без настройки. 23.10.2018

  • 2

    Проверьте, что аргументы являются допустимым классом (с FQCN или с упрощением пакета), например:

    acme.custom_repository:
        class: Doctrine\ORM\EntityRepository
        factory: 
            - '@doctrine.orm.entity_manager'
            - getRepository
        arguments:
            - Acme\MainBundle\Entity\MyEntity
    

    or

    acme.custom_repository:
        class: Doctrine\ORM\EntityRepository
        factory: 
            - '@doctrine.orm.entity_manager'
            - getRepository
        arguments:
            - AcmeMainBundle:MyEntity
    

    Надеюсь, это поможет

    07.03.2018

    3

    Создайте пользовательский репозиторий правильно

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

    use Doctrine\ORM\EntityRepository;
    
    class UserRepository extends EntityRepository
    {
       // your own methods
    }
    

    Затем вам понадобится эта аннотация в классе сущностей:

    /**
     * @ORM\Entity(repositoryClass="MyDomain\Model\UserRepository")
     */
    

    Затем вы определяете репозиторий в файле .yml:

    custom_repository:
            class: MyDomain\Model\UserRepository
            factory: ["@doctrine", getRepository]
            arguments:
              - Acme\FileBundle\Model\File
    

    Убедитесь, что в определении вашего репозитория class указывает на ваш собственный класс репозитория, а не на Doctrine\ORM\EntityRepository.

    Внедрите пользовательские сервисы в свой пользовательский репозиторий:

    В вашем пользовательском репозитории создайте собственные сеттеры для ваших сервисов.

    используйте Doctrine\ORM\EntityRepository;

    class UserRepository extends EntityRepository
    {
        protected $paginator;
    
        public function setPaginator(PaginatorInterface $paginator)
        {
            $this->paginator = $paginator;
        }
    }
    

    Затем введите их следующим образом:

    custom_repository:
            class: MyDomain\Model\UserRepository
    
            factory: ["@doctrine", getRepository]
            arguments:
              - Acme\FileBundle\Model\File
            calls:
              - [setPaginator, ['@knp_paginator']]
    

    Вставьте свой репозиторий в службу:

    my_custom_service:
        class: Acme\FileBundle\Services\CustomService
        arguments:
            - "@custom_repository"
    
    07.03.2018

    4

    Решения, которые я мог видеть здесь до сих пор, неплохие. Я посмотрел на это под другим углом. Таким образом, мое решение позволяет вам поддерживать чистоту репозиториев, как бы обеспечивает согласованную структуру проекта, и вы можете продолжать автомонтаж!

    Вот как я решил бы это в Symfony 5.

    ЦЕЛЬ

    Мы хотим, чтобы репозитории были автосвязанными, и мы хотим, чтобы они были как можно более чистыми. Мы также хотим, чтобы они были очень просты в использовании.

    ПРОБЛЕМА

    Нам нужно найти способ сообщить репозиторию о сущности, которую он должен использовать.

    РЕШЕНИЕ

    Решение простое и состоит из нескольких вещей:

    1. У нас есть собственный класс репозитория, который расширяет класс Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository.
    2. Наш пользовательский класс имеет свойство public string $entity.
    3. Когда мы создаем наш новый репозиторий и расширяем наш пользовательский класс репозитория, у нас есть два варианта: в нашем новом репозитории мы можем просто указать на класс, подобный этому

      namespace App\Database\Repository\Post;
      
      use App\Database\Repository\Repository;
      use App\Entity\Blog\Post;
      
      /**
       * Class PostRepository
       * @package App\Database\Repository
       */
      class PostRepository extends Repository
      {
          public string $entity = Post::class;
      
          public function test()
          {
              dd(99999, $this->getEntityName());
          }
      }
      

    or we could omit that property and let our new base Repository class find it automatically! (More about that later.)

    КОД

    Итак, давайте начнем с кода, а затем я объясню его:

    <?php
    
    namespace App\Database\Repository;
    
    use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
    use Doctrine\Persistence\ManagerRegistry;
    use Laminas\Code\Reflection\ClassReflection;
    use Symfony\Component\Finder\Finder;
    
    /**
     * Class Repository
     * @package App\Database\Repository
     */
    abstract class Repository extends ServiceEntityRepository
    {
        /** @var string  */
        private const REPOSITORY_FILE = 'repository';
    
        /** @var string */
        public string $entity = '';
        /** @var string */
        public string $defaultEntitiesLocation;
        /** @var string */
        public string $defaultEntitiesNamespace;
    
        /**
         * Repository constructor.
         *
         * @param ManagerRegistry $registry
         * @param $defaultEntitiesLocation
         * @param $defaultEntitiesNamespace
         * @throws \Exception
         */
        public function __construct(
            ManagerRegistry $registry,
            $defaultEntitiesLocation,
            $defaultEntitiesNamespace
        ) {
            $this->defaultEntitiesLocation = $defaultEntitiesLocation;
            $this->defaultEntitiesNamespace = $defaultEntitiesNamespace;
            $this->findEntities();
            parent::__construct($registry, $this->entity);
        }
    
        /**
         * Find entities.
         *
         * @return bool
         * @throws \ReflectionException
         */
        public function findEntities()
        {
            if (class_exists($this->entity)) {
                return true;
            }
            $repositoryReflection = (new ClassReflection($this));
            $repositoryName = strtolower(preg_replace('/Repository/', '', $repositoryReflection->getShortName()));
            $finder = new Finder();
            if ($finder->files()->in($this->defaultEntitiesLocation)->hasResults()) {
                foreach ($finder as $file) {
                    if (strtolower($file->getFilenameWithoutExtension()) === $repositoryName) {
                        if (!empty($this->entity)) {
                            throw new \Exception('Entity can\'t be matched automatically. It looks like there is' .
                                ' more than one ' . $file->getFilenameWithoutExtension() . ' entity. Please use $entity 
                                property on your repository to provide entity you want to use.');
                        }
                        $namespacePart = preg_replace(
                            '#' . $this->defaultEntitiesLocation . '#',
                            '',
                            $file->getPath() . '/' . $file->getFilenameWithoutExtension()
                        );
                        $this->entity = $this->defaultEntitiesNamespace . preg_replace('#/#', '\\', $namespacePart);
                    }
                }
            }
        }
    }
    

    Итак, что здесь происходит? Я привязал некоторые значения к контейнеру в services.yml:

     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.
                bind:
                    $defaultEntitiesLocation: '%kernel.project_dir%/src/Entity'
                    $defaultEntitiesNamespace: 'App\Entity'
    
    1. Затем в нашем новом классе расширения я знаю, где по умолчанию искать мои объекты (это обеспечивает некоторую согласованность).

    2. ОЧЕНЬ ВАЖНАЯ ИНФОРМАЦИЯ. Я предполагаю, что мы будем называть репозитории и сущности точно так же, например: Post будет нашей сущностью, а PostRepository — нашим репозиторием. Только обратите внимание, что слово Repository не обязательно. Если он есть, он будет удален.

    3. Некоторая умная логика создаст для вас пространства имен — я предполагаю, что вы будете следовать некоторым хорошим практикам, и все это будет согласовано.

    4. Это сделано! Чтобы ваш репозиторий был автоматически связан, все, что вам нужно сделать, это расширить свой новый базовый класс репозитория и назвать Entity так же, как репозиторий. поэтому конечный результат выглядит так:

      <?php
      
      namespace App\Database\Repository\Post;
      
      use App\Database\Repository\Repository;
      use App\Entity\Blog\Post;
      
      /**
       * Class PostRepository
       * @package App\Database\Repository
       */
      class PostRepository extends Repository
      {
          public function test()
          {
              dd(99999, $this->getEntityName());
          }
      }
      

    Это ЧИСТЫЙ, АВТОМАТИЧЕСКИЙ, ОЧЕНЬ ЛЕГКО И БЫСТРО СОЗДАЕТСЯ!

    12.04.2020
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

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

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..