asArray и виртуальные атрибуты

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

asArray и виртуальные атрибуты

Сообщение de1phi »

добрый день,

подскажите, пожалуйста, реализацию переопределенной функции asArray, чтобы подтягивать виртуальные атрибуты модели.

p.s. делается для оптимизации, т.к. ООП ресурсы сильно кушает
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение samdark »

Покажите, как вы хотите этот метод использовать. И расскажите, что вы понимаете под виртуальными атрибутами.
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

к примеру,

в модели есть атрибут fullName, который получается конкатенацией фамилией и именем на нужном языке. Производим выборку нескольких моделей с зависимостью:

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

$models = Employeer::find()
            ->crew()
            ->with('rank')
            ->orderBy(['updated_at' => SORT_DESC])
            ->limit(Yii::$app->config->get('elementsInPanel'))
            ->asArray()
            ->all(); 
и чтобы можно было во view получить доступ к к атрибуту fullName

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

$model['fullName'] 
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: asArray и виртуальные атрибуты

Сообщение zelenin »

я так понмиаю, вам нужен метод fields(), который как раз к результату asArray подмешивает любые атрибуты.
https://github.com/yiisoft/yii2/blob/36 ... ng-fields-
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

zelenin писал(а):я так понмиаю, вам нужен метод fields(), который как раз к результату asArray подмешивает любые атрибуты.
https://github.com/yiisoft/yii2/blob/36 ... ng-fields-
не совсем то, получается надо делать запрос без asArray. И потом результат перебирать в foreach и преобразовывать модель в массив с помощью toArray.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение samdark »

zelenin, asArray не инстранциирует модель.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: asArray и виртуальные атрибуты

Сообщение zelenin »

Sam Dark писал(а):zelenin, asArray не инстранциирует модель.
ну ему и не нужен инстанс, ему нужен массив с полем.
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

Sam Dark писал(а):zelenin, asArray не инстранциирует модель.
не знаю, может как вариант. Написать что-то типа Хелпера под модель. И вызывать его методы для обработки как в геттере модели, так и при обработке данных массива
zelenin писал(а):ну ему и не нужен инстанс, ему нужен массив с полем.
так не получится вызвать метод без инстанса
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: asArray и виртуальные атрибуты

Сообщение zelenin »

de1phi писал(а):
Sam Dark писал(а):zelenin, asArray не инстранциирует модель.
не знаю, может как вариант. Написать что-то типа Хелпера под модель. И вызывать его методы для обработки как в геттере модели, так и при обработке данных массива
zelenin писал(а):ну ему и не нужен инстанс, ему нужен массив с полем.
так не получится вызвать метод без инстанса
по ссылке пример

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

public function fields()
{
    return [
        // field name is the same as the attribute name
        'id',
        // field name is "email", the corresponding attribute name is "email_address"
        'email' => 'email_address',
        // field name is "name", its value is defined by a PHP callback
        'name' => function ($model) {
            return $model->first_name . ' ' . $model->last_name;
        },
    ];
} 
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение samdark »

fields работает если у нас есть инстанс и мы делаем toArray. Это не asArray. Весь смысл затеи автора топика — не инстанциировать объект класса для сохранения ресурсов.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: asArray и виртуальные атрибуты

Сообщение zelenin »

Sam Dark писал(а):fields работает если у нас есть инстанс и мы делаем toArray. Это не asArray. Весь смысл затеи автора топика — не инстанциировать объект класса для сохранения ресурсов.
ага, понятно. спутал toArray и asArray.
Аватара пользователя
Insolita
Сообщения: 788
Зарегистрирован: 2011.06.06, 01:39
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение Insolita »

ну надо полагать у тебя аттрибут конкатенацию в afterFind делает
а соласно коду https://github.com/yiisoft/yii2/blob/36 ... y.php#L225 при asArray afterFind не выполняется
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

Insolita писал(а):ну надо полагать у тебя аттрибут конкатенацию в afterFind делает
а соласно коду https://github.com/yiisoft/yii2/blob/36 ... y.php#L225 при asArray afterFind не выполняется
зачем? обычным геттером
Аватара пользователя
Insolita
Сообщения: 788
Зарегистрирован: 2011.06.06, 01:39
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение Insolita »

если именно нужно имя + фамилию то как-то так

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

 $query->select(['{{%table}}.*', new Expression('CONCAT_WS({{%table}}.name, {{%table}}.surname, " ") as fullName')]) 
а про геттеры и сеттеры модели при asArray тем более ничего не знает https://github.com/yiisoft/yii2/blob/36 ... t.php#L111
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

Insolita писал(а):если именно нужно имя + фамилию то как-то так

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

 $query->select(['{{%table}}.*', new Expression('CONCAT_WS({{%table}}.name, {{%table}}.surname, " ") as fullName')]) 
а про геттеры и сеттеры модели при asArray тем более ничего не знает https://github.com/yiisoft/yii2/blob/36 ... t.php#L111
это все хорошо :) я обрисовал самый простой пример. Но в модели же полно других геттеров :)

поэтому все-таки склоняюсь к хелперу...

p.s. хотя тоже не вариант, в модели же есть константы и т.д. =( похоже придется дублировать код
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение samdark »

Не статические методы модели без экземпляра класса модели не вызвать. Так что да, либо в статику выносить, либо дублировать.
Аватара пользователя
Insolita
Сообщения: 788
Зарегистрирован: 2011.06.06, 01:39
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение Insolita »

ну так как при asArray инстансов модели вообще не создается - соответственно нет возможности обратится к модели и узнать аттрибуты поэтому хелпер тут не поможет ... из того что навскидку - в модели создать метод типа virtfields() по аналогии с fields

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

 public static function virtFields(){
        return [
            'fullName'=>function($model){return $model['name'].' '.$model['surname'];}
        ];
    }
 
и расширить ActiveQuery с переопределением метода populate

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

public function populate($rows){
        $models=parent::populate($rows);

        if(!$this->asArray){
            return $models;
        }else{
            $class = $this->modelClass;
            $dopfields=method_exists($class, 'virtFields')?$class::virtFields():[];
            foreach ($models as &$model) {
              if(!empty($dopfields)){
                  foreach($dopfields as $attr=>$val){
                      if(is_string($val)){
                          $model=array_merge($model,[$attr=>$val]);
                      }elseif(is_callable($val)){
                          $model=array_merge($model,[$attr=>call_user_func($val, $model)]);
                      }
                  }
              }
            }
            return $models;
        }
    }
 
ну и в модели соответственно использовать нужный ActiveQuery

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

 /**
     * @inheritdoc
     * @return ActiveQuery
     */
    public static function find()
    {
        return new MyActiveQuery(get_called_class());
    }
в общем у меня отработало, правда еще надо тестировать чтоб другие никакие запросы не использовало
Последний раз редактировалось Insolita 2015.01.27, 19:45, всего редактировалось 3 раза.
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

Insolita спасибо, но по использованию ресурсов почти тоже самое, что и toArray =(
Аватара пользователя
Insolita
Сообщения: 788
Зарегистрирован: 2011.06.06, 01:39
Контактная информация:

Re: asArray и виртуальные атрибуты

Сообщение Insolita »

ну чтоб избавиться от еще одного перебора - это уже в ActiveQueryTrate надо лезть... а что большой объем данных в выборках? может не это место ресурсы кушает? (в любом случае это явно менее жирно чем AR - модели) - ресурсы в плане памяти? в production режиме тоже?
de1phi
Сообщения: 145
Зарегистрирован: 2013.12.23, 20:02

Re: asArray и виртуальные атрибуты

Сообщение de1phi »

больше 8000 записей надо вывести :)
Ответить