📜 ⬆️ ⬇️

Doctrine 2 ORM User Repositories

In most cases, the standard methods generated by the Yaml-based doctrine (XML or annotations) are only enough to get some fields using a simple filter. For a more complex query, you have to use native QueryBuilder and use dql to query our model. All this is a consequence of the accumulation of large pieces of code that have the properties to be duplicated where identical requests need to be applied. And how I would like to deal with the model simply and beautifully through one single method? How? Write your own!

User Repositories


We will help custom repositories! In short, the point of these repositories is to store user (non-standard) methods for working with models. All methods will be available through EntityManager for each model to which a specific repository will be “screwed”.

The repositories themselves are descendants of the EntityRepository class. It is better to store them in a separate folder (for example, Repositories) and in your namespace (namespace) - let it be also Repositories.

An example of a simple user repository framework:
namespace Repositories; use Doctrine\ORM\EntityRepository; use Entities; class UserRepository extends EntityRepository { public function getUserMethod($params) { } } 

')

Project structure


To make it clearer, let's define the folder structure of our project directory:


Connecting to doctrine


To begin with, in order for the doctrine to see our classes, we will register another ClassLoader in the Doctrine general configuration file. In this case, the configuration is in the file cli-config.php . Add the following lines of code to it:
 //    define("ROOT_DIR", __DIR__); define("DOCTRINE_DIR", ROOT_DIR."/doctrine"); ... //     ,     require_once DOCTRINE_DIR . '/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php'; //           $classLoader = new ClassLoader('Repositories', ROOT_DIR); $classLoader->register(); ... 


Connecting the repository to the model


The place of association of the model with the repository depends on what type of mappers we use (Annunciations, YAML or XML). Since we use YAML, we connect the repository through it using the attribute repositoryClass where we describe the name of the class and its namespace:
 Entities\ModelName: type: entity repositoryClass: Repositories\UserRepository table: model_table fields: ... 


In this example, it is assumed that we have a generated model with annotations for this YAML.
 namespace Entities; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\EntityRepository; /** * Entities\ModelName * * @Table(name="model_table") * @Entity(repositoryClass="Repositories\UserRepository") */ class ModelName { ... } 


That's all. Now you can write your own methods in the repository and work with them through our models. Everything turned out to be simple.

Example


A small life example based on writing your own method for a custom mood model.
/Entities/UserMood.php
 namespace Entities; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\EntityRepository; /** * Entities\UserMood * * @Table(name="b_mood") * @Entity(repositoryClass="Repositories\RUserMood") */ class UserMood { /** * @var integer $ID * * @Column(name="ID", type="integer") * @Id * @GeneratedValue(strategy="IDENTITY") */ private $ID; /** * @var string $ACTIVE * * @Column(name="ACTIVE", type="string", length=1, nullable=false) */ private $ACTIVE; /** * @var string $NAME * * @Column(name="NAME", type="string", length=255, nullable=false) */ private $NAME; /** * @var datetime $DATE_ACTIVE_FROM * * @Column(name="DATE_ACTIVE_FROM", type="datetime", nullable=false) */ private $DATE_ACTIVE_FROM; /** * @var decimal $VALUE * * @Column(name="VALUE", type="decimal", nullable=false) */ private $VALUE; /** * @var integer $USER_ID * * @Column(name="USER_ID", type="integer", length=6, nullable=false) */ private $USER_ID; /** * @var string $UNAUTH_HASH * * @Column(name="UNAUTH_HASH", type="string", length=255, nullable=false) */ private $UNAUTH_HASH; //.....       ,        . //.....    ORM. } 


/yaml/Entities.UserMood.dcm.yml

 Entities\UserMood: type: entity repositoryClass: Repositories\RUserMood table: b_mood fields: ID: id: true type: integer generator: strategy: AUTO ACTIVE: type: string length: 1 nullable: false NAME: type: string length: 255 nullable: false DATE_ACTIVE_FROM: type: datetime nullable: false VALUE: type: decimal nullable: false USER_ID: type: integer length: 6 nullable: false UNAUTH_HASH: type: string length: 255 nullable: false 


/Repositories/RUserMood.php

Here it is worth paying attention to how in our method EntityManager ($ em) will be declared. This is done like this:

 $this->_em 


And now the code of our repository itself:

 namespace Repositories; use Doctrine\ORM\EntityRepository; use Entities; class RUserMood extends EntityRepository { public function getMoodsInDateRange($from, $to, $user = false) { $qb = $this->_em->createQueryBuilder(); $filter[1] = $from; $filter[2] = $to; if (!$user) { $varwhere = $qb->expr()->andX( $qb->expr()->gte('um.DATE_ACTIVE_FROM', '?1'), $qb->expr()->lte('um.DATE_ACTIVE_FROM', '?2') ); } else { $filter[3] = $user; $varwhere = $qb->expr()->andX( $qb->expr()->gte('um.DATE_ACTIVE_FROM', '?1'), $qb->expr()->lte('um.DATE_ACTIVE_FROM', '?2'), $qb->expr()->eq('um.USER_ID', '?3') ); } $qb->add('select', new \Doctrine\ORM\Query\Expr\Select(array('um'))) ->add('from', new \Doctrine\ORM\Query\Expr\From('Entities\UserMood', 'um')) ->add('where', $varwhere) ->add('orderBy', new \Doctrine\ORM\Query\Expr\OrderBy('um.DATE_ACTIVE_FROM', 'DESC')) ->setParameters($filter); return $qb->getQuery(); } } 


That's all! Now if we turn to our model, we can work with our method! For example:

 include_once ('../cli-config.php'); $repo = DDB::getEM()->getRepository('Entities\UserMood')->getMoodsInDateRange('2011-05-01 00:00:00', '2011-05-09 23:59:59')->getResult(); print_r($repo); 


Sources



PS

Since I am just beginning to actively use ORM for PHP and Doctrine in particular, I cannot claim to be 100% correct solution to this problem in this material, therefore sensible criticism is very welcome! Thanks to all!

Source: https://habr.com/ru/post/130275/


All Articles