spotorm / spot2

Spot v2.x DataMapper built on top of Doctrine's Database Abstraction Layer
http://phpdatamapper.com
BSD 3-Clause "New" or "Revised" License
601 stars 101 forks source link

Convert empty string to null with eventMitter #219

Closed Sysix closed 7 years ago

Sysix commented 7 years ago

Hey guys, I tried so check my data before saving it into the database. I found that the Mapper has access to an Listener with callback-functions.

My code:

<?php

namespace AddOn\Library\Model;

use Core\Sql\DataObject;
use Spot\EntityInterface;
use Spot\MapperInterface;

class PackageTag extends DataObject // extends Entity
{
    protected static $table = 'package_tags';

    public function getMapper()
    {
        $mapper = parent::getMapper();

        $mapper->eventEmitter()->on('beforeSave', [$this, 'checkParentForEmpty']);

        return $mapper;
    }

    public function checkParentForEmpty(&$tag)
    {
        if ($tag->parent === '') {
            $tag->parent = null;
        }

        return true;
    }

    public function getRootTags()
    {
        return $this->getMapper()->all()->where(['parent' => null]);
    }

    public static function fields()
    {
        return [
            'tag' => [
                'type' => 'string',
                'length' => 255,
                'primary' => true,
            ],
            'parent' => [
                'type' => 'string',
                'length' => 255,
                'index' => true,
                'default' => null
            ]
        ];
    }

    public static function relations(MapperInterface $mapper, EntityInterface $entity)
    {
        return [
            'children' => $mapper->hasMany($entity, __CLASS__, 'parent'),
            'parent' => $mapper->belongsTo($entity, __CLASS__, 'parent')
        ];
    }
}

With XDebug I found, that on EventEmitterTrait:emit the result of the callback is always "null".

What is with the code wrong?

nebulousGirl commented 7 years ago

It shouldn't be possible that it returns null.

See the class used for events: https://github.com/fruux/sabre-event/blob/master/lib/EmitterTrait.php

You don't need the "&" beside $tag either, PHP objects are references by default.

Sysix commented 7 years ago

You don't need the "&" beside $tag either, PHP objects are references by default.

Yeah I know, but for help to understand, that the object is changing.

It shouldn't be possible that it returns null.

I dont see a condition, which check for null. Only for false

tuupola commented 7 years ago

The way you use events looks a bit unorthdox. Have you tried the documented way? Ie. something like:

public static function events(EventEmitter $eventEmitter)
{
    $eventEmitter->on('beforeSave', function (Entity $entity, Mapper $mapper) {
        /* checkParentForEmpty logic here, returning false cancels saving */
        if ($entity->parent === '') {
            $entity->parent = null;
        }
        return true;
    });
}
Sysix commented 7 years ago

I found the problem. It was really the Problem with the reference. The Error-Message was not shown. After I die() in the callback, I could debugging :)

Thanks for the help!