sokil / php-mongo

MongoDB ODM. Part of @PHPMongoKit
http://phpmongokit.github.io/
MIT License
242 stars 46 forks source link

Making behaviors work with Document events #164

Closed angelxmoreno closed 6 years ago

angelxmoreno commented 6 years ago

Looking at the docs and the code it is not apparently obvious how i can create a behavior that listens to the events on the document it is attached to. For example, I would like to create a behavior that sets date fields on a beforeSave event of the document.

How do I accomplish this?

sokil commented 6 years ago

Behavior is just implementation of traits on php versions where traits not supported, so uou can just add some methods for all documents where trait added, and then through getOwner get instance of Document.

<?php

class SomeBehavior extends Behavior
{
    public function doSome()
    {
        $this->getOwner()->onBeforeSave(function() {});
    }
}

And then you must call this method directly:

<?php

$document->attachBehavior('someBehavior', SomeBehavior::class);
$document->doSome();

If you just want to add some functionality to Document, use Document::beforeConstruct().


<?php

class SomeDocument extends Document
{
    public function beforeConstruct()
    {
         $this->onBeforeSave(function() {})
    }
}
angelxmoreno commented 6 years ago

Thank you. I will rework my solution to make use of traits instead. This was my solution, a bit hacky and requires more thought but got the job done:


namespace AXM\Slim\Core\Model\Document\Behavior;

use Sokil\Mongo\Behavior;
use Sokil\Mongo\Document;
use Sokil\Mongo\Event;

/**
 * Class BehaviorBase
 * @package AXM\Slim\Core\Model\Document\Behavior
 *
 * @method void afterConstruct(Event $event)
 * @method void beforeValidate(Event $event)
 * @method void afterValidate(Event $event)
 * @method void validateError(Event $event)
 * @method void beforeInsert(Event $event)
 * @method void afterInsert(Event $event)
 * @method void beforeUpdate(Event $event)
 * @method void afterUpdate(Event $event)
 * @method void beforeSave(Event $event)
 * @method void afterSave(Event $event)
 * @method void beforeDelete(Event $event)
 * @method void afterDelete(Event $event)
 */
abstract class BehaviorBase extends Behavior
{
    /**
     * @var array
     */
    protected $event_names = [
        'afterConstruct',
        'beforeValidate',
        'afterValidate',
        'validateError',
        'beforeInsert',
        'afterInsert',
        'beforeUpdate',
        'afterUpdate',
        'beforeSave',
        'afterSave',
        'beforeDelete',
        'afterDelete',
    ];

    /**
     * @param $owner
     * @return $this
     */
    public function setOwner($owner)
    {
        parent::setOwner($owner);
        $this->attachEvents();
        return $this;
    }

    protected function attachEvents()
    {
        /** @var Document $doc */
        $doc = $this->getOwner();
        foreach ($this->event_names as $event_name) {
            if (method_exists($this, $event_name)) {
                $doc->attachEvent($event_name, [$this, $event_name], 100);
            }
        }
    }
}