Doctrine2 Behavioral Extensions

Как-то поверхностно я с Doctrine2 разобрался. Уже несколько раз ловил себя на мысли, что использую далеко не все возможности, а о многих наверное и не в курсе. Поэтому решил поковырять её более предметно.

Разворачиваем Doctrine2 + sandbox

Тянем доктрину с оригинального репозитория и инициализируем/обновляем сабмодули.

/var/www/test/doctrine2 $ git clone git@github.com:doctrine/doctrine2.git .
/var/www/test/doctrine2 $ git submodule init
/var/www/test/doctrine2 $ git submodule update --recursive

В файле tools/sandbox/cli-config.php и tools/sandbox/index.php правим конфиг DBAL:

// Database connection information
$connectionOptions = array(
    'driver' => 'pdo_mysql',
    'dbname' => 'doctrine2',
    'user' => 'root',
    'password' => '',
    'host' => 'localhost',
);

После этого можно запускать CLI скрипт tools/sandbox/doctrine и создавать схему БД:

/var/www/test/doctrine/tools/sandbox $ ./doctrine orm:schema-tool:create
ATTENTION: This operation should not be executed in an production enviroment.
 
Creating database schema...
Database schema created successfully!

Doctrine2 Behavioral Extensions

Для начала решил разобраться с Doctrine2 Behavioral Extensions. В первой Doctrine они назывались Doctrine Templates и мы довольно активно использовали I18n, NestedSet, Sluggable, Timestampable, а возможно даже Versionable и SoftDelete. Помню ещё были шаблоны от сторонних разработчиков, но не могу сейчас найти их на сайте доктрины.

Итак в Doctrine2 эти самые Behavioral Extensions вынесли отдельно. Сопровождением стандартного набора экстеншенов занимается Gediminas Morkevicius из KnpLabs. Они лежат в репо https://github.com/l3pp4rd/DoctrineExtensions и я подключил их через сабмодули.

Чтобы экстеншен заработал нужно для начала натравить автолоадер доктрины/сифони/зф/свой/чужой на скачанные либы. В нашем случае это выглядит вот так:

$classLoader = new \Doctrine\Common\ClassLoader('Gedmo', realpath(__DIR__ . '/../../lib/vendor/doctrine-extensions/lib'));
$classLoader->register();

После этого цепляем обработчики нужных экстеншенов к EventManager’у нашего EntityManager’а:

// Create EntityManager
$em = EntityManager::create($connectionOptions, $config);
// timestable
$em->getEventManager()->addEventSubscriber(new \Gedmo\Timestampable\TimestampableListener());

Для Symfony2 можно использовать DoctrineExtensionsBundle, а для ZF я видел решение на http://zendframework.ru/forum/.

Timestable

Первым шаблон, который я использовал в Doctrine был именно Timestable, Довольно часто нужно фиксировать время создания/редактирования сущности и писать эту логику в каждой модели не есть гуд.

Итак, добавим к модели \Entities\User поле created, значение для которого будет устанавливать Timestampable:

    /**
     * @var datetime $created
     *
     * @gedmo:Timestampable(on="create")
     * @Column(type="date")
     */
    private $created;
 
    public function getCreated()
    {
        return $this->created;
    }

А эту логику нужно поместить в скрипт tools/sandbox/index.php после строк “## PUT YOUR TEST CODE BELOW”:

$user = new User;
$user->setName('Stepan Tanasiychuk');
 
$address = new Address;
$address->setStreet('Lenina street');
 
$user->setAddress($address);
 
$em->persist($user);
$em->persist($address);
$em->flush();
 
var_dump($user);

Если на выходе получился следующий фрагмент, то все ок:

object(Entities\User)[25]
  private 'id' => int 1
  private 'name' => string 'Stepan Tanasiychuk' (length=18)
  private 'address' => 
    object(Entities\Address)[26]
      private 'id' => int 1
      private 'street' => string 'Lenina street' (length=13)
      private 'user' => 
        &object(Entities\User)[25]
  private 'created' => 
    object(DateTime)[33]
      public 'date' => string '2011-04-16 00:55:53' (length=19)
      public 'timezone_type' => int 3
      public 'timezone' => string 'Europe/Kiev' (length=11)

Документация по Timestable.

Дальше я подключил Sluggable и разобрался по какому принципу работают бехевиор экстеншены, но писать об этом уже лень. Давайте хоть то что есть опубликую 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *