Имена виртуальных атрибутов Yii2 - очень странная проблема в верхнем / нижнем регистре? - PullRequest
0 голосов
/ 02 ноября 2018

Я использую Yii2, и у меня есть виртуальный атрибут notes2 (который используется функциями графического интерфейса вместо примечаний к атрибуту базы данных):

class Order extends \yii\db\ActiveRecord
{    
    public function getnotes2() {
        return iconv('UTF-16LE', 'UTF-8', $this->notes);
    }

    public function setnotes2($value) {
        $this->notes = iconv('UTF-8', 'UTF-16LE', $value);
    }
}

В этом случае оба следующих кода $order->notes2 и $order->Notes2 вызывают установщик и возвращают правильное значение.

Но я должен использовать функцию $order->getAttributes(), и реализация по умолчанию не включает виртуальные атрибуты. Поэтому я попытался переопределить эту функцию с помощью:

public function attributes() {
    $attributes = parent::attributes();
    $attributes['notes2'] = 'notes2';
    return $attributes;
} 

А теперь json_encode($order->getAttributes()) включает пустое поле notes2, но $order->notes2 (очевидно - это приводит к тому, что поле notes2 становится пустым) не имеет значения, но $order->Notes2 имеет значение!

Почему происходит такой триггер регистра первого символа? Как правильно объявить виртуальное поле, которое доступно и в getAttributes()?

Но следующий код (вместо переопределения attributes())

public function getAttributes($names = null, $except = []) {
    return array_merge(['notes2'], parent::getAttributes($names, $except));
}

ведет себя так, как будто ничего не было переопределено - и $order->notes2, и $order->Notes2 рассчитываются, и в json_encode($order->getAttributes())

нет notes2 (или Notes2)

1 Ответ

0 голосов
/ 02 ноября 2018

Эта проблема чувствительности к регистру связана с ограничением / функцией PHP - имена методов нечувствительны к регистру, поэтому виртуальные атрибуты, предоставляемые методами, также нечувствительны к регистру - нет разницы, если вы определяете / называете его как getnotes2() или getNotes2(), таким образом, нет никакого различия между $order->notes2 и $order->Notes2.

Это работает иначе для обычных атрибутов (и свойств), которые не используют методы, и на них не влияет это ограничение нечувствительности к регистру. Вы не объяснили, чего хотите достичь, но обычные атрибуты (определяемые attributes()) и виртуальные атрибуты (предоставляемые геттерами и сеттерами) - это две разные вещи, и вы не можете смешивать их - если вы определяете атрибут в attributes() он будет сохранен во внутреннем массиве, а метод получения / установки будет игнорироваться (поскольку обычные атрибуты имеют приоритет над виртуальными атрибутами).

В вашем случае вы определили один и тот же атрибут дважды: один раз как обычный атрибут (в attributes()), а второй как виртуальный атрибут (с getter и setter). Если вы используете этот атрибут с правильным регистром ($order->notes2), будет использоваться обычный атрибут. Если регистр неверен ($order->Notes2), обычный атрибут не будет использоваться (так как он чувствителен к регистру и отсутствует атрибут Notes2), а виртуальный атрибут будет использоваться (так как он будет игнорировать регистр) в качестве запасного варианта.


Если единственное, что вы хотите сделать, это включить notes2 в getAttributes(), попробуйте переопределить getAttributes() таким образом и вообще не трогать attributes():

public function getAttributes($names = null, $except = []) {
    return array_merge(
        ['notes2' => $this->getNotes2()], 
        parent::getAttributes($names, $except)
    );
}

Не то, чтобы при этом игнорировались аргументы $names и $except и всегда возвращался атрибут notes2.

...