Страница 1 из 1

Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.12, 18:24
Matvik
Суть такова:
Есть модель (любая). К ней аттаччится поведение со своими дополнительными аттрибутами.
Хочу для этих аттрибутов зарегистрировать правила валидации (например, safe).
Пробую следующим образом (в поведении):

Код: Выделить всё

public function attach($owner)
    {
        parent::attach($owner);
        $owner->validators[] = Validator::createValidator('safe', $owner, ['galleryImagesDelete', 'galleryImagesOrder']);
    }
При этом странная штука - если посмотреть дебаггером, то в этом методе у овнера появляется новый валидатор, но в контроллере сразу после, например, вызова $model->load() (когда срабатывает метод attach() в поведении), его уже нет. Что с этим делать?

Через beforeValidate не подходит, так как массовое присваивание (для которого нужен safe) не вызывает валидацию. В самой модели тоже не изменяется ничего, даже просто

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.12, 18:57
andku83
$owner->validators - readonly-property
У модели есть свойство $_validators, но к нему похоже доступа не получить.

Попробуйте вот так:

Код: Выделить всё

        parent::attach($owner);
        $validators = $owner->getValidators();
        $validators->append(Validator::createValidator('safe', $owner, ['galleryImagesDelete', 'galleryImagesOrder']);
Идея взята отсюда

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.12, 23:32
Matvik
andku83 писал(а): 2018.04.12, 18:57 $owner->validators - readonly-property
У модели есть свойство $_validators, но к нему похоже доступа не получить.

Попробуйте вот так:

Код: Выделить всё

        parent::attach($owner);
        $validators = $owner->getValidators();
        $validators->append(Validator::createValidator('safe', $owner, ['galleryImagesDelete', 'galleryImagesOrder']);
Идея взята отсюда
Так тоже не работает. Та же ситуация - в методе аттач добавляется, но в экшне снова дефолтный набор.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.13, 08:36
kukuruku

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.13, 09:01
SiZE

Код: Выделить всё

class MyBehavior extends Behavior
{
    private $isAttached = false;

    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
        ];
    }

    public function beforeValidate($event)
    {
        if (!$this->isAttached) {
            $validators = $this->owner->getValidators();
            // а тут все остальные валидаторы
            $validators->append(Validator::createValidator('oops', $this->owner, ['galleryImagesDelete', 'galleryImagesOrder']);

            $this->isAttached = true;
        }
    }

    /**
      * @override
      */
    public function safeAttributes()
    {
         return array_unique(array_merge($this->owner->safeAttributes(), [
             'galleryImagesDelete',
             'galleryImagesOrder'
         ]));
    }
}

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.13, 21:23
Matvik

Код: Выделить всё

/**
      * @override
      */
    public function safeAttributes()
    {
         return array_unique(array_merge($this->owner->safeAttributes(), [
             'galleryImagesDelete',
             'galleryImagesOrder'
         ]));
    }
К сожалению, так не работает, дебагерром проверял, в этот метод не заходит даже.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.14, 03:46
Matvik
Видимо, таким через поведение невозможно перекрыть родительский метод модели

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.14, 07:36
SiZE
Да, я погорячился с оверрайдом в поведении. Заюзай трейты =)

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.16, 01:24
Matvik
Да ну не, плохо так. Это ж тогда отдельно от поведения еще трейт придется присобачивать в модель каждый раз, а хотелось бы, чтоб все в одном поведении.

Собственно. не понимаю, почему нельзя через attach(), кто-нибуть может внятно обьяснить? Ведь видно же через дебаггер - у овнера появляется валидатор, а потом пропадает сразу, как так?

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.16, 07:49
kukuruku
смотрел мою ссылку?

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.16, 09:22
SiZE
Matvik писал(а): 2018.04.16, 01:24 Собственно. не понимаю, почему нельзя через attach(), кто-нибуть может внятно обьяснить?
можно если проинициализируешь поведение.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.17, 04:20
Matvik
kukuruku писал(а): 2018.04.16, 07:49 смотрел мою ссылку?
Смотрел, не нашел там решения.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.17, 04:21
Matvik
SiZE писал(а): 2018.04.16, 09:22
Matvik писал(а): 2018.04.16, 01:24 Собственно. не понимаю, почему нельзя через attach(), кто-нибуть может внятно обьяснить?
можно если проинициализируешь поведение.
Можно ссылку? Не понимаю, что значит, "проинициализировать" в данном контексте

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.17, 09:32
kukuruku
специально проверил у себя
создал поведение

Код: Выделить всё

class B extends Behavior
{
    public function attach($owner)
    {
        parent::attach($owner); // TODO: Change the autogenerated stub

        $owner->validators[] = Validator::createValidator('required', $owner, ['name', 'website_email', 'customer_email']);
    }
}
добавил в класс модели, и перечисленные поля начали ругаться что не заполненные
версия 2.0.15

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.17, 15:12
Matvik
kukuruku писал(а): 2018.04.17, 09:32 специально проверил у себя
создал поведение

Код: Выделить всё

class B extends Behavior
{
    public function attach($owner)
    {
        parent::attach($owner); // TODO: Change the autogenerated stub

        $owner->validators[] = Validator::createValidator('required', $owner, ['name', 'website_email', 'customer_email']);
    }
}
добавил в класс модели, и перечисленные поля начали ругаться что не заполненные
версия 2.0.15
Хм. Интересно. Нужно будет на другой модели проверить.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.17, 15:59
SiZE
Matvik писал(а): 2018.04.17, 04:21 Можно ссылку? Не понимаю, что значит, "проинициализировать" в данном контексте
Метод attach() у поведений вызывается в методе yii\base\Component::ensureBehaviors(). Можешь поиском пройтись по Component и посмотреть где ensureBehaviors() вызывается.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.18, 22:35
Matvik
SiZE писал(а): 2018.04.17, 15:59
Matvik писал(а): 2018.04.17, 04:21 Можно ссылку? Не понимаю, что значит, "проинициализировать" в данном контексте
Метод attach() у поведений вызывается в методе yii\base\Component::ensureBehaviors(). Можешь поиском пройтись по Component и посмотреть где ensureBehaviors() вызывается.
Ок, ну понятно, а в конкретном случае, когда новая модель создается, он же вызывается сразу во время создания. И непонятно, почему новосозданные валидаторы удаляются сразу после этого. Я сейчас порешаю другим методом, если это баг конкретного применения, то фиг с ним.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.19, 09:51
SiZE
Matvik писал(а): 2018.04.18, 22:35 Ок, ну понятно, а в конкретном случае, когда новая модель создается, он же вызывается сразу во время создания
Само по себе конечно ничего не должно удаляться

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.19, 10:07
ElisDN
SiZE писал(а): 2018.04.19, 09:51 Когда создается новая модель поведения автоматически не атачатся (не смотря на то что сказано об этом в мане). attach() вызывается только при инициализации поведений в следствии обращения к несуществующему методу или свойству модели.
В методе BaseActiveRecord::init() при создании вызывается trigger(EVENT_INIT), который запускает ensureBehaviors.

Re: Не добавляется правило валидации в модель через поведение

Добавлено: 2018.04.19, 11:00
SiZE
ElisDN писал(а): 2018.04.19, 10:07 В методе BaseActiveRecord::init() при создании вызывается trigger(EVENT_INIT), который запускает ensureBehaviors.
Действительно, спасибо за поправку. Я по коду смотрел, не учел этот момент.