dereuromark / cakephp-tools

A CakePHP Tools plugin containing lots of useful helpers, behaviors, components, shells, ...
http://www.dereuromark.de
MIT License
336 stars 142 forks source link

SluggedBehavior does not work with virtual fields #250

Closed asgraf closed 4 years ago

asgraf commented 4 years ago

I have virtual field name defined in in my Userpackage entity and _getName() getter has been implemented.

//in my /Model/Entity/Userpackage.php
protected $_virtual = [
        'name',
    ];
//in my /Model/Entity/Userpackage.php
 protected function _getName()
    {
        if ($this->custom_name) {
            return $this->custom_name;
        }
        if (!$this->package) {
            throw new InternalErrorException('Invalid Package');
        }
        return $this->package->name;
    }
//in my /Model/Table/UserpackagesTable.php
$this->addBehavior('Tools.Slugged', [
            'label' => 'name',
            'case' => 'low',
            'mode' => [Text::class, 'slug'],
            'unique' => false,
            'overwrite' => true
        ]);

Now i get following error:

(SluggedBehavior::setup) model Userpackages is missing the field name specified in the setup.
dereuromark commented 4 years ago

The behavior is only for DB fetching and real fields. What you want you can easily do inside your _getName() method directly. Just return the Text::slug() value there. No need for any behaviors.

asgraf commented 4 years ago

You seem to not understand my code correctly. I have real field slug in my userpackages table and i want to be able to to search by slug. So i want to fill this real field slug with a string generated from slugging contents of virtual field name

dereuromark commented 4 years ago

I sure don't quite fully understand the use case here. Feel free to provide a patch if you think something could be improved or fixed here.

As for non-real fields support, you could also try to extend/overwrite

public function hasField($field)
{
    if ($field === 'fake') { return true; }

    return parent::hasField($field);
}

in your Table class.

Just an idea.

asgraf commented 4 years ago

Following code seems to solve the problem:

public function hasField($field)
    {
        $virtualFields = $this->newEntity()->getVirtual();
        if(in_array($field, $virtualFields)) {
            return true;
        }

        return parent::hasField($field);
    }

But i still think that slug behavior should work correctly out of the box without need of overriding native cakephp methods

dereuromark commented 4 years ago

Can u maybe add a pr to Support this? Either by making check optional or including virtual fields?

dereuromark commented 4 years ago

My idea: New config key

'checkExistence' => false (default true)

for your case to not check if the field exists in model.

dereuromark commented 4 years ago

Actually, the existence check is mainly done to be able to get some meta data. But it has a fallback in place, and also a passing test case:

testSlugGenerationWithVirtualField()

Can you please check why this test case with a virtual field does work, but your example doesnt?

dereuromark commented 4 years ago

Please use latest master to check I added a better debug message for the error: https://github.com/dereuromark/cakephp-tools/commit/cde92a50ba30702c6c5d8cdd3769641d0873065a

dereuromark commented 4 years ago

Any update here?