We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Why is "parent model's" validation being triggered?!

Hello!

I have a folowing relationship: Gallery model, which has all the gallery information and GalleryImage model, which has images from the Gallery. GalleryImage has:

$this->belongsTo('galleryId', 'Gallery', 'id', ['alias' => 'gallery']);

Gallery has it's own validation() method used which makes sure user can't create a gallery without a name and that the gallery's slug (URL) is unique.

GalleryImage has no validation method as there are no model-level validations required.

However, for some reason when I trigger save() in the GalleryImage model, the validation in Gallery model is executed and fails with an error saying that "Slug is not unique".

How can this happen? I'm using Phalcon 3.1.0.

edited Mar '17

Post your code causing a problem, this is expected behavior i guess.

If you will do something like:

$galleryImage = new GalleryImage();
$galleryImage->gallery = new Gallery();
$galleryImage->save();

Then this save will try to create and validate both Gallery object and GalleryImage.



2.9k

I was trying to avoid posting a whole lot of code, but here goes:

Gallery model:

use Phalcon\Validation;
use Phalcon\Validation\Validator\Uniqueness;

class Gallery extends ModelBase {

    public function initialize() {

        $this->setSource('gallery');

        $this->hasMany(
            'id',
            'GalleryImage',
            'galleryId',
            [
                'alias' => 'images'
            ]
        );

    }

    public function columnMap() {
        return [
            'id' => 'id', 
            'name' => 'name', 
            'slug' => 'slug', 
            'description' => 'description',
            'rating' => 'rating'
        ];
    }

    public function validation() {

        $validator = new Validation();

        $validator->add('slug', new Uniqueness([
            'message' => 'This slug already exists!'
        ]));

        return $this->validate($validator);

    }

}

GalleryImage model:

class GalleryImage extends ModelBase {

    public function initialize() {

        parent::initialize();

        $this->setSource('gallery_image');
        $this->belongsTo('galleryId', 'Gallery', 'id', ['alias' => 'gallery']);

    }

    public function columnMap() {

        return [
            'id' => 'id', 
            'gallery_id' => 'galleryId',
            'title' => 'title',
            'image' => 'image',
            'link' => 'link'
        ];

    }

    public function beforeSave () {

        $this->link = trim($this->link);

        if (empty($this->link) && !is_null($this->link)) {
            $this->link = NULL;
        }

    }

}

The Gallery model may have NULL slug, in which case gallery is not accessible on the web site. However, since Uniqueness checks NULL against other NULLs, it will fail, even though it was not the Gallery object that was being saved, rather a GalleryImage object.

The fix was to do this in the Gallery object:

public function validation() {

    $validator = new Validation();

    if (!empty($this->slug)) {

        $validator->add('slug', new Uniqueness([
            'message' => 'This slug already exists!'
        ]));

    }

    return $this->validate($validator);
}

However, I'm still puzzled why is Gallery object being validated if save is being made on GalleryImage.

edited Mar '17

But you didn't provide code how are you saving

Instead of:

 if (!empty($this->slug)) {

        $validator->add('slug', new Uniqueness([
            'message' => 'This slug already exists!'
        ]));

    }

Do:

        $validator->add('slug', new Uniqueness([
            'message' => 'This slug already exists!',
            'allowEmpty' => true
        ]));

But better post your code, it might be about something other. Maybe you just need to change your relation:

$this->belongsTo('galleryId', 'Gallery', 'id', ['alias' => 'gallery', 'foreignKey' => ['allowNulls' => true]]);