Properties
Оновлено: 12.05.2023
Змінні-члени класу називаються властивостями. На них можна посилатися, використовуючи інші терміни, наприклад, поля, але для цілей цього посібника буде використано термін властивості. Вони визначаються за допомогою принаймні одного модифікатора (наприклад, Visibility, Static Keyword або, починаючи з PHP 8.1.0, readonly), необов'язково (за винятком властивостей, доступних тільки для читання), починаючи з PHP 7.4, після чого слідує оголошення типу, а потім звичайне оголошення змінної. Це оголошення може містити ініціалізацію, але ця ініціалізація має бути константним значенням.
Зауважте:
Застарілим способом оголошення властивостей класу є використання ключового слова var замість модифікатора.
Примітка: Властивість, оголошена без модифікатора видимості, буде оголошена як загальнодоступна.
У методах класу до нестатичних властивостей можна звертатися за допомогою -> (оператор об'єкта): $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;
// invalid property declarations:
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
// valid property declarations:
public $var6 = myConstant;
public $var7 = [true, false];
public $var8 = <<<'EOD'
hello world
EOD;
// Without visibility modifier:
static $var9;
readonly int $var10;
}
?>
Зауважте:
Існують різні функції для роботи з класами та об'єктами. Див. довідник Функції класів/об'єктів.
Починаючи з версії PHP 7.4.0, визначення властивостей можуть включати оголошення типів, за винятком викликуваних.
Приклад #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);
?>
Типізовані властивості повинні бути ініціалізовані перед доступом, інакше буде згенеровано помилку.
Приклад #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());
?>
Починаючи з версії PHP 8.1.0, властивість можна оголошувати з модифікатором readonly, який запобігає зміні властивості після ініціалізації.
Приклад #4 Приклад властивостей тільки для читання
<?php
class Test {
public readonly string $prop;
public function __construct(string $prop) {
// Legal initialization.
$this->prop = $prop;
}
}
$test = new Test("foobar");
// Legal read.
var_dump($test->prop); // string(6) "foobar"
// Illegal reassignment. It does not matter that the assigned value is the same.
$test->prop = "foobar";
// Error: Cannot modify readonly property Test::$prop
?>
Зауважте:
Модифікатор readonly можна застосовувати лише до типізованих властивостей. Властивість, доступну тільки для читання без обмежень типу, можна створити за допомогою типу Mixed.
Зауважте:
Статичні властивості, доступні лише для читання, не підтримуються.
Властивість, доступну лише для читання, можна ініціалізувати лише один раз і лише з області видимості, де її було оголошено. Будь-яке інше присвоєння або модифікація властивості призведе до виникнення виключення Error.
Приклад #5 Неправомірна ініціалізація властивостей, доступних тільки для читання
<?php
class Test1 {
public readonly string $prop;
}
$test1 = new Test1;
// Illegal initialization outside of private scope.
$test1->prop = "foobar";
// Error: Cannot initialize readonly property Test1::$prop from global scope
?>
Зауважте:
Вказувати явне значення за замовчуванням для властивостей, доступних лише для читання, не дозволяється, оскільки властивість, доступна лише для читання, зі значенням за замовчуванням, по суті, є константою, а отже, не є особливо корисною.
<?php
class Test {
// Fatal error: Readonly property Test::$prop cannot have default value
public readonly int $prop = 42;
}
?>
Зауважте:
Властивості, доступні тільки для читання, не можуть бути скинуті функцією unset() після їх ініціалізації. Однак, можна скинути властивість 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);
?>
Втім, властивості, доступні лише для читання, не виключають внутрішньої мутабельності. Об'єкти (або ресурси), що зберігаються у властивостях, доступних лише для читання, все одно можуть бути змінені зсередини:
<?php
class Test {
public function __construct(public readonly object $obj) {}
}
$test = new Test(new stdClass);
// Legal interior mutation.
$test->obj->foo = 1;
// Illegal reassignment.
$test->obj = new stdClass;
?>
При спробі присвоїти неіснуючу властивість об'єкту, PHP автоматично створить відповідну властивість. Ця динамічно створена властивість буде доступна лише для цього екземпляра класу.
Динамічні властивості є застарілими, починаючи з версії PHP 8.2.0. Натомість рекомендується оголошувати властивість. Для роботи з довільними іменами властивостей у класі слід реалізувати магічні методи __get() і __set(). У крайньому випадку клас можна позначити атрибутом #[\AllowDynamicProperties].