我正在使用 Yii2 并且我有虚拟属性
notes2
(由 GUI 功能而不是数据库属性注释使用):
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
都会调用 setter 并返回正确的值。
但是我必须使用
$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
均已计算,并且 notes2
内没有
Notes2
(或
json_encode($order->getAttributes())
)
这个大小写敏感问题与 PHP 限制/功能有关 - 方法名称不区分大小写,因此方法提供的虚拟属性也不区分大小写 - 如果您定义/调用它为
getnotes2()
或 getNotes2()
没有区别,所以有无法区分 $order->notes2
和 $order->Notes2
。
这对于不使用方法的常规属性(和属性)的工作方式有所不同,并且它们不受此不区分大小写的限制的影响。您没有解释您想要实现的目标,但是常规属性(由
attributes()
定义)和虚拟属性(由 getter 和 setter 提供)是两个独立的东西,您不能将它们混淆 - 如果您在 中定义属性attributes()
它将存储在内部数组中,并且 getter/setter 将被忽略(因为常规属性优先于虚拟属性)。
在您的例子中,您定义了相同的属性两次:一次作为常规属性(在
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
属性。