vendor/doctrine/orm/src/EntityRepository.php line 84
<?phpdeclare(strict_types=1);namespace Doctrine\ORM;use BadMethodCallException;use Doctrine\Common\Collections\AbstractLazyCollection;use Doctrine\Common\Collections\Criteria;use Doctrine\Common\Collections\Selectable;use Doctrine\Common\Persistence\PersistentObject;use Doctrine\DBAL\LockMode;use Doctrine\Deprecations\Deprecation;use Doctrine\Inflector\Inflector;use Doctrine\Inflector\InflectorFactory;use Doctrine\ORM\Exception\NotSupported;use Doctrine\ORM\Mapping\ClassMetadata;use Doctrine\ORM\Query\ResultSetMappingBuilder;use Doctrine\ORM\Repository\Exception\InvalidMagicMethodCall;use Doctrine\Persistence\ObjectRepository;use function array_slice;use function class_exists;use function lcfirst;use function sprintf;use function str_starts_with;use function substr;/*** An EntityRepository serves as a repository for entities with generic as well as* business specific methods for retrieving entities.** This class is designed for inheritance and users can subclass this class to* write their own repositories with business-specific methods to locate entities.** @template T of object* @template-implements Selectable<int,T>* @template-implements ObjectRepository<T>*/class EntityRepository implements ObjectRepository, Selectable{/*** @internal This property will be private in 3.0, call {@see getEntityName()} instead.** @var string* @psalm-var class-string<T>*/protected $_entityName;/*** @internal This property will be private in 3.0, call {@see getEntityManager()} instead.** @var EntityManagerInterface*/protected $_em;/*** @internal This property will be private in 3.0, call {@see getClassMetadata()} instead.** @var ClassMetadata* @psalm-var ClassMetadata<T>*/protected $_class;/** @var Inflector|null */private static $inflector;/** @psalm-param ClassMetadata<T> $class */public function __construct(EntityManagerInterface $em, ClassMetadata $class){$this->_entityName = $class->name;$this->_em = $em;$this->_class = $class;}/*** Creates a new QueryBuilder instance that is prepopulated for this entity name.** @param string $alias* @param string|null $indexBy The index for the from.** @return QueryBuilder*/public function createQueryBuilder($alias, $indexBy = null){return $this->_em->createQueryBuilder()->select($alias)->from($this->_entityName, $alias, $indexBy);}/*** Creates a new result set mapping builder for this entity.** The column naming strategy is "INCREMENT".** @param string $alias** @return ResultSetMappingBuilder*/public function createResultSetMappingBuilder($alias){$rsm = new ResultSetMappingBuilder($this->_em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);$rsm->addRootEntityFromClassMetadata($this->_entityName, $alias);return $rsm;}/*** Creates a new Query instance based on a predefined metadata named query.** @deprecated** @param string $queryName** @return Query*/public function createNamedQuery($queryName){Deprecation::trigger('doctrine/orm','https://github.com/doctrine/orm/issues/8592','Named Queries are deprecated, here "%s" on entity %s. Move the query logic into EntityRepository',$queryName,$this->_class->name);return $this->_em->createQuery($this->_class->getNamedQuery($queryName));}/*** Creates a native SQL query.** @deprecated** @param string $queryName** @return NativeQuery*/public function createNativeNamedQuery($queryName){Deprecation::trigger('doctrine/orm','https://github.com/doctrine/orm/issues/8592','Named Native Queries are deprecated, here "%s" on entity %s. Move the query logic into EntityRepository',$queryName,$this->_class->name);$queryMapping = $this->_class->getNamedNativeQuery($queryName);$rsm = new Query\ResultSetMappingBuilder($this->_em);$rsm->addNamedNativeQueryMapping($this->_class, $queryMapping);return $this->_em->createNativeQuery($queryMapping['query'], $rsm);}/*** Clears the repository, causing all managed entities to become detached.** @deprecated 2.8 This method is being removed from the ORM and won't have any replacement** @return void*/public function clear(){Deprecation::trigger('doctrine/orm','https://github.com/doctrine/orm/issues/8460','Calling %s() is deprecated and will not be supported in Doctrine ORM 3.0.',__METHOD__);if (! class_exists(PersistentObject::class)) {throw NotSupported::createForPersistence3(sprintf('Partial clearing of entities for class %s',$this->_class->rootEntityName));}$this->_em->clear($this->_class->rootEntityName);}/*** Finds an entity by its primary key / identifier.** @param mixed $id The identifier.* @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants* or NULL if no specific lock mode should be used* during the search.* @param int|null $lockVersion The lock version.* @psalm-param LockMode::*|null $lockMode** @return object|null The entity instance or NULL if the entity can not be found.* @psalm-return ?T*/public function find($id, $lockMode = null, $lockVersion = null){return $this->_em->find($this->_entityName, $id, $lockMode, $lockVersion);}/*** Finds all entities in the repository.** @psalm-return list<T> The entities.*/public function findAll(){return $this->findBy([]);}/*** Finds entities by a set of criteria.** @param int|null $limit* @param int|null $offset* @psalm-param array<string, mixed> $criteria* @psalm-param array<string, string>|null $orderBy** @return object[] The objects.* @psalm-return list<T>*/public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null){$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);return $persister->loadAll($criteria, $orderBy, $limit, $offset);}/*** Finds a single entity by a set of criteria.** @psalm-param array<string, mixed> $criteria* @psalm-param array<string, string>|null $orderBy** @return object|null The entity instance or NULL if the entity can not be found.* @psalm-return ?T*/public function findOneBy(array $criteria, ?array $orderBy = null){$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);return $persister->load($criteria, null, null, [], null, 1, $orderBy);}/*** Counts entities by a set of criteria.** @psalm-param array<string, mixed> $criteria** @return int The cardinality of the objects that match the given criteria.** @todo Add this method to `ObjectRepository` interface in the next major release*/public function count(array $criteria){return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->count($criteria);}/*** Adds support for magic method calls.** @param string $method* @param mixed[] $arguments* @psalm-param list<mixed> $arguments** @return mixed The returned value from the resolved method.** @throws BadMethodCallException If the method called is invalid.*/public function __call($method, $arguments){if (str_starts_with($method, 'findBy')) {return $this->resolveMagicCall('findBy', substr($method, 6), $arguments);}if (str_starts_with($method, 'findOneBy')) {return $this->resolveMagicCall('findOneBy', substr($method, 9), $arguments);}if (str_starts_with($method, 'countBy')) {return $this->resolveMagicCall('count', substr($method, 7), $arguments);}throw new BadMethodCallException(sprintf('Undefined method "%s". The method name must start with ' .'either findBy, findOneBy or countBy!',$method));}/*** @return string* @psalm-return class-string<T>*/protected function getEntityName(){return $this->_entityName;}/*** {@inheritDoc}*/public function getClassName(){return $this->getEntityName();}/** @return EntityManagerInterface */protected function getEntityManager(){return $this->_em;}/*** @return ClassMetadata* @psalm-return ClassMetadata<T>*/protected function getClassMetadata(){return $this->_class;}/*** Select all elements from a selectable that match the expression and* return a new collection containing these elements.** @return AbstractLazyCollection* @psalm-return AbstractLazyCollection<int, T>&Selectable<int, T>*/public function matching(Criteria $criteria){$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);return new LazyCriteriaCollection($persister, $criteria);}/*** Resolves a magic method call to the proper existent method at `EntityRepository`.** @param string $method The method to call* @param string $by The property name used as condition* @psalm-param list<mixed> $arguments The arguments to pass at method call** @return mixed** @throws InvalidMagicMethodCall If the method called is invalid or the* requested field/association does not exist.*/private function resolveMagicCall(string $method, string $by, array $arguments){if (! $arguments) {throw InvalidMagicMethodCall::onMissingParameter($method . $by);}if (self::$inflector === null) {self::$inflector = InflectorFactory::create()->build();}$fieldName = lcfirst(self::$inflector->classify($by));if (! ($this->_class->hasField($fieldName) || $this->_class->hasAssociation($fieldName))) {throw InvalidMagicMethodCall::becauseFieldNotFoundIn($this->_entityName,$fieldName,$method . $by);}return $this->$method([$fieldName => $arguments[0]], ...array_slice($arguments, 1));}}