yii\base\Model переопределить createValidators()

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
NeverDie
Сообщения: 70
Зарегистрирован: 2012.05.13, 04:05
Откуда: Минск
Контактная информация:

yii\base\Model переопределить createValidators()

Сообщение NeverDie »

Здравствуйте! Поскажите, есть ли возможность переопределить ф-цию из системного класса yii\base\Model, не переписывая при этом yii\db\ActiveRecord который extends yii\base\Model.
Возможно есть вариант, который может подменить пути, что бы получилось примерно так:
path\to\MyModel extends yii\base\Model; yii\db\ActiveRecord extends path\to\MyModel?
Аватара пользователя
futbolim
Сообщения: 2051
Зарегистрирован: 2012.07.08, 19:28

Re: yii\base\Model переопределить createValidators()

Сообщение futbolim »

Ничего не понял. Попробуйте описать подробнее. При чём здесь пути и createValidators()?
Аватара пользователя
NeverDie
Сообщения: 70
Зарегистрирован: 2012.05.13, 04:05
Откуда: Минск
Контактная информация:

Re: yii\base\Model переопределить createValidators()

Сообщение NeverDie »

У нас есть системный класс yii\base\Model. От него можно наследваться, допустим в форму LoginForm extends yii\base\Model. Но так же от него наследуется системный класс yii\db\ActiveRecord.
Получается 2 цепочки наследования.

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

class LoginForm extends yii\base\Model {}
class Article extends yii\db\ActiveRecord extends yii\db\BaseActiveRecord extends yii\base\Model {}
Мне нужно переопределить в yii\base\Model метод createValidators() на свой, сохранив работу всего класса в целом.

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

class MyModel extends yii\base\Model {
    public function createValidators() { ... }
}
По сути получится такая цепочка:

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

class LoginForm extends path\to\MyModel extends yii\base\Model {} //в этом случае нет проблем, просто наследуемся от новой модели.
class Article extends yii\db\ActiveRecord extends yii\db\BaseActiveRecord extends path\to\MyModel extends  yii\base\Model {}
Во втором случае как раз и возникает вопрос. Как избежать копи паста кода BaseActiveRecord в новый файл но при этом используя переписанную ф-цию createValidators()
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: yii\base\Model переопределить createValidators()

Сообщение ElisDN »

Сначала расскажите, зачем хотите переопределить createValidators(). А файлы можно подменить через

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

Yii::$classMap['yii\base\Model'] = '@app/framework/Model.php';
Аватара пользователя
NeverDie
Сообщения: 70
Зарегистрирован: 2012.05.13, 04:05
Откуда: Минск
Контактная информация:

Re: yii\base\Model переопределить createValidators()

Сообщение NeverDie »

Решил добавить это решение по валидаторам.
https://github.com/yiisoft/yii2/issues/6534
Возможно есть какое-то решение через DI.

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

Yii::$classMap['yii\base\Model'] = '@app/framework/Model.php';
В таком случае теряется extends. Хочу избежать именно этого копипаста кода из системного класса.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: yii\base\Model переопределить createValidators()

Сообщение ElisDN »

В таком случае автоматически - никак. Наследование динамически не меняется. И этим сломаете валидации всех чужих моделей.

Лучше сделать явным написанием своего хелпера:

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

public function rules()
{
    return RulesHelper::build([
        ['slug', 'required'],

        'name' => [
            'trim',
            'required',
            'string' => ['max' => 255],
        ],

        ['imageFiles', 'safe'],
    ]);
}
который будет формировать массив:

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

class RulesHelper
{
    public function build(array $rules)
    {
        $items = [];
        foreach ($rules as $key, $rule) {
            if ($rule instanceof Validator) {
                $items[] = $rule;
            } elseif (is_string($key) && is_array($rule)) {
                foreach ($rule as $sub) {
                    if (is_array($sub)) {
                        $items[] = ArrayHelper::merge([$key], $sub);
                    } elseif ($sub instanceof Closure) {
                        $items[] = [$key, 'filter', 'filter' => $sub];
                    } else {
                        $items[] =[$key, $sub];
                    }
                }
            } elseif (is_array($rule) && isset($rule[0], $rule[1])) {                
                $items[] = $rule;
            } else {
                throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
            }
        }
        return $items;
    }
}
Последний раз редактировалось ElisDN 2017.09.01, 12:27, всего редактировалось 1 раз.
Аватара пользователя
NeverDie
Сообщения: 70
Зарегистрирован: 2012.05.13, 04:05
Откуда: Минск
Контактная информация:

Re: yii\base\Model переопределить createValidators()

Сообщение NeverDie »

Спасибо!
webwizardry
Сообщения: 1
Зарегистрирован: 2018.10.13, 10:32

Re: yii\base\Model переопределить createValidators()

Сообщение webwizardry »

NeverDie писал(а): 2017.08.31, 13:36 Здравствуйте! Поскажите, есть ли возможность переопределить ф-цию из системного класса yii\base\Model, не переписывая при этом yii\db\ActiveRecord который extends yii\base\Model.
Возможно есть вариант, который может подменить пути, что бы получилось примерно так:
path\to\MyModel extends yii\base\Model; yii\db\ActiveRecord extends path\to\MyModel?
На самом деле есть, если использовать трейт

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

	trait MyTrait()
	{
	      public function createValidators()
	      {
	           ... ваш код
	      }
	      
	}
	
	class MyActiveRecord extends yii\db\ActiveRecord 
	{
	      use MyTrait;
	}
	
	class MyModel extends yii\base\Model
	{
	      use MyTrait;
	}
Ну а свои модели уже наследуем от MyModel и MyActiveRecord соответственно.
Ответить