use Doctrine\ORM\EntityManager; use Doctrine\ORM\Configuration; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\AnnotationRegistry; class DoctrineComponent extends CComponent { private $em = null; private $basePath; private $proxyPath; private $entityPath; private $driver; private $user; private $password; private $host; private $dbname; public function init() { $this->initDoctrine(); } public function initDoctrine() { Yii::setPathOfAlias('Doctrine', $this->getBasePath() . '/vendor/Doctrine'); $cache = new Doctrine\Common\Cache\FilesystemCache($this->getBasePath() . '/cache'); $config = new Configuration(); $config->setMetadataCacheImpl($cache); $driverImpl = new AnnotationDriver(new AnnotationReader(), $this->getEntityPath()); AnnotationRegistry::registerAutoloadNamespace('Doctrine\ORM\Mapping', $this->getBasePath() . '/vendor'); $config->setMetadataDriverImpl($driverImpl); $config->setQueryCacheImpl($cache); $config->setProxyDir($this->getProxyPath()); $config->setProxyNamespace('Proxies'); $config->setAutoGenerateProxyClasses(true); $connectionOptions = array( 'driver' => $this->getDriver(), 'user' => $this->getUser(), 'password' => $this->getPassword(), 'host' => $this->getHost(), 'dbname' => $this->getDbname() ); $this->em = EntityManager::create($connectionOptions, $config); } public function setBasePath($basePath) { $this->basePath = $basePath; } public function getBasePath() { return $this->basePath; } public function setEntityPath($entityPath) { $this->entityPath = $entityPath; } public function getEntityPath() { return $this->entityPath; } public function setProxyPath($proxyPath) { $this->proxyPath = $proxyPath; } public function getProxyPath() { return $this->proxyPath; } public function setDbname($dbname) { $this->dbname = $dbname; } public function getDbname() { return $this->dbname; } public function setDriver($driver) { $this->driver = $driver; } public function getDriver() { return $this->driver; } public function setHost($host) { $this->host = $host; } public function getHost() { return $this->host; } public function setPassword($password) { $this->password = $password; } public function getPassword() { return $this->password; } public function setUser($user) { $this->user = $user; } public function getUser() { return $this->user; } /** * @return EntityManager */ public function getEntityManager() { return $this->em; } }
initDoctrine
method. Let's sort out the code in more detail.
$cache = new Doctrine\Common\Cache\FilesystemCache($this->getBasePath() . '/cache'); $config = new Configuration(); $config->setMetadataCacheImpl($cache);
FilesystemCache
) should be better made into the parameters of the component, which we could change when configuring the component.
$driverImpl = new AnnotationDriver(new AnnotationReader(), $this->getEntityPath()); AnnotationRegistry::registerAutoloadNamespace('Doctrine\ORM\Mapping', $this->getBasePath() . '/vendor'); $config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl($cache); $config->setProxyDir($this->getProxyPath()); $config->setProxyNamespace('Proxies'); $config->setAutoGenerateProxyClasses(true);
$connectionOptions = array( 'driver' => $this->getDriver(), 'user' => $this->getUser(), 'password' => $this->getPassword(), 'host' => $this->getHost(), 'dbname' => $this->getDbname() ); $this->em = EntityManager::create($connectionOptions, $config);
$connectionOptions
and $config
, with which you can work with our entities.
DoctrineComponent
to the project.
return array( 'components' => array( 'doctrine'=>array( 'class' => 'DoctrineComponent', 'basePath' => __DIR__ . '/../', 'proxyPath' => __DIR__ . '/../proxies', 'entityPath' => array( __DIR__ . '/../entities' ), 'driver' => 'pdo_mysql', 'user' => 'dbuser', 'password' => 'dbpassword', 'host' => 'localhost', 'dbname' => 'somedb' ), // ... );
Yii::app()->doctrine
, and we can get the EntityManager
through Yii::app()->doctrine->getEntityManager()
EntityManager
object. For this, the following solution was invented:
lass MainController extends Controller { private $entityManager = null; /** * @return Doctrine\ORM\EntityManager */ public function getEntityManager() { if(is_null($this->entityManager)){ $this->entityManager = Yii::app()->doctrine->getEntityManager(); } return $this->entityManager; } // ... }
MainController
and thus, in each controller, you can call the $this->getEntityManager()
method to get an entity manager, and the IDE will now work with method hints for the EntityManager
, which is undoubtedly a plus.
doctrine
command to start the console even more simply, but I haven’t done it yet.
doctrine.php
file for working with the Doctrine console.
// change the following paths if necessary $yii = __DIR__ .'path/to/yii.php'; $config = __DIR__ . 'path/to/config/console.php'; require_once($yii); Yii::createWebApplication($config); Yii::setPathOfAlias('Symfony', Yii::getPathOfAlias('application.vendor.Symfony')); $em = Yii::app()->doctrine->getEntityManager(); $helperSet = new \Symfony\Component\Console\Helper\HelperSet(array( 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) )); \Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);
php doctrine.php
.
Entity
and Repository
. Entity
typically includes business logic, and in Repository
, methods for retrieving data from a database using DBAL Doctrine (or entity manager, or other methods).
User
entity as an example.
CModel.
class CModel.
use Doctrine\ORM\Mapping as ORM; /** * User * * @ORM\Table(name="user") * @ORM\Entity(repositoryClass="UserRepository") * @ORM\HasLifecycleCallbacks */ class User extends CModel { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var string * * @ORM\Column(name="name", type="string", length=255, nullable=false) */ private $name; /** * @var string * * @ORM\Column(name="password", type="string", length=255, nullable=false) */ private $password; /** * @var string * * @ORM\Column(name="email", type="string", length=255, nullable=false) */ private $email; /** * @var string * * @ORM\Column(name="role", type="string", length=255, nullable=false) */ private $role; /** * @var \DateTime * * @ORM\Column(name="created", type="datetime", nullable=false) */ private $created; /** * @var \DateTime * * @ORM\Column(name="modified", type="datetime", nullable=false) */ private $modified; public function rules(){ return array( array('name, password', 'required'), // ... ); } public function attributeNames() { return array( 'id'=>'id', 'name'=>'name', 'email'=>'email', 'created'=>'created', 'updated'=>'updated' ); } public function attributeLabels() { return array( 'description' => 'Description', 'createdString' => 'Creation Date' ); } // ... }
/** * Creates a new model. * If creation is successful, the browser will be redirected to the 'view' page. */ public function actionCreate() { $user = new User(); $userData = $this->getRequest()->get('User'); $course->setAttributes($userData); if(!is_null($userData) && $user->validate()) { $user->setName($userData['name']); // ... $this->getEntityManager()->persist($user); $this->getEntityManager()->flush(); $this->redirect(array('view','id'=>$user->getId())); } $this->render('create',array( 'model'=>$user, )); }
ActiveRecord
(I mean the GridView
widget). And personally, I would like to get them to work with Doctrine and entities. For this you can use the Repository
.
GridView
there are 2 bottlenecks - the dataProvider
and filter
properties. And here I sing odes to Yii developers - in order for GridView
work with some data other than ActiveRecord
, it is enough that the object transferred to the GridView
as a dataProvider
correctly implements the IDataProvider
interface (this interface should be implemented in our UserRepository
), and the object passed to filter
must inherit from CModel
(our User
entity is already well suited for this).
UserRepository
, I will outline only the general scheme.
use Doctrine\ORM\EntityRepository; abstract class BaseRepository extends EntityRepository implements IDataProvider { protected $_id; private $_data; private $_keys; private $_totalItemCount; private $_sort; private $_pagination; public $modelClass; public $model; public $keyAttribute; private $_criteria; private $_countCriteria; public $data; abstract protected function fetchData(); abstract protected function calculateTotalItemCount(); public function getId(){ //... } public function getPagination($className='CPagination'){ //... } public function setPagination($value){ //... } public function setSort($value){ //... } public function getData($refresh=false){ //... } public function setData($value){ //... } public function getKeys($refresh=false){ //... } public function setKeys($value){ //... } public function getItemCount($refresh=false){ //... } public function getTotalItemCount($refresh=false){ //... } public function setTotalItemCount($value){ //... } public function getCriteria(){ //... } public function setCriteria($value){ //... } public function getCountCriteria(){ //... } public function setCountCriteria($value){ //... } public function getSort($className='CSort'){ //... } protected function fetchKeys(){ //... } private function _getSort($className){ //... } }
CActiveDataProvider
which implements the IDataProvider
interface. In the UserRepository
we only have to define 2 methods (sample code below):
<?php class UserRepository extends BaseRepository { protected $_id = 'UserRepository'; /** * Fetches the data from the persistent data storage. * @return array list of data items */ protected function fetchData() { //... } /** * Calculates the total number of data items. * @return integer the total number of data items. */ protected function calculateTotalItemCount() { //... } }
Source: https://habr.com/ru/post/208182/