SlideShare ist ein Scribd-Unternehmen logo
1 von 142
Doctrator
           Pablo Díez




Symfony Live 2011 - San Francisco
Pablo Díez
Creator of Mondongo
  ODM for MongoDB and PHP
  http://mondongo.es (in English :)
Creator of Mondator
  Class generator for PHP
Creator of Doctrator




http://twitter.com/pablodip
http://github.com/pablodip
What is Doctrator?
Doctrator = Doctrine2 + Mondator
Agile Development
Agile Development

  ActiveRecord
Agile Development

  ActiveRecord      optional
Agile Development
  ActiveRecord
    Behaviors
Agile Development
          ActiveRecord
             Behaviors

Doctrator saves you a lot of time! ;)
How does Doctrine2 work?
How does Doctrine2 work?

“Doctrine2 provides transparent persistence for PHP objects.”




                            http://www.doctrine-project.org/docs/orm/2.0/en/reference/introduction.html
That is, persist PHP objects without restrictions of a base class,
                      properties, methods.


                       namespace Model;

                       class User
                       {
                           public $id;
                           public $username;
                           public $email;
                       }
You only have to tell Doctrine2 (map) what you want to persist.
You only have to tell Doctrine2 (map) what you want to persist.

                 With Docblock Annotations

                    /**
                      * @Entity
                      */
                    class User
                    {
                         /**
                          * @Id
                          * @Column(type="integer")
                          */
                         public $id;

                        /**
                         * @Column(length=50)
                         */
                        public $username;

                        /**
                         * @Column(length=100)
                         */
                        public $email;
                    }
You only have to tell Doctrine2 (map) what you want to persist.

                            With YAML


            EntitiesUser:
                type: entity
                fields:
                    id:       { type: integer, id: true }
                    username: { type: string(50) }
                    email:    { type: string(50) }
You only have to tell Doctrine2 (map) what you want to persist.

                                          With XML


    <?xml version="1.0" encoding="UTF-8"?>
    <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                              http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

        <entity name="ModelUser" table="user">

            <id name="id" type="integer" column="id">
                <generator strategy="AUTO"/>
            </id>

            <field name="username" type="string" length="50" />
            <field name="email" type="string" length="100" />

        </entity>

    </doctrine-mapping>
You only have to tell Doctrine2 (map) what you want to persist.

                              With PHP


                     $metadata->mapField(array(
                         'id' => true,
                         'fieldName' => 'id',
                         'type' => 'integer'
                     ));

                     $metadata->mapField(array(
                         'fieldName' => 'username',
                         'type' => 'string'
                     ));

                     $metadata->mapField(array(
                        'fieldName' => 'email',
                        'type' => 'string'
                     ));
You only have to tell Doctrine2 (map) what you want to persist.


      Then you are able to persist those objects.
Then you are able to persist those objects.


         $user = new User();
         $user->username = 'pablodip';
         $user->password = 'pa$$word';
         $user->email = 'pablodip@gmail.com';

         $entityManager->persist($user);
         $entityManager->flush();
A Doctrine2 best practice is to use non public
         properties in the entities.

              class User
              {
                  protected   $id;
                  protected   $username;
                  protected   $password;
                  protected   $email;
              }
You have to create methods to access to the properties.

                     Setters & Getters

                public function setId($id)
                {
                    $this->id = $id;
                }

                public function getId()
                {
                    return $this->id;
                }

                public function setUsername($username)
                {
                    $this->username = $username;
                }

                public function getUsername()
                {
                    return $this->username;
                }

                public function setPassword($password)
                {
                    $this->password = $password;
What do you need to work with this simple table?


                         user
                   id           integer
                username        string
                password        string
                 email          string
namespace Model;

   class User
   {
   }



                Class

         user
   id             integer
username           string
password           string
 email             string
namespace Model;

protected   $id;            class User
protected   $username;      {
protected   $password;      }
protected   $email;


                                         Class
            Properties
                                  user
                            id             integer
                         username           string
                         password           string
                          email             string
namespace Model;

   protected       $id;                             class User
   protected       $username;                       {
   protected       $password;                       }
   protected       $email;


                                                                 Class
                  Properties
                                                           user
                                                    id             integer
                                               username             string
public function setId($id)
{

}
    $this->id = $id;
                                               password             string
public function getId()
{
    return $this->id;
                                                  email             string
}

public function setUsername($username)
{
    $this->username = $username;         Setters/Getters
}

public function getUsername()
{
    return $this->username;
}

public function setPassword($password)
{
    $this->password = $password;
namespace Model;

   protected       $id;                             class User
   protected       $username;                       {
   protected       $password;                       }
   protected       $email;


                                                                 Class
                                                                                     Mapping
                  Properties
                                                           user
                                                    id             integer
                                                                             /**
                                                                              * @Entity
                                               username             string    */
public function setId($id)
{                                                                                /**

}
    $this->id = $id;
                                               password             string        * @Id
                                                                                  * @Column(type="integer")
                                                                                  */
public function getId()
{
    return $this->id;
                                                  email             string       /**
                                                                                  * @Column(length=50)
}
                                                                                  */
public function setUsername($username)
{
    $this->username = $username;         Setters/Getters                         /**
                                                                                  * @Column(length=100)
}                                                                                 */

public function getUsername()
{
    return $this->username;
}

public function setPassword($password)
{
    $this->password = $password;
namespace Model;

                          /**
                            * @Entity
                            */
                          class User
                          {
                               /**
                                * @Id
                                * @Column(type="integer")
                                */
                               protected $id;

                              /**
                               * @Column(length="50")
                               */
                              protected $username;

                              /**
                               * @Column(length="40")
                               */
                              protected $password;

                              /**
         user                  * @Column(length="100")
                               */
                              protected $email;

   id           integer       public function setId($id)
                              {
                                  $this->id = $id;
                              }
username        string        public function getId()
                              {
                                  return $this->id;
password        string        }

                              public function setUsername($username)
                              {
 email          string        }
                                  $this->username = $username;


                              public function getUsername()
                              {
                                  return $this->username;
                              }

                              public function setPassword($password)
                              {
                                  $this->password = $password;
                              }

                              public function getPassword()
                              {
                                  return $this->password;
                              }

                              public function setEmail($email)
                              {
                                  $this->email = $email;
                              }

                              public function getEmail()
                              {
                                  return $this->email;
                              }
                          }
namespace Model;

                          /**
                            * @Entity
                            */
                          class User
                          {
                               /**
                                * @Id
                                * @Column(type="integer")
                                */
                               protected $id;

                              /**
                               * @Column(length="50")
                               */
                              protected $username;

                              /**
                               * @Column(length="40")
                               */
                              protected $password;

                              /**
         user                  * @Column(length="100")
                               */
                              protected $email;

   id           integer       public function setId($id)
                              {
                                  $this->id = $id;


                                                                       LORC
                              }
username        string        public function getId()
                              {
                                  return $this->id;
password        string        }

                              public function setUsername($username)
                              {
 email          string        }
                                  $this->username = $username;


                              public function getUsername()
                              {
                                  return $this->username;
                              }

                              public function setPassword($password)
                              {
                                  $this->password = $password;
                              }

                              public function getPassword()
                              {
                                  return $this->password;
                              }

                              public function setEmail($email)
                              {
                                  $this->email = $email;
                              }

                              public function getEmail()
                              {
                                  return $this->email;
                              }
                          }
LORC

Lines Of Repetitive Code
LORC
      Lines Of Repetitive Code


... and we still don’t have any features! :)
How many LORC do we need in a real database?
How many LORC do we need in a real database?

                    ...
Doctrator’s principle is to avoid writing LORC
What does Doctrator do?
What does Doctrator do?

Doctrator generates classes and maps them with Doctrine2
Doctrator generates classes and maps them with Doctrine2


    You only have to tell it the configuration of the classes.
In PHP


array(
    'ModelUser' => array(
        'columns' => array(
            'id'       => array('id' => 'auto', 'type' => 'integer'),
            'username' => array('type' => 'string', 'length' => 50),
            'password' => array('type' => 'string', 'length' => 40),
            'email'    => array('type' => 'string', 'length' => 100),
        ),
    ),
);
In YAML



ModelUser:
    columns:
        id:         {   id: auto, type: integer }
        username:   {   type: string, length: 50 }
        password:   {   type: string, length: 40 }
        email:      {   type: string, length: 100 }
ModelUser:
                                         columns:
                                             id:         {   id: auto, type: integer }
                                             username:   {   type: string, length: 50 }
                                             password:   {   type: string, length: 40 }
                                             email:      {   type: string, length: 100 }




This generates your object.                                              This maps your object.
     class User
     {

        protected $id;

        protected $username;
                                                                               /**
        protected $password;
                                                                                * @Entity
        protected $email;
                                                                                */
        public function setId($id)
        {
            $this->id = $id;
        }                                                                          /**
        public function getId()                                                     * @Id
        {
            return $this->id;                                                       * @Column(type="integer")
        }
                                                                                    */
        public function setUsername($username)
        {
            $this->username = $username;
        }                                                                          /**
        public function getUsername()                                               * @Column(length=50)
        {
            return $this->username;
                                                                                    */
        }

        public function setPassword($password)
        {
                                                                                   /**
        }
            $this->password = $password;                                            * @Column(length=100)
        public function getPassword()
                                                                                    */
        {
            return $this->password;
        }

         public function setEmail($email)
ModelUser:
    columns:
        id:         {   id: auto, type: integer }
        username:   {   type: string, length: 50 }
        password:   {   type: string, length: 40 }
        email:      {   type: string, length: 100 }




      You can start to work.


$user = new ModelUser();
$user->setUsername('pagafantas');
$user->setEmail('pagafantas@gmail.com');

$entityManager->persist($user);
$entityManager->flush();
How does Doctrator work?
How does Doctrator work?

Doctrator uses Mondator to generate the classes for you.
Mondator defines PHP classes.
namespace Model;

class User
{
    protected $username;

    public function setUsername($username)
    {
        $this->username = $username;
    }

    public function getUsername()
    {
        return $this->username;
    }
}
namespace Model;           Definition

class User
{                                      Properties
    protected $username;

    public function setUsername($username)
    {
        $this->username = $username;
    }

    public function getUsername()
    {
        return $this->username;
    }
}
                                              Methods
use MondongoMondatorDefinitionDefinition;
use MondongoMondatorDefinitionProperty;
use MondongoMondatorDefinitionMethod;
namespace Model;

class User
{
}
                              Full Class Name



$definition = new Definition('ModelUser');
protected $username;



                            Visibility   Name



$property = new Property('protected', 'username');
$definition->addProperty($property);
public function setUsername($username)
{
    $this->username = $username;
}


                      Visibility   Name         Arguments     Code


$method = new Method('public', 'setUsername', '$username', <<<EOF
        $this->username = $username;
EOF
);
$definition->addMethod($method);
You can define any PHP class.
Parent class
$definition->setParentClass('ModelBaseUser');


                    Interfaces
$definition->addInterface('ArrayAccess');


                     Abstract
$definition->setIsAbstract(true);
Default value
$property->setValue($defaultValue);



                      Static
$property->setIsStatic(true);
Abstract
$method->setIsAbstract(true);



                      Static
$method->setIsStatic(true);
Even with comments.
$definition->setDocComment(<<<EOF
/**
 * User Class.
 */
EOF
);

$method->setDocComment(<<<EOF
    /**
     * Set the username.
     *
     * @param string $username The username.
     */
EOF
);
Then you can export them with the Dumper.


      use MondongoMondatorDumper;

      $dumper = new Dumper($definition);
      $classCode = $dumper->dump();




      echo $classCode;
/**
  * User entity.
  */
class User
{
     protected $username;

    /**
      * Set the username.
      *
      * @param string $username The username.
      */
    public function setUsername($username)
    {
         $this->username = $username;
    }

    /**
      * Returns the username.
      *
      * @return string The username.
      */
    public function getUsername()
    {
         return $this->username;
    }
}
And save them in files.


file_put_contents($file, $codeClass);
Mondator Extensions
Mondator Extensions

Mondator uses extensions to generate similar classes
          in a powerful and flexible way.
The Mondator Extensions process the config classes
     to define what classes will be generated.
ModelUser:
               columns:
                   id:         {   id: auto, type: integer }
                   username:   {   type: string, length: 50 }
                   password:   {   type: string, length: 40 }
                   email:      {   type: string, length: 100 }




The Mondator Extensions process the config classes
     to define what classes will be generated.


          MondongoMondatorDefinitionDefinition
ModelUser:
            columns:
                id:         {   id: auto, type: integer }
                username:   {   type: string, length: 50 }
                password:   {   type: string, length: 40 }
                email:      {   type: string, length: 100 }



use MondongoMondatorExtension;

class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        $this->class;
        $this->configClass;

           $this->definitions;
    }
}
ModelUser:
            columns:
                id:         {   id: auto, type: integer }
                username:   {   type: string, length: 50 }
                password:   {   type: string, length: 40 }
                email:      {   type: string, length: 100 }



use MondongoMondatorExtension;

class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        $this->class;
        $this->configClass;

           $this->definitions;
    }
}
ModelUser:
            columns:
                id:         {   id: auto, type: integer }
                username:   {   type: string, length: 50 }
                password:   {   type: string, length: 40 }
                email:      {   type: string, length: 100 }



use MondongoMondatorExtension;

class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        $this->class;
        $this->configClass;

           $this->definitions;
    }
}
ModelUser:
            columns:
                id:         {   id: auto, type: integer }
                username:   {   type: string, length: 50 }
                password:   {   type: string, length: 40 }
                email:      {   type: string, length: 100 }



use MondongoMondatorExtension;

class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        $this->class;
        $this->configClass;

           $this->definitions;
    }
}                                                Definitions to generate
An extension can generate any definition.
use MondongoMondatorExtension;
use MondongoMondatorDefinitionDefinition;

class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        $definition = new Definition($this->class);
        $this->definitions['entity'] = $definition;

        $definition = new Definition($this->class.'Repository');
        $this->definitions['repository'] = $definition;
    }
}
foreach ($this->configClass['columns'] as $name => $column) {

    $property = new Property('protected', $name);

    $this->definitions['entity']->addProperty($property);

}
foreach ($this->configClass['columns'] as $name => $column) {

      $setterName = 'set'.Inflector::camelize($name);
      $setter = new Method('public', $setterName, '$value', <<<EOF
          $this->$name = $value;
EOF
      );

      $this->definitions['entity']->addMethod($setter);
}
Different extensions can modify the same definition.
class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        $definition = new Definition($this->class);
        $this->definitions['entity'] = $defintion;

        $this->processColumns();
    }
}



class ArrayAccess extends Extension
{
    protected function doClassProcess()
    {
        $this->definitions['entity']->addInterface('ArrayAccess');

        $method = new Method('public', 'offsetGet', '$name', $code);
        $this->definitions['entity']->addMethod($method);

        // ...
    }
}
An extension can have options.
class Doctrator extends Extension
{
    protected function setUp()
    {
        $this->addOptions(array(
            'columns'      => true,
            'array_access' => true,
        ));
    }

    protected function doClassProcess()
    {
        if ($this->getOption('columns')) {
            $this->processColumns();
        }

        if ($this->getOption('array_access')) {
            $this->processArrayAccess();
        }
    }
}
You can process the extensions that you want.
$mondator = new MondongoMondatorMondator();
$mondator->setConfigClasses($configClasses);
$mondator->setExtensions(array(
    new DoctratorExtensionCore($options),
));
$mondator->process();
$mondator = new MondongoMondatorMondator();
$mondator->setConfigClasses($configClasses);
$mondator->setExtensions(array(
    new DoctratorExtensionCore($options),
    new DoctratorExtensionArrayAccess(),
));
$mondator->process();
$mondator = new MondongoMondatorMondator();
$mondator->setConfigClasses($configClasses);
$mondator->setExtensions(array(
    new DoctratorExtensionCore($options),
    new DoctratorExtensionArrayAccess(),
));
$mondator->process();




$article['title'] = 'Doctrator';
echo $article['title']; // Doctrator
$mondator = new MondongoMondatorMondator();
$mondator->setConfigClasses($configClasses);
$mondator->setExtensions(array(
    new DoctratorExtensionCore($options),
    //new DoctratorExtensionArrayAccess(),
));
$mondator->process();




$article['title'] = 'Doctrator';
echo $article['title']; // Doctrator
An extension can change the config class to extend
               another extension.
class Doctrator extends Extension
{
    protected function doClassProcess()
    {
        foreach ($this->configClass['columns'] as $name => $column) {
            // ...
        }
    }
}




class DateColumn extends Extension
{
    protected function doConfigClassProcess()
    {
        $this->configClass['columns']['date'] = array(
            'type' => 'date',
        )
    }
}
You can even use extensions in the config classes.
ModelArticle:
    columns:
        id:     { id: auto, type: integer }
        title: { type: string, length: 100 }
    behaviors:
        -
             class: DoctratorBehaviorTimestampable
             options: { }
And you can combine all these things to do what you
                      want.
Generated code is not necessarily magic code.
Doctrator’s generated code is really simple, non-
                 magical code.
Code even with PHPDoc.
You can use IDE Autocompletion.
Doctrator Extensions
Doctrator Extensions

                          Core

ArrayAccess   PropertyOverloading   ActiveRecord   Behaviors
Core


Generates and maps objects with Doctrine2.
Doctrator uses base classes to separate generated
             code from your code.
ModelUser
namespace Model;

class User extends ModelBaseUser
{
    // your code
}

namespace ModelBase;

class User
{
    // generated code
}
ModelArticle:
    table_name: articles
    columns:
        id:        { id: auto, type: integer }
        title:     { type: string, length: 100 }
        slug:      { type: string, length: 100 }
        content:   { type: string }
        is_active: { type: boolean, default: true }
        date:      { type: date }
    many_to_one:
        category: { class: ModelCategory, inversed: articles }
    indexes:
        slug: { columns: ['slug'], unique: true }
        date: { columns: ['is_active', 'date'] }
    events:
        preUpdate: ['updateDate']
Associations
ModelArticle:
    table_name: articles     one_to_one
                            one_to_many
    columns:
                            many_to_one
        id:      { id: auto,many_to_many
                             type: integer }
        title:   { type: string, length: 100 }
        slug:    { type: string, length: 100 }
                                 name
        content: { type: string class
                                  }
                               mapped
        is_active: { type: boolean, default: true }
        date:    { type: date }inversed
    many_to_one:
        category: { class: ModelCategory, inversed: articles }
    indexes:
        slug: { columns: ['slug'], unique: true }
        date: { columns: ['is_active', 'date'] }
    events:
        preUpdate: ['updateDate']
ModelArticle:               Events
    table_name: articles
    columns:                  prePersist
        id:      { id: auto, type: integer }
                              postPersist
        title:   { type: string, length: 100 }
                              preUpdate
        slug:                postUpdate
                 { type: string, length: 100 }
                             preRemove
        content: { type: string }
                             postRemove
        is_active: { type: boolean, default: true }
                               postLoad
        date:    { type: date }
    many_to_one:
        category: { class: ModelCategory, inversed: articles }
    indexes:
        slug: { columns: ['slug'], unique: true }
        date: { columns: ['is_active', 'date'] }
    events:
        preUpdate: ['updateDate']
$category = new ModelCategory();
$category->setName('Class Generator');
$entityManager->persist($category);

$article = new ModelArticle();
$article->setTitle('Doctrator');
$article->setDate(new DateTime('now'));
$article->setCategory($category);
$entityManager->persist($article);

$entityManager->flush();
Core

Useful methods.
Set & Get by string



$article->set('title', 'Doctrator');

echo $article->get('title'); // Doctrator
fromArray & toArray


$article->fromArray(array(
    'title' => 'Doctrator',
    'date' => new DateTime('now')
));

$array = $article->toArray();
ArrayAccess



Implements the ArrayAccess interface in the entities.
$article = new ModelArticle();
$article['title'] = 'Doctrator';
echo $article['title']; // Doctrator
PropertyOverloading


Allows you access to entity data like properties.
$article = new ModelArticle();
$article->title = 'Doctrator';
echo $article->title; // Doctrator
ActiveRecord


Implements the ActiveRecord pattern in your entities.
$article = new ModelArticle();
$article->setTitle('Doctrator');
$article->save();


$article->refresh();


$article->delete();
print_r($article);
print_r($article);



 ModelArticle Object
 (
     [id:protected] => 1
     [title:protected] => Doctrator
     [content:protected] => Rocks!
 )




Doctrator entities are clean even with ActiveRecord!
Doctrator uses a global object to save the EntityManager



  use DoctratorEntityManagerContainer;

  EntityManagerContainer::set($entityManager);
$em = ModelArticle::entityManager();
$articleRepository = ModelArticle::repository();
$queryBuilder = ModelArticle::queryBuilder();
$articles = $entityManager->getRepository('Model
Article')->findAll();
$article = $entityManager->getRepository('Model
Article')->find($id);




$articles = ModelArticle::repository()->findAll();
$article = ModelArticle::repository()->find($id);
Behaviors
Behaviors


Reuse features.
A behavior is simply a Mondator extension.
A behavior can

Have options
Change config classes:
 •   Columns
 •   Associations
 •   Indexes
 •   Events
 •   ...
Add new generated classes
Add properties and methods
 • Entities
 • Repositories
 • ...
Timestampable



Saves the created and updated date.
                created TRUE
        created_column created_at
               updated TRUE
       updated_column updated_at
ModelArticle:
    columns:
        id:    { id: auto, type: integer }
        title: { type: name, length: 100 }
    behaviors:
        - DoctratorBehaviorTimestampable
$article = new ModelArticle();
$article->setTitle('Doctrator');
$article->save();

echo $article->getCreatedAt(); // now
echo $article->getUpdatedAt(); // null

$article->setContent('Rocks!');
$article->save();

echo $article->getCreatedAt(); // before
echo $article->getUpdatedAt(); // now
Ipable



Saves the created and updated ip.
              created TRUE
      created_column created_from
             updated TRUE
      updated_column updated_from
Hashable
               Ipable



Saves a unique hash in each entity.
            column hash
ModelArticle:
    columns:
        id:    { id: auto, type: integer }
        title: { type: name, length: 100 }
    behaviors:
        - DoctratorBehaviorHashable
$article = new Article();
$article->setTitle('Doctrator');

$entityManager->persist();
$entityManager->flush();

echo $article->getHash();
// da39a3ee5e6b4b0d3255bfef95601890afd80709
Timestampable
           Sluggable



Saves a slug from a field.
    from_column *
    slug_column slug
         unique TRUE
         update FALSE
ModelArticle:
    columns:
        id:     { id: auto, type: integer }
        title: { type: name, length: 100 }
    behaviors:
        -
             class: DoctratorBehaviorSluggable
             options: { from_column: title }
$article = new ModelArticle();
$article->setTitle('Doctrator Rocks!');
$article->save();

echo $article->getSlug(); // doctrator-rocks
Sortable



Allows you to sort your entities.
             column position
        new_position bottom
$articles = array();
for ($i = 0; $i <= 10; $i++) {
    $articles[$i] = $a = new ModelArticle();
    $a->setTitle('Article '.$i);
    $a->save();
}

echo $articles[3]->getPosition(); // 3
echo $articles[6]->getPosition(); // 6
// some methods
$articles[1]->isFirst();
$articles[1]->isLast();
$articles[1]->getNext();
$articles[1]->getPrevious();
$articles[1]->swapWith($articles[2]);
$articles[1]->moveUp();
$articles[1]->moveDown();
 
$repository->getMinPosition();
$repository->getMaxPosition();
Taggable
                 Sortable



Allows you to save tags in the entities.
$article = new ModelArticle();
$article->setTitle('My Title');
$article->save();

// methods
$article->addTags('foobar, barfoo');
$article->removeTags('foobar');
$article->removeAllTags(); // saved and not saved
$article->getSavedTags();
$article->getTags(); // saved and not saved
$article->setTags(array('foo', 'bar'));
$article->saveTags();

$repository->getTags();
$repository->getTagsWithCount();
Translatable
                 Taggable
                 Sortable



Allows you to translate entity columns.
              columns *
ModelArticle:
    columns:
        id:       { id: auto, type: integer }
        title:    { type: string, length: 100 }
        content: { type: string }
        date:     { type: date }
    behaviors:
        -
             class: DoctratorBehaviorTranslatable
             options: { columns: ['title', 'content'] }
$article = new ModelArticle();
$article->setDate(new DateTime());

// en
$article->translation('en')->setTitle('My Title');
$article->translation('en')->setContent('My Content');

// es
$article->translation('es')->setTitle('Mi Título');
$article->translation('es')->setContent('Mi Contenido');

$article->save();
Doctrator in Symfony2
DoctratorBundle
doctrator.config:
    extensions:
        array_access:           false
        property_overloading:   false
        active_record:          true
        behaviors:              true

        validation:             true
doctrator.config:
    extensions:
        array_access:           false
        property_overloading:   false
        active_record:          true
        behaviors:              true

        validation:             true

        my_extension_id:        true
Config Classes


    app/config/doctrator/*.yml
*Bundle/Resources/doctrator/*.yml
Standard Namespace

ModelArticle:
    columns:
        id:      { id: auto, type: integer }
        title:   { type: string, length: 100 }
        content: { type: string }


ModelDoctratorUserBundleUser:
    columns:
        id:       { id: auto, type: integer }
        username: { type: string, length: 20 }
ModelArticle:
    validation:
        - MyArticleClassValidator: ~
    columns:
        id:      { id: auto, type: integer }
        title:   { type: string, length: 100 }
        content: { type: string, validation: [MaxLength: 2000] }




                        Validation integrated
php app/console doctrator:generate
Questions?

                 http://mondongo.es (English :)



You can contact me for Mondongo, Doctrator, consulting, development
                       pablodip@gmail.com

Weitere ähnliche Inhalte

Was ist angesagt?

Advanced php
Advanced phpAdvanced php
Advanced phphamfu
 
Object Oriented Programming Basics with PHP
Object Oriented Programming Basics with PHPObject Oriented Programming Basics with PHP
Object Oriented Programming Basics with PHPDaniel Kline
 
Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Karsten Dambekalns
 
Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Karsten Dambekalns
 
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونیاسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونیMohammad Reza Kamalifard
 
Handout - Introduction to Programming
Handout - Introduction to ProgrammingHandout - Introduction to Programming
Handout - Introduction to ProgrammingCindy Royal
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPWildan Maulana
 
0php 5-online-cheat-sheet-v1-3
0php 5-online-cheat-sheet-v1-30php 5-online-cheat-sheet-v1-3
0php 5-online-cheat-sheet-v1-3Fafah Ranaivo
 
Revisiting SOLID Principles
Revisiting  SOLID Principles Revisiting  SOLID Principles
Revisiting SOLID Principles Anis Ahmad
 
Demystifying Object-Oriented Programming - PHP UK Conference 2017
Demystifying Object-Oriented Programming - PHP UK Conference 2017Demystifying Object-Oriented Programming - PHP UK Conference 2017
Demystifying Object-Oriented Programming - PHP UK Conference 2017Alena Holligan
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible CodeAnis Ahmad
 
Doctrator Symfony Live 2011 Paris
Doctrator Symfony Live 2011 ParisDoctrator Symfony Live 2011 Paris
Doctrator Symfony Live 2011 Parispablodip
 
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲Mohammad Reza Kamalifard
 

Was ist angesagt? (20)

Advanced php
Advanced phpAdvanced php
Advanced php
 
Python classes objects
Python classes objectsPython classes objects
Python classes objects
 
Object Oriented Programming Basics with PHP
Object Oriented Programming Basics with PHPObject Oriented Programming Basics with PHP
Object Oriented Programming Basics with PHP
 
Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3
 
Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3
 
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونیاسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
 
Python Metaclasses
Python MetaclassesPython Metaclasses
Python Metaclasses
 
Values
ValuesValues
Values
 
Handout - Introduction to Programming
Handout - Introduction to ProgrammingHandout - Introduction to Programming
Handout - Introduction to Programming
 
Python programming : Classes objects
Python programming : Classes objectsPython programming : Classes objects
Python programming : Classes objects
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
 
0php 5-online-cheat-sheet-v1-3
0php 5-online-cheat-sheet-v1-30php 5-online-cheat-sheet-v1-3
0php 5-online-cheat-sheet-v1-3
 
Revisiting SOLID Principles
Revisiting  SOLID Principles Revisiting  SOLID Principles
Revisiting SOLID Principles
 
Demystifying Object-Oriented Programming - PHP UK Conference 2017
Demystifying Object-Oriented Programming - PHP UK Conference 2017Demystifying Object-Oriented Programming - PHP UK Conference 2017
Demystifying Object-Oriented Programming - PHP UK Conference 2017
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible Code
 
Doctrator Symfony Live 2011 Paris
Doctrator Symfony Live 2011 ParisDoctrator Symfony Live 2011 Paris
Doctrator Symfony Live 2011 Paris
 
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
 
I regret nothing
I regret nothingI regret nothing
I regret nothing
 
Solid in practice
Solid in practiceSolid in practice
Solid in practice
 
Lodash js
Lodash jsLodash js
Lodash js
 

Andere mochten auch (20)

Program conf 2014
Program conf 2014Program conf 2014
Program conf 2014
 
10
1010
10
 
Case1
Case1Case1
Case1
 
Constructia while
Constructia whileConstructia while
Constructia while
 
650 de ani de la formarea statului moldovensc
650 de ani de la formarea statului moldovensc650 de ani de la formarea statului moldovensc
650 de ani de la formarea statului moldovensc
 
AP 3D intro
AP 3D introAP 3D intro
AP 3D intro
 
Constructia for
Constructia forConstructia for
Constructia for
 
Instructiunea if
Instructiunea ifInstructiunea if
Instructiunea if
 
Instructiunea If
Instructiunea IfInstructiunea If
Instructiunea If
 
Fused glass Unit
Fused glass UnitFused glass Unit
Fused glass Unit
 
Boletin
BoletinBoletin
Boletin
 
Afip
AfipAfip
Afip
 
Boletin
BoletinBoletin
Boletin
 
Copia
CopiaCopia
Copia
 
Amparo
AmparoAmparo
Amparo
 
Alimentos
AlimentosAlimentos
Alimentos
 
Boletin
BoletinBoletin
Boletin
 
Boletin
BoletinBoletin
Boletin
 
Afip
AfipAfip
Afip
 
Boletin
BoletinBoletin
Boletin
 

Ähnlich wie Doctrator Symfony Live 2011 San Francisco

Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperJonathan Wage
 
Demystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPDemystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPAlena Holligan
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of LithiumNate Abele
 
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)Ryan Mauger
 
Building DSLs With Eclipse
Building DSLs With EclipseBuilding DSLs With Eclipse
Building DSLs With EclipsePeter Friese
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency InjectionRifat Nabi
 
Demystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHPDemystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHPAlena Holligan
 
Jak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.com
Jak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.comJak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.com
Jak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.comWebScience1
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your CodeDrupalDay
 
Lecture 17 - PHP-Object-Orientation.pptx
Lecture 17 - PHP-Object-Orientation.pptxLecture 17 - PHP-Object-Orientation.pptx
Lecture 17 - PHP-Object-Orientation.pptxDavidLazar17
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Alena Holligan
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 

Ähnlich wie Doctrator Symfony Live 2011 San Francisco (20)

Object Features
Object FeaturesObject Features
Object Features
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
 
Demystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHPDemystifying Object-Oriented Programming - Lone Star PHP
Demystifying Object-Oriented Programming - Lone Star PHP
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
 
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
 
Building DSLs With Eclipse
Building DSLs With EclipseBuilding DSLs With Eclipse
Building DSLs With Eclipse
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Kick Start Jpa
Kick Start JpaKick Start Jpa
Kick Start Jpa
 
Spring data
Spring dataSpring data
Spring data
 
Demystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHPDemystifying Object-Oriented Programming - Midwest PHP
Demystifying Object-Oriented Programming - Midwest PHP
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Jak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.com
Jak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.comJak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.com
Jak neopakovat kód, ale nepo**** abstrakci | Jiří Pudil | 15. 2. 2023 – Kiwi.com
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
Lecture 17 - PHP-Object-Orientation.pptx
Lecture 17 - PHP-Object-Orientation.pptxLecture 17 - PHP-Object-Orientation.pptx
Lecture 17 - PHP-Object-Orientation.pptx
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016Demystifying Object-Oriented Programming - ZendCon 2016
Demystifying Object-Oriented Programming - ZendCon 2016
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 

Kürzlich hochgeladen

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 

Kürzlich hochgeladen (20)

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 

Doctrator Symfony Live 2011 San Francisco

  • 1. Doctrator Pablo Díez Symfony Live 2011 - San Francisco
  • 2. Pablo Díez Creator of Mondongo ODM for MongoDB and PHP http://mondongo.es (in English :) Creator of Mondator Class generator for PHP Creator of Doctrator http://twitter.com/pablodip http://github.com/pablodip
  • 6. Agile Development ActiveRecord
  • 7. Agile Development ActiveRecord optional
  • 8. Agile Development ActiveRecord Behaviors
  • 9. Agile Development ActiveRecord Behaviors Doctrator saves you a lot of time! ;)
  • 11. How does Doctrine2 work? “Doctrine2 provides transparent persistence for PHP objects.” http://www.doctrine-project.org/docs/orm/2.0/en/reference/introduction.html
  • 12. That is, persist PHP objects without restrictions of a base class, properties, methods. namespace Model; class User { public $id; public $username; public $email; }
  • 13. You only have to tell Doctrine2 (map) what you want to persist.
  • 14. You only have to tell Doctrine2 (map) what you want to persist. With Docblock Annotations /** * @Entity */ class User { /** * @Id * @Column(type="integer") */ public $id; /** * @Column(length=50) */ public $username; /** * @Column(length=100) */ public $email; }
  • 15. You only have to tell Doctrine2 (map) what you want to persist. With YAML EntitiesUser: type: entity fields: id: { type: integer, id: true } username: { type: string(50) } email: { type: string(50) }
  • 16. You only have to tell Doctrine2 (map) what you want to persist. With XML <?xml version="1.0" encoding="UTF-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="ModelUser" table="user"> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> <field name="username" type="string" length="50" /> <field name="email" type="string" length="100" /> </entity> </doctrine-mapping>
  • 17. You only have to tell Doctrine2 (map) what you want to persist. With PHP $metadata->mapField(array( 'id' => true, 'fieldName' => 'id', 'type' => 'integer' )); $metadata->mapField(array( 'fieldName' => 'username', 'type' => 'string' )); $metadata->mapField(array( 'fieldName' => 'email', 'type' => 'string' ));
  • 18. You only have to tell Doctrine2 (map) what you want to persist. Then you are able to persist those objects.
  • 19. Then you are able to persist those objects. $user = new User(); $user->username = 'pablodip'; $user->password = 'pa$$word'; $user->email = 'pablodip@gmail.com'; $entityManager->persist($user); $entityManager->flush();
  • 20. A Doctrine2 best practice is to use non public properties in the entities. class User { protected $id; protected $username; protected $password; protected $email; }
  • 21. You have to create methods to access to the properties. Setters & Getters public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password;
  • 22. What do you need to work with this simple table? user id integer username string password string email string
  • 23. namespace Model; class User { } Class user id integer username string password string email string
  • 24. namespace Model; protected $id; class User protected $username; { protected $password; } protected $email; Class Properties user id integer username string password string email string
  • 25. namespace Model; protected $id; class User protected $username; { protected $password; } protected $email; Class Properties user id integer username string public function setId($id) { } $this->id = $id; password string public function getId() { return $this->id; email string } public function setUsername($username) { $this->username = $username; Setters/Getters } public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password;
  • 26. namespace Model; protected $id; class User protected $username; { protected $password; } protected $email; Class Mapping Properties user id integer /** * @Entity username string */ public function setId($id) { /** } $this->id = $id; password string * @Id * @Column(type="integer") */ public function getId() { return $this->id; email string /** * @Column(length=50) } */ public function setUsername($username) { $this->username = $username; Setters/Getters /** * @Column(length=100) } */ public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password;
  • 27. namespace Model; /** * @Entity */ class User { /** * @Id * @Column(type="integer") */ protected $id; /** * @Column(length="50") */ protected $username; /** * @Column(length="40") */ protected $password; /** user * @Column(length="100") */ protected $email; id integer public function setId($id) { $this->id = $id; } username string public function getId() { return $this->id; password string } public function setUsername($username) { email string } $this->username = $username; public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password; } public function getPassword() { return $this->password; } public function setEmail($email) { $this->email = $email; } public function getEmail() { return $this->email; } }
  • 28. namespace Model; /** * @Entity */ class User { /** * @Id * @Column(type="integer") */ protected $id; /** * @Column(length="50") */ protected $username; /** * @Column(length="40") */ protected $password; /** user * @Column(length="100") */ protected $email; id integer public function setId($id) { $this->id = $id; LORC } username string public function getId() { return $this->id; password string } public function setUsername($username) { email string } $this->username = $username; public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password; } public function getPassword() { return $this->password; } public function setEmail($email) { $this->email = $email; } public function getEmail() { return $this->email; } }
  • 30. LORC Lines Of Repetitive Code ... and we still don’t have any features! :)
  • 31. How many LORC do we need in a real database?
  • 32. How many LORC do we need in a real database? ...
  • 33. Doctrator’s principle is to avoid writing LORC
  • 35. What does Doctrator do? Doctrator generates classes and maps them with Doctrine2
  • 36. Doctrator generates classes and maps them with Doctrine2 You only have to tell it the configuration of the classes.
  • 37. In PHP array( 'ModelUser' => array( 'columns' => array( 'id' => array('id' => 'auto', 'type' => 'integer'), 'username' => array('type' => 'string', 'length' => 50), 'password' => array('type' => 'string', 'length' => 40), 'email' => array('type' => 'string', 'length' => 100), ), ), );
  • 38. In YAML ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }
  • 39. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } This generates your object. This maps your object. class User { protected $id; protected $username; /** protected $password; * @Entity protected $email; */ public function setId($id) { $this->id = $id; } /** public function getId() * @Id { return $this->id; * @Column(type="integer") } */ public function setUsername($username) { $this->username = $username; } /** public function getUsername() * @Column(length=50) { return $this->username; */ } public function setPassword($password) { /** } $this->password = $password; * @Column(length=100) public function getPassword() */ { return $this->password; } public function setEmail($email)
  • 40. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } You can start to work. $user = new ModelUser(); $user->setUsername('pagafantas'); $user->setEmail('pagafantas@gmail.com'); $entityManager->persist($user); $entityManager->flush();
  • 42. How does Doctrator work? Doctrator uses Mondator to generate the classes for you.
  • 44. namespace Model; class User { protected $username; public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; } }
  • 45. namespace Model; Definition class User { Properties protected $username; public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; } } Methods
  • 47. namespace Model; class User { } Full Class Name $definition = new Definition('ModelUser');
  • 48. protected $username; Visibility Name $property = new Property('protected', 'username'); $definition->addProperty($property);
  • 49. public function setUsername($username) { $this->username = $username; } Visibility Name Arguments Code $method = new Method('public', 'setUsername', '$username', <<<EOF $this->username = $username; EOF ); $definition->addMethod($method);
  • 50. You can define any PHP class.
  • 51. Parent class $definition->setParentClass('ModelBaseUser'); Interfaces $definition->addInterface('ArrayAccess'); Abstract $definition->setIsAbstract(true);
  • 52. Default value $property->setValue($defaultValue); Static $property->setIsStatic(true);
  • 53. Abstract $method->setIsAbstract(true); Static $method->setIsStatic(true);
  • 55. $definition->setDocComment(<<<EOF /** * User Class. */ EOF ); $method->setDocComment(<<<EOF /** * Set the username. * * @param string $username The username. */ EOF );
  • 56. Then you can export them with the Dumper. use MondongoMondatorDumper; $dumper = new Dumper($definition); $classCode = $dumper->dump(); echo $classCode;
  • 57. /** * User entity. */ class User { protected $username; /** * Set the username. * * @param string $username The username. */ public function setUsername($username) { $this->username = $username; } /** * Returns the username. * * @return string The username. */ public function getUsername() { return $this->username; } }
  • 58. And save them in files. file_put_contents($file, $codeClass);
  • 60. Mondator Extensions Mondator uses extensions to generate similar classes in a powerful and flexible way.
  • 61. The Mondator Extensions process the config classes to define what classes will be generated.
  • 62. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } The Mondator Extensions process the config classes to define what classes will be generated. MondongoMondatorDefinitionDefinition
  • 63. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } }
  • 64. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } }
  • 65. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } }
  • 66. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } } Definitions to generate
  • 67. An extension can generate any definition.
  • 68. use MondongoMondatorExtension; use MondongoMondatorDefinitionDefinition; class Doctrator extends Extension { protected function doClassProcess() { $definition = new Definition($this->class); $this->definitions['entity'] = $definition; $definition = new Definition($this->class.'Repository'); $this->definitions['repository'] = $definition; } }
  • 69. foreach ($this->configClass['columns'] as $name => $column) { $property = new Property('protected', $name); $this->definitions['entity']->addProperty($property); }
  • 70. foreach ($this->configClass['columns'] as $name => $column) { $setterName = 'set'.Inflector::camelize($name); $setter = new Method('public', $setterName, '$value', <<<EOF $this->$name = $value; EOF ); $this->definitions['entity']->addMethod($setter); }
  • 71. Different extensions can modify the same definition.
  • 72. class Doctrator extends Extension { protected function doClassProcess() { $definition = new Definition($this->class); $this->definitions['entity'] = $defintion; $this->processColumns(); } } class ArrayAccess extends Extension { protected function doClassProcess() { $this->definitions['entity']->addInterface('ArrayAccess'); $method = new Method('public', 'offsetGet', '$name', $code); $this->definitions['entity']->addMethod($method); // ... } }
  • 73. An extension can have options.
  • 74. class Doctrator extends Extension { protected function setUp() { $this->addOptions(array( 'columns' => true, 'array_access' => true, )); } protected function doClassProcess() { if ($this->getOption('columns')) { $this->processColumns(); } if ($this->getOption('array_access')) { $this->processArrayAccess(); } } }
  • 75. You can process the extensions that you want.
  • 76. $mondator = new MondongoMondatorMondator(); $mondator->setConfigClasses($configClasses); $mondator->setExtensions(array( new DoctratorExtensionCore($options), )); $mondator->process();
  • 77. $mondator = new MondongoMondatorMondator(); $mondator->setConfigClasses($configClasses); $mondator->setExtensions(array( new DoctratorExtensionCore($options), new DoctratorExtensionArrayAccess(), )); $mondator->process();
  • 78. $mondator = new MondongoMondatorMondator(); $mondator->setConfigClasses($configClasses); $mondator->setExtensions(array( new DoctratorExtensionCore($options), new DoctratorExtensionArrayAccess(), )); $mondator->process(); $article['title'] = 'Doctrator'; echo $article['title']; // Doctrator
  • 79. $mondator = new MondongoMondatorMondator(); $mondator->setConfigClasses($configClasses); $mondator->setExtensions(array( new DoctratorExtensionCore($options), //new DoctratorExtensionArrayAccess(), )); $mondator->process(); $article['title'] = 'Doctrator'; echo $article['title']; // Doctrator
  • 80. An extension can change the config class to extend another extension.
  • 81. class Doctrator extends Extension { protected function doClassProcess() { foreach ($this->configClass['columns'] as $name => $column) { // ... } } } class DateColumn extends Extension { protected function doConfigClassProcess() { $this->configClass['columns']['date'] = array( 'type' => 'date', ) } }
  • 82. You can even use extensions in the config classes.
  • 83. ModelArticle: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } behaviors: - class: DoctratorBehaviorTimestampable options: { }
  • 84. And you can combine all these things to do what you want.
  • 85. Generated code is not necessarily magic code.
  • 86. Doctrator’s generated code is really simple, non- magical code.
  • 87. Code even with PHPDoc.
  • 88. You can use IDE Autocompletion.
  • 90. Doctrator Extensions Core ArrayAccess PropertyOverloading ActiveRecord Behaviors
  • 91. Core Generates and maps objects with Doctrine2.
  • 92. Doctrator uses base classes to separate generated code from your code.
  • 93. ModelUser namespace Model; class User extends ModelBaseUser { // your code } namespace ModelBase; class User { // generated code }
  • 94. ModelArticle: table_name: articles columns: id: { id: auto, type: integer } title: { type: string, length: 100 } slug: { type: string, length: 100 } content: { type: string } is_active: { type: boolean, default: true } date: { type: date } many_to_one: category: { class: ModelCategory, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate']
  • 95. Associations ModelArticle: table_name: articles one_to_one one_to_many columns: many_to_one id: { id: auto,many_to_many type: integer } title: { type: string, length: 100 } slug: { type: string, length: 100 } name content: { type: string class } mapped is_active: { type: boolean, default: true } date: { type: date }inversed many_to_one: category: { class: ModelCategory, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate']
  • 96. ModelArticle: Events table_name: articles columns: prePersist id: { id: auto, type: integer } postPersist title: { type: string, length: 100 } preUpdate slug: postUpdate { type: string, length: 100 } preRemove content: { type: string } postRemove is_active: { type: boolean, default: true } postLoad date: { type: date } many_to_one: category: { class: ModelCategory, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate']
  • 97. $category = new ModelCategory(); $category->setName('Class Generator'); $entityManager->persist($category); $article = new ModelArticle(); $article->setTitle('Doctrator'); $article->setDate(new DateTime('now')); $article->setCategory($category); $entityManager->persist($article); $entityManager->flush();
  • 99. Set & Get by string $article->set('title', 'Doctrator'); echo $article->get('title'); // Doctrator
  • 100. fromArray & toArray $article->fromArray(array( 'title' => 'Doctrator', 'date' => new DateTime('now') )); $array = $article->toArray();
  • 101. ArrayAccess Implements the ArrayAccess interface in the entities.
  • 102. $article = new ModelArticle(); $article['title'] = 'Doctrator'; echo $article['title']; // Doctrator
  • 103. PropertyOverloading Allows you access to entity data like properties.
  • 104. $article = new ModelArticle(); $article->title = 'Doctrator'; echo $article->title; // Doctrator
  • 105. ActiveRecord Implements the ActiveRecord pattern in your entities.
  • 106. $article = new ModelArticle(); $article->setTitle('Doctrator'); $article->save(); $article->refresh(); $article->delete();
  • 108. print_r($article); ModelArticle Object ( [id:protected] => 1 [title:protected] => Doctrator [content:protected] => Rocks! ) Doctrator entities are clean even with ActiveRecord!
  • 109. Doctrator uses a global object to save the EntityManager use DoctratorEntityManagerContainer; EntityManagerContainer::set($entityManager);
  • 110. $em = ModelArticle::entityManager(); $articleRepository = ModelArticle::repository(); $queryBuilder = ModelArticle::queryBuilder();
  • 111. $articles = $entityManager->getRepository('Model Article')->findAll(); $article = $entityManager->getRepository('Model Article')->find($id); $articles = ModelArticle::repository()->findAll(); $article = ModelArticle::repository()->find($id);
  • 114. A behavior is simply a Mondator extension.
  • 115. A behavior can Have options Change config classes: • Columns • Associations • Indexes • Events • ... Add new generated classes Add properties and methods • Entities • Repositories • ...
  • 116. Timestampable Saves the created and updated date. created TRUE created_column created_at updated TRUE updated_column updated_at
  • 117. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - DoctratorBehaviorTimestampable
  • 118. $article = new ModelArticle(); $article->setTitle('Doctrator'); $article->save(); echo $article->getCreatedAt(); // now echo $article->getUpdatedAt(); // null $article->setContent('Rocks!'); $article->save(); echo $article->getCreatedAt(); // before echo $article->getUpdatedAt(); // now
  • 119. Ipable Saves the created and updated ip. created TRUE created_column created_from updated TRUE updated_column updated_from
  • 120. Hashable Ipable Saves a unique hash in each entity. column hash
  • 121. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - DoctratorBehaviorHashable
  • 122. $article = new Article(); $article->setTitle('Doctrator'); $entityManager->persist(); $entityManager->flush(); echo $article->getHash(); // da39a3ee5e6b4b0d3255bfef95601890afd80709
  • 123. Timestampable Sluggable Saves a slug from a field. from_column * slug_column slug unique TRUE update FALSE
  • 124. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - class: DoctratorBehaviorSluggable options: { from_column: title }
  • 125. $article = new ModelArticle(); $article->setTitle('Doctrator Rocks!'); $article->save(); echo $article->getSlug(); // doctrator-rocks
  • 126. Sortable Allows you to sort your entities. column position new_position bottom
  • 127. $articles = array(); for ($i = 0; $i <= 10; $i++) { $articles[$i] = $a = new ModelArticle(); $a->setTitle('Article '.$i); $a->save(); } echo $articles[3]->getPosition(); // 3 echo $articles[6]->getPosition(); // 6
  • 129. Taggable Sortable Allows you to save tags in the entities.
  • 130. $article = new ModelArticle(); $article->setTitle('My Title'); $article->save(); // methods $article->addTags('foobar, barfoo'); $article->removeTags('foobar'); $article->removeAllTags(); // saved and not saved $article->getSavedTags(); $article->getTags(); // saved and not saved $article->setTags(array('foo', 'bar')); $article->saveTags(); $repository->getTags(); $repository->getTagsWithCount();
  • 131. Translatable Taggable Sortable Allows you to translate entity columns. columns *
  • 132. ModelArticle: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string } date: { type: date } behaviors: - class: DoctratorBehaviorTranslatable options: { columns: ['title', 'content'] }
  • 133. $article = new ModelArticle(); $article->setDate(new DateTime()); // en $article->translation('en')->setTitle('My Title'); $article->translation('en')->setContent('My Content'); // es $article->translation('es')->setTitle('Mi Título'); $article->translation('es')->setContent('Mi Contenido'); $article->save();
  • 136. doctrator.config: extensions: array_access: false property_overloading: false active_record: true behaviors: true validation: true
  • 137. doctrator.config: extensions: array_access: false property_overloading: false active_record: true behaviors: true validation: true my_extension_id: true
  • 138. Config Classes app/config/doctrator/*.yml *Bundle/Resources/doctrator/*.yml
  • 139. Standard Namespace ModelArticle: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string } ModelDoctratorUserBundleUser: columns: id: { id: auto, type: integer } username: { type: string, length: 20 }
  • 140. ModelArticle: validation: - MyArticleClassValidator: ~ columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string, validation: [MaxLength: 2000] } Validation integrated
  • 142. Questions? http://mondongo.es (English :) You can contact me for Mondongo, Doctrator, consulting, development pablodip@gmail.com