vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php line 196

Open in your IDE?
  1. <?php
  2. /*
  3.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  *
  15.  * This software consists of voluntary contributions made by many individuals
  16.  * and is licensed under the MIT license. For more information, see
  17.  * <http://www.doctrine-project.org>.
  18.  */
  19. namespace Doctrine\ORM;
  20. use Doctrine\Common\Inflector\Inflector;
  21. use Doctrine\ORM\Query\ResultSetMappingBuilder;
  22. use Doctrine\Common\Persistence\ObjectRepository;
  23. use Doctrine\Common\Collections\Selectable;
  24. use Doctrine\Common\Collections\Criteria;
  25. /**
  26.  * An EntityRepository serves as a repository for entities with generic as well as
  27.  * business specific methods for retrieving entities.
  28.  *
  29.  * This class is designed for inheritance and users can subclass this class to
  30.  * write their own repositories with business-specific methods to locate entities.
  31.  *
  32.  * @since   2.0
  33.  * @author  Benjamin Eberlei <kontakt@beberlei.de>
  34.  * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
  35.  * @author  Jonathan Wage <jonwage@gmail.com>
  36.  * @author  Roman Borschel <roman@code-factory.org>
  37.  */
  38. class EntityRepository implements ObjectRepositorySelectable
  39. {
  40.     /**
  41.      * @var string
  42.      */
  43.     protected $_entityName;
  44.     /**
  45.      * @var EntityManager
  46.      */
  47.     protected $_em;
  48.     /**
  49.      * @var \Doctrine\ORM\Mapping\ClassMetadata
  50.      */
  51.     protected $_class;
  52.     /**
  53.      * Initializes a new <tt>EntityRepository</tt>.
  54.      *
  55.      * @param EntityManager         $em    The EntityManager to use.
  56.      * @param Mapping\ClassMetadata $class The class descriptor.
  57.      */
  58.     public function __construct(EntityManagerInterface $emMapping\ClassMetadata $class)
  59.     {
  60.         $this->_entityName $class->name;
  61.         $this->_em         $em;
  62.         $this->_class      $class;
  63.     }
  64.     /**
  65.      * Creates a new QueryBuilder instance that is prepopulated for this entity name.
  66.      *
  67.      * @param string $alias
  68.      * @param string $indexBy The index for the from.
  69.      *
  70.      * @return QueryBuilder
  71.      */
  72.     public function createQueryBuilder($alias$indexBy null)
  73.     {
  74.         return $this->_em->createQueryBuilder()
  75.             ->select($alias)
  76.             ->from($this->_entityName$alias$indexBy);
  77.     }
  78.     /**
  79.      * Creates a new result set mapping builder for this entity.
  80.      *
  81.      * The column naming strategy is "INCREMENT".
  82.      *
  83.      * @param string $alias
  84.      *
  85.      * @return ResultSetMappingBuilder
  86.      */
  87.     public function createResultSetMappingBuilder($alias)
  88.     {
  89.         $rsm = new ResultSetMappingBuilder($this->_emResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
  90.         $rsm->addRootEntityFromClassMetadata($this->_entityName$alias);
  91.         return $rsm;
  92.     }
  93.     /**
  94.      * Creates a new Query instance based on a predefined metadata named query.
  95.      *
  96.      * @param string $queryName
  97.      *
  98.      * @return Query
  99.      */
  100.     public function createNamedQuery($queryName)
  101.     {
  102.         return $this->_em->createQuery($this->_class->getNamedQuery($queryName));
  103.     }
  104.     /**
  105.      * Creates a native SQL query.
  106.      *
  107.      * @param string $queryName
  108.      *
  109.      * @return NativeQuery
  110.      */
  111.     public function createNativeNamedQuery($queryName)
  112.     {
  113.         $queryMapping   $this->_class->getNamedNativeQuery($queryName);
  114.         $rsm            = new Query\ResultSetMappingBuilder($this->_em);
  115.         $rsm->addNamedNativeQueryMapping($this->_class$queryMapping);
  116.         return $this->_em->createNativeQuery($queryMapping['query'], $rsm);
  117.     }
  118.     /**
  119.      * Clears the repository, causing all managed entities to become detached.
  120.      *
  121.      * @return void
  122.      */
  123.     public function clear()
  124.     {
  125.         $this->_em->clear($this->_class->rootEntityName);
  126.     }
  127.     /**
  128.      * Finds an entity by its primary key / identifier.
  129.      *
  130.      * @param mixed    $id          The identifier.
  131.      * @param int|null $lockMode    One of the \Doctrine\DBAL\LockMode::* constants
  132.      *                              or NULL if no specific lock mode should be used
  133.      *                              during the search.
  134.      * @param int|null $lockVersion The lock version.
  135.      *
  136.      * @return object|null The entity instance or NULL if the entity can not be found.
  137.      */
  138.     public function find($id$lockMode null$lockVersion null)
  139.     {
  140.         return $this->_em->find($this->_entityName$id$lockMode$lockVersion);
  141.     }
  142.     /**
  143.      * Finds all entities in the repository.
  144.      *
  145.      * @return array The entities.
  146.      */
  147.     public function findAll()
  148.     {
  149.         return $this->findBy([]);
  150.     }
  151.     /**
  152.      * Finds entities by a set of criteria.
  153.      *
  154.      * @param array      $criteria
  155.      * @param array|null $orderBy
  156.      * @param int|null   $limit
  157.      * @param int|null   $offset
  158.      *
  159.      * @return array The objects.
  160.      */
  161.     public function findBy(array $criteria, array $orderBy null$limit null$offset null)
  162.     {
  163.         $persister $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
  164.         return $persister->loadAll($criteria$orderBy$limit$offset);
  165.     }
  166.     /**
  167.      * Finds a single entity by a set of criteria.
  168.      *
  169.      * @param array      $criteria
  170.      * @param array|null $orderBy
  171.      *
  172.      * @return object|null The entity instance or NULL if the entity can not be found.
  173.      */
  174.     public function findOneBy(array $criteria, array $orderBy null)
  175.     {
  176.         $persister $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
  177.         return $persister->load($criterianullnull, [], null1$orderBy);
  178.     }
  179.     /**
  180.      * Counts entities by a set of criteria.
  181.      *
  182.      * @todo Add this method to `ObjectRepository` interface in the next major release
  183.      *
  184.      * @param array $criteria
  185.      *
  186.      * @return int The cardinality of the objects that match the given criteria.
  187.      */
  188.     public function count(array $criteria)
  189.     {
  190.         return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->count($criteria);
  191.     }
  192.     /**
  193.      * Adds support for magic method calls.
  194.      *
  195.      * @param string $method
  196.      * @param array  $arguments
  197.      *
  198.      * @return mixed The returned value from the resolved method.
  199.      *
  200.      * @throws ORMException
  201.      * @throws \BadMethodCallException If the method called is invalid
  202.      */
  203.     public function __call($method$arguments)
  204.     {
  205.         if (=== strpos($method'findBy')) {
  206.             return $this->resolveMagicCall('findBy'substr($method6), $arguments);
  207.         }
  208.         if (=== strpos($method'findOneBy')) {
  209.             return $this->resolveMagicCall('findOneBy'substr($method9), $arguments);
  210.         }
  211.         if (=== strpos($method'countBy')) {
  212.             return $this->resolveMagicCall('count'substr($method7), $arguments);
  213.         }
  214.         throw new \BadMethodCallException(
  215.             "Undefined method '$method'. The method name must start with ".
  216.             "either findBy, findOneBy or countBy!"
  217.         );
  218.     }
  219.     /**
  220.      * @return string
  221.      */
  222.     protected function getEntityName()
  223.     {
  224.         return $this->_entityName;
  225.     }
  226.     /**
  227.      * @return string
  228.      */
  229.     public function getClassName()
  230.     {
  231.         return $this->getEntityName();
  232.     }
  233.     /**
  234.      * @return EntityManager
  235.      */
  236.     protected function getEntityManager()
  237.     {
  238.         return $this->_em;
  239.     }
  240.     /**
  241.      * @return Mapping\ClassMetadata
  242.      */
  243.     protected function getClassMetadata()
  244.     {
  245.         return $this->_class;
  246.     }
  247.     /**
  248.      * Select all elements from a selectable that match the expression and
  249.      * return a new collection containing these elements.
  250.      *
  251.      * @param \Doctrine\Common\Collections\Criteria $criteria
  252.      *
  253.      * @return \Doctrine\Common\Collections\Collection
  254.      */
  255.     public function matching(Criteria $criteria)
  256.     {
  257.         $persister $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
  258.         return new LazyCriteriaCollection($persister$criteria);
  259.     }
  260.     /**
  261.      * Resolves a magic method call to the proper existent method at `EntityRepository`.
  262.      *
  263.      * @param string $method    The method to call
  264.      * @param string $by        The property name used as condition
  265.      * @param array  $arguments The arguments to pass at method call
  266.      *
  267.      * @throws ORMException If the method called is invalid or the requested field/association does not exist
  268.      *
  269.      * @return mixed
  270.      */
  271.     private function resolveMagicCall($method$by, array $arguments)
  272.     {
  273.         if (! $arguments) {
  274.             throw ORMException::findByRequiresParameter($method $by);
  275.         }
  276.         $fieldName lcfirst(Inflector::classify($by));
  277.         if (! ($this->_class->hasField($fieldName) || $this->_class->hasAssociation($fieldName))) {
  278.             throw ORMException::invalidMagicCall($this->_entityName$fieldName$method $by);
  279.         }
  280.         return $this->$method([$fieldName => $arguments[0]], ...array_slice($arguments1));
  281.     }
  282. }