Переменные, которые относятся к членам класса, называются свойствами.
Переменные-члены класса также называют другими терминами, например, полями,
но в этой документации,
такие переменные будут называться — свойствами.
Свойства класса определяют хотя бы одним модификатором (которые описывают разделы
«Область видимости», «Ключевое слово static»
или начиная с PHP 8.1.0 readonly),
за которым начиная с PHP 7.4 следует необязательное (за исключением readonly
-свойств)
объявление типа, за которым следует стандартное объявление переменной.
При объявлении свойства класса переменную разрешается инициализировать,
но начальное значение переменной потребуется указать как
постоянное значение.
Замечание:
Устаревший способ объявления свойств класса — ключевое слово
var
вместо модификатора.
Замечание: Свойство, которое объявили без модификатора раздела «Область видимости», PHP объявит как
public
.
Внутри методов класса доступ к нестатическим свойствам получают
через оператор объекта ->
—
$this->property, где property
— имя свойства.
Доступ к статическим свойствам получают через оператор двойного двоеточия ::
—
self::$property. Дополнительную информацию об отличиях
статических свойств от нестатических даёт раздел
«Ключевое слово static».
Псевдопеременная $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
При обращении к типизированному свойству, для которого не определили начальное значение, PHP выбросит исключение Error.
Пример #3 Обращение к свойствам
<?php
class 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 Примеры readonly-свойств
<?php
class 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";
// Error: Cannot modify readonly property Test::$prop
?>
Замечание:
Модификатор readonly разрешается применять только к типизированным свойствам. Тип свойства объявляют как Mixed, когда требуется создать readonly-свойство без ограничений типа.
Замечание:
Статические readonly-свойства не поддерживаются.
Readonly-свойство разрешается инициализировать только один раз и только из области видимости, в которой свойство объявили. Другое присваивание или изменение свойства приведёт к исключению Error.
Пример #5 Неправильная инициализация readonly-свойств
<?php
class Test1
{
public readonly string $prop;
}
$test1 = new Test1();
// Неправильная инициализация за пределами закрытой области
$test1->prop = "foobar";
// Error: Cannot initialize readonly property Test1::$prop from global scope
?>
Замечание:
Нельзя явным образом указывать значение по умолчанию для readonly-свойств, потому что readonly-свойство со значением по умолчанию по существу совпадает с константой, и поэтому бесполезно.
<?php
class Test
{
// Error: Readonly property Test::$prop cannot have default value
public readonly int $prop = 42;
}
?>
Замечание:
Конструкцией unset() нельзя уничтожить readonly-свойство после инициализации. Однако можно уничтожить readonly-свойство до инициализации из области видимости, в которой свойство объявили.
Изменения не обязаны быть стандартными присваиваниями, инструкции ниже также приведут к исключению Error:
<?php
class 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);
?>
При этом readonly-свойства не исключают внутреннюю изменчивость. Объекты и ресурсы, которые хранятся в readonly-свойствах, по-прежнему получится изменить внутри:
<?php
class 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 Клонирование readonly-свойств
<?php
class 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
?>
При попытке присвоить несуществующее свойство объекту (object), PHP автоматически создаст такое свойство. Это динамически созданное свойство будет доступно только для этого экземпляра класса.
С PHP 8.2.0 динамические свойства устарели.
Вместо динамического присваивания свойства классу рекомендуют объявлять свойство.
Для обработки произвольных имён свойств
класс должен реализовать магические методы
__get() и __set().
В крайнем случае класс помечают атрибутом #[\AllowDynamicProperties]
.