Fork me on GitHub

how to use Doctrine 2 behaviors?  Bottom

Go to page 1 - 2 [+1]:

  • Following Drak and Craig's advice I'm testing with Doctrine 2, but I'm having a hard time figuring out how to use the behaviors.
    Using hint from Craig's Tag module I figure I need to use the ORM and Gedmo namespace with

    Code

    use Doctrine\ORM\Mapping as ORM;
    use Gedmo\Mapping\Annotation as Gedmo;


    Then I tried to declare a Timestampable field in my entity with the annotation

    Code

    /**
         * @ORM\Column(type="date")
         * @Gedmo\Timestampable(on="create")
         */

        protected $created_at;


    When I create a new instance of the entity class and try to persist it, there's an SQL error
    SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null

    If I remove the created_at field from my entity definition then it works fine. Apparently the Timestampable behavior isn't working and the created_at field is left null before the persisting. I tried Translatable too, it doesn't work either (no translation table is created as can be confirmed by looking at the output of schemaTool::getCreateSchemaSql()).

    What am I doing wrong? I don't think there's a problem with the availability of the namespaces since they popup in codecompletion in my IDE and Apache didn't complain.
  • There are instructions here: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/timestampable.md#entity for some reason the anchor doesn't work, so scan to the title "Timestampable Entity example: {#entity}".

    Regards,

    Drak

    --
    Zikula Lead Developer
    Board Member of the Zikula Foundation
    Follow me on twitter.com/zikuladrak
  • You can also use ModuleStudio to generate corresponding code.

    --
    Guite | ModuleStudio
  • Thanks Drak. However, looking at the link you gave I believe I'm using Timestampable exactly the same way as in the example with namespace reference

    Code

    use Gedmo\Mapping\Annotation as Gedmo;
    use Doctrine\ORM\Mapping as ORM;


    and annotation

    Code

    /**
         * @Gedmo\Timestampable(on="create")
         * @ORM\Column(type="date")
         */

        protected $created_at;


    The TimestampableListener should have been registered with Doctrine eventmanager in plugins/DoctrineExtensions/Plugin.php. I'm getting an error that the field created_at is null when persisting a new object and flushing the entityManager, which suggests that TimestampableListener isn't doing its job (if it was registered after all). Is there a setting that I need to turn on in order to use the DoctrineExtensions plugin?

    In case it matters, I'm using Zkula_1.3.0, build 3168, the official pre-release. Just wonder if anyone is successful in using Timestampable in Zikula_1.3.0 and knows what I'm doing wrong.



    Edited by xizhou on Sep 17, 2011 - 06:06 PM.
  • The field cannot be null, you need to set the property with an instance of new DateTime() if I recall. You can do that in the constructor for example.

    Regards,

    Drak

    --
    Zikula Lead Developer
    Board Member of the Zikula Foundation
    Follow me on twitter.com/zikuladrak
  • Isn't Timestampable supposed to set the time for created_at for me automatically when I persist a new instance? As far as I understand this is how behavior works. It's also the logic behind my suspicion that the behavior is not working (since created_at is null when I persist the object even though the field's declared Timestampable). Of course I can persist the object if I set created_at to some date (in fact to any date I like not just the moment the object is saved), but if I need to do this then there's no point of using timestampable.

    It's not just Timestampable. I tried translatable and it doesn't work either. A translation table should be created when the schema is created, but this is not the case.
  • Ok, seems I found a piece of clue that might be important. In plugins/DoctrineExtensions/Plugin.php, the behavior listeners are registered with

    Code

    $types = array('Loggable', 'Sluggable', 'Timestampable', 'Translatable', 'Tree', 'Sortable');
            foreach ($types as $type) {
                $definition = new Zikula_ServiceManager_Definition("Gedmo$type\{$type}Listener");
                $this->serviceManager->registerService(strtolower("doctrine_extensions.listener.$type"), $definition);
            }


    Curiously, for Translatable, the listener file is named Gedmo/Translatable/TranslationListener.php, not TranslatableListener.php. I don't know if this matters. I copied TranslationListener.php to TranslatableListener.php in that dir, even tried removing Translatable from the types array, but it doesn't seem to resolve my problem with the behaviors. I suspect the behavior listeners are never registered, but I don't know how to test this.

    Should I file this problem with the behaviors as a bug?
  • I think you might be missing the bootstrap.php example from Craig's module. Also, please try the later build http://ci.zikula.org/job/Zikula_Core-1.3.1/42/ (pending release shortly).

    Regards,

    Drak

    --
    Zikula Lead Developer
    Board Member of the Zikula Foundation
    Follow me on twitter.com/zikuladrak
  • Hi,

    I think I found what's wrong. The behavior listeners need to be registered with \Doctrine\Common\EventManager but in plugins/DoctrineExtensions/Plugin.php they are registered with Zikula_EventManager instead. Taking into account the problem with the naming of Translatable's listener file reported above, I'm using the following in plugins/DoctrineExtensions/Plugin.php to have the behavior listeners work for me:

    Code

    $types = array('Loggable' => 'Loggable', 'Sluggable' => 'Sluggable', 'Timestampable' => 'Timestampable', 'Translatable' => 'Translation', 'Tree' => 'Tree', 'Sortable' => 'Sortable');
            foreach ($types as $behaviorname => $filename) {
                //$definition = new Zikula_ServiceManager_Definition("Gedmo$type\{$type}Listener");
                //$this->serviceManager->registerService(strtolower("doctrine_extensions.listener.$behaviorname"), $definition);
                $listener = "Gedmo$behaviorname\{$filename}Listener";
                $this->serviceManager->getService('doctrine.entitymanager')->getEventManager()->addEventSubscriber(new $listener());
            }


    The way I access Doctrine's eventmanager above is clumsy but I don't know a more straightforward route. I'm guessing somehow Zikula_service is supposed to notify Doctrine when data is about to be created or updated, but it's not working. Adding the behavior listeners to Doctrine's eventmanager does the trick.

    Since this is kind of a serious problem I'll file a bug later. My codes just get around the problem in a dirty way and a more elaborate fix is needed.
  • Please look at the version I posted, this is already addressed AFAIK.

    Drak

    --
    Zikula Lead Developer
    Board Member of the Zikula Foundation
    Follow me on twitter.com/zikuladrak
  • Thanks Drak. There's no need for me to bother with filing a bug report then.
  • Update:

    This problem isn't fixed in Zikula_Core-1.3.1/42/ as Drak suggested, though the naming of TranslationListener was taken care of in that and later build. I tested with build 47. None of the Doctrine 2 behaviors work because of the problem I explained earlier (the behaviors' listeners aren't registered with Doctrine's eventmanager). My codes above are a quick dirty fix.

    I filed a bug on Cozi. It's not a minor issue and hopefully it'll be fixed before 1.3.1 is released.
  • The tracker is at https://github.com/zikula/core/issues
    Have you checked your bootstrap.php is correct? You need something like https://github.com/zikula/core/blob/master/src/docs/examples/modules/ExampleDoctrine/bootstrap.php

    Regards,

    Drak

    --
    Zikula Lead Developer
    Board Member of the Zikula Foundation
    Follow me on twitter.com/zikuladrak
  • By the way, your entity needs a constructor with something like:

    $this->created_at = new DateTime();

    That is how you will get the created at time as a default.

    Regards,

    Drak

    --
    Zikula Lead Developer
    Board Member of the Zikula Foundation
    Follow me on twitter.com/zikuladrak
  • Drak,

    Adding the behaviors' listeners in the module's bootstrap file seems to solve the problem. I don't need to do $this->created_at = new DateTime(); though, timestampable will set the time for me automatically.

    So the issue is about me not knowing how to use the extensions rather than sth wrong with the Core. However, I wonder why I am supposed to register the listeners on a per module basis rather than have them registered globally. Is doing this globally expensive?

    So far I'm successful using Sluggable, Timestampable and Tree. Not so lucky with Translatable; the translation table doesn't seem to be created.

    Thanks and appologies if the bug report is considered mis-filed.

Go to page 1 - 2 [+1]:

  • 0 users

This list is based on users active over the last 60 minutes.