您可以通过以下方式访问包含连字符的属性名称(例如,因为您将 XML 文件转换为对象)
<?php
$ref = new StdClass();
$ref->{'ref-type'} = 'Journal Article';
var_dump($ref);
?>
类成员变量称为属性。它们可以使用其他术语(例如字段)来引用,但出于本参考的目的,将使用属性。它们通过使用至少一个修饰符(例如可见性、静态关键字,或者从 PHP 8.1.0 开始的只读)来定义,可选地(除了readonly
属性外),从 PHP 7.4 开始,后跟类型声明,然后是正常的变量声明。此声明可能包含初始化,但此初始化必须是常量值。
注意:
声明类属性的一种已过时的方式是使用
var
关键字而不是修饰符。
注意:未声明可见性修饰符的属性将声明为
public
。
在类方法中,非静态属性可以通过使用->
(对象运算符)来访问:$this->property(其中property
是属性的名称)。静态属性通过使用::
(双冒号)来访问:self::$property。有关静态属性和非静态属性之间区别的更多信息,请参见静态关键字。
伪变量$this在从对象上下文中调用该方法时,在任何类方法内部都可用。$this是调用对象的的值。
示例 #1 属性声明
<?php
class SimpleClass
{
public $var1 = 'hello ' . 'world';
public $var2 = <<<EOD
hello world
EOD;
public $var3 = 1+2;
// 无效的属性声明:
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
// 有效的属性声明:
public $var6 = myConstant;
public $var7 = [true, false];
public $var8 = <<<'EOD'
hello world
EOD;
// 无可见性修饰符:
static $var9;
readonly int $var10;
}
?>
注意:
有各种函数可以处理类和对象。请参阅类/对象函数参考。
从 PHP 7.4.0 开始,属性定义可以包含类型声明,除了callable。
示例 #2 类型化属性的示例
<?php
class User
{
public int $id;
public ?string $name;
public function __construct(int $id, ?string $name)
{
$this->id = $id;
$this->name = $name;
}
}
$user = new User(1234, null);
var_dump($user->id);
var_dump($user->name);
?>
以上示例将输出
int(1234) NULL
类型化属性必须在访问之前初始化,否则会抛出Error。
示例 #3 访问属性
<?php
类 Shape
{
public int $numberOfSides;
public string $name;
public function setNumberOfSides(int $numberOfSides): void
{
$this->numberOfSides = $numberOfSides;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getNumberOfSides(): int
{
return $this->numberOfSides;
}
public function getName(): string
{
return $this->name;
}
}
$triangle = new Shape();
$triangle->setName("triangle");
$triangle->setNumberofSides(3);
var_dump($triangle->getName());
var_dump($triangle->getNumberOfSides());
$circle = new Shape();
$circle->setName("circle");
var_dump($circle->getName());
var_dump($circle->getNumberOfSides());
?>
以上示例将输出
string(8) "triangle" int(3) string(6) "circle" Fatal error: Uncaught Error: Typed property Shape::$numberOfSides must not be accessed before initialization
从 PHP 8.1.0 开始,可以使用 readonly
修饰符声明属性,这可以防止在初始化后修改属性。在 PHP 8.4.0 之前,readonly
属性隐式设置为私有设置,并且只能从同一类中写入。从 PHP 8.4.0 开始,readonly
属性隐式为 protected(set)
,因此可以在子类中设置。如果需要,可以显式覆盖它。
示例 #4 只读属性示例
<?php
类 Test {
public readonly string $prop;
public function __construct(string $prop) {
// 合法的初始化。
$this->prop = $prop;
}
}
$test = new Test("foobar");
// 合法的读取。
var_dump($test->prop); // string(6) "foobar"
// 非法的重新赋值。分配的值相同与否都没有关系。
$test->prop = "foobar";
// 错误:无法修改只读属性 Test::$prop
?>
注意:
注意:
不支持只读静态属性。
只读属性只能初始化一次,并且只能从声明它的作用域初始化。对属性的任何其他赋值或修改都将导致 Error 异常。
示例 #5 只读属性的非法初始化
<?php
类 Test1 {
public readonly string $prop;
}
$test1 = new Test1;
// 非法初始化,不在私有作用域内。
$test1->prop = "foobar";
// 错误:无法从全局作用域初始化只读属性 Test1::$prop
?>
注意:
不允许在只读属性上指定显式默认值,因为具有默认值的只读属性本质上与常量相同,因此没有特别的有用之处。
<?php
类 Test {
// 严重错误:只读属性 Test::$prop 不能有默认值
public readonly int $prop = 42;
}
?>
注意:
一旦初始化,就无法 unset() 只读属性。但是,可以在初始化之前,从声明属性的作用域取消设置只读属性。
修改不一定是简单的赋值,以下所有操作都将导致 Error 异常
<?php
类 Test {
public function __construct(
public readonly int $i = 0,
public readonly array $ary = [],
) {}
}
$test = new Test;
$test->i += 1;
$test->i++;
++$test->i;
$test->ary[] = 1;
$test->ary[0][] = 1;
$ref =& $test->i;
$test->i =& $ref;
byRef($test->i);
foreach ($test as &$prop);
?>
但是,只读属性并不排除内部可变性。存储在只读属性中的对象(或资源)仍然可以在内部修改。
<?php
类 Test {
public function __construct(public readonly object $obj) {}
}
$test = new Test(new stdClass);
// 合法的内部修改。
$test->obj->foo = 1;
// 非法的重新赋值。
$test->obj = new stdClass;
?>
从 PHP 8.3.0 开始,使用 __clone() 方法克隆对象时,可以重新初始化只读属性。
示例 #6 只读属性和克隆
<?php
类 Test1 {
public readonly string $prop;
public function __clone() {
$this->prop = null;
}
public function setProp(string $prop): void {
$this->prop = $prop;
}
}
$test1 = new Test1;
$test1->setProp('foobar');
$test2 = clone $test1;
var_dump($test2->prop); // NULL
?>
您可以通过以下方式访问包含连字符的属性名称(例如,因为您将 XML 文件转换为对象)
<?php
$ref = new StdClass();
$ref->{'ref-type'} = 'Journal Article';
var_dump($ref);
?>
$this 可以转换为数组。但是,在执行此操作时,它会根据属性分类在属性名称/新数组键前面添加某些数据。公共属性名称不会更改。受保护的属性以空格填充的 '*' 为前缀。私有属性以空格填充的类名为前缀...
<?php
class test
{
public $var1 = 1;
protected $var2 = 2;
private $var3 = 3;
static $var4 = 4;
public function toArray()
{
return (array) $this;
}
}
$t = new test;
print_r($t->toArray());
/* 输出:
Array
(
[var1] => 1
[ * var2] => 2
[ test var3] => 3
)
*/
?>
这是将任何对象转换为数组时的文档化行为(请参阅 </language.types.array.php#language.types.array.casting> PHP 手册页面)。在将对象转换为数组时,将显示所有属性(无论可见性如何)(某些内置对象除外)。
要获取所有属性名称都不更改的数组,请在类范围内任何方法中使用 'get_object_vars($this)' 函数检索所有属性(无论外部可见性如何)的数组,或在类范围之外使用 'get_object_vars($object)' 检索仅公共属性的数组(请参阅: </function.get-object-vars.php> PHP 手册页面)。
不要将 php 中的属性版本与其他语言(例如 C++)中的属性混淆。在 php 中,属性与属性相同,是简单的变量,没有功能。它们应该称为属性,而不是属性。
属性具有隐式访问器和修改器功能。我创建了一个抽象类,允许隐式属性功能。
<?php
抽象类 PropertyObject
{
public function __get($name)
{
if (method_exists($this, ($method = 'get_'.$name)))
{
return $this->$method();
}
else return;
}
public function __isset($name)
{
if (method_exists($this, ($method = 'isset_'.$name)))
{
return $this->$method();
}
else return;
}
public function __set($name, $value)
{
if (method_exists($this, ($method = 'set_'.$name)))
{
$this->$method($value);
}
}
public function __unset($name)
{
if (method_exists($this, ($method = 'unset_'.$name)))
{
$this->$method();
}
}
}
?>
扩展此类后,您可以创建访问器和修改器,当访问相应的属性时,这些访问器和修改器将使用 php 的魔术方法自动调用。