Переменные класса в PHP: от объявления до продвинутых техник
В PHP переменные, объявленные внутри класса, называются свойствами класса. Они определяют состояние объектов. Существует несколько способов объявления таких переменных, различающихся по модификаторам доступа, типизации и принадлежности (экземпляру или самому классу).
Основные варианты объявления переменных класса
Как объявить типизированное свойство с модификатором доступа?
Начиная с PHP 7.4 рекомендуется указывать тип свойства (string, int, float, bool, array, объект и т.д.) и модификатор доступа (public, protected, private). Это обеспечивает строгую проверку типов и инкапсуляцию.
class User {
public string $name;
private int $age;
protected float $score;
}
Php environment variable (переменные окружения в php)
Пояснение: свойство $name доступно из любого места, $age только внутри класса User, $score внутри User и его наследников. При присвоении значения другого типа возникнет TypeError.
Проблема: попытка присвоить число с плавающей точкой свойству int приводит к ошибке. Решение: привести значение к нужному типу или использовать declare(strict_types=1) для строгой проверки.
Цель: создание предсказуемого и безопасного кода, предотвращение случайного присвоения неверных данных.
Как объявить статическое свойство, общее для всех экземпляров?
Ключевое слово static делает свойство принадлежащим классу, а не объекту. Значение такого свойства одинаково для всех экземпляров.
class Counter {
public static int $count = 0;
public function __construct() {
self::$count++;
}
}
Php class variable (переменные класса в php)
$c1 = new Counter(); $c2 = new Counter(); echo Counter::$count; // 2
Php get variable (получение переменной в php)
Пояснение: статическое свойство $count увеличивается при создании каждого объекта. Обращение через self::$count внутри класса или ИмяКласса::$count снаружи.
Проблема: забыв self:: внутри класса, можно случайно обратиться к нестатическому свойству. Решение: всегда использовать self:: для статических свойств.
Цель: реализация счетчиков, общих настроек, пулов соединений.
Как создать неизменяемое свойство (readonly) после инициализации?
В PHP 8.1 появился модификатор readonly. Такое свойство можно установить только один раз, обычно в конструкторе.
class Configuration {
public readonly string $apiKey;
public function __construct(string $apiKey) {
$this->apiKey = $apiKey;
}
}
Isset php (функция isset() в php)
$config = new Configuration('123abc');
echo $config->apiKey; // 123abc
// $config->apiKey = 'new'; // Fatal error: Cannot modify readonly property
Php цифры (работа с цифрами в php)
Пояснение: после присвоения в конструкторе свойство нельзя изменить. Это полезно для значений, которые должны оставаться постоянными после создания объекта.
Проблема: попытка изменить readonly свойство вызывает фатальную ошибку. Решение: не пытаться изменить; для изменяемых данных использовать обычные свойства.
Цель: гарантия неизменности заданных параметров, например ключей API, путей к файлам.
Как объявить константу класса (неизменяемую переменную, принадлежащую классу)?
Константы объявляются с помощью const и не содержат знака доллара. Они всегда static и public.
class MathConstants {
public const float PI = 3.14159;
protected const int DAYS_IN_WEEK = 7; // доступ только в этом классе и наследниках
}
Php get type (получение типа переменной в php)
echo MathConstants::PI; // 3.14159 // echo MathConstants::DAYS_IN_WEEK; // Error, protected
Пояснение: значение константы не может быть изменено во время выполнения. Модификатор доступа (public/protected/private) влияет на область видимости.
Проблема: попытка изменить константу через объект (например, $obj->PI = 3) создаст новое динамическое свойство, не затрагивая константу. Решение: не путать константы со свойствами, использовать :: для доступа.
Цель: определение фиксированных значений, таких как математические константы, статусы, максимальные лимиты.
Как объявить динамическое свойство (без предварительного определения)?
До PHP 8.2 можно было создавать свойства на ходу, присваивая значение необъявленному свойству. Начиная с PHP 8.2 это вызывает уведомление, а в будущем может быть запрещено.
class DynamicExample {}
$obj = new DynamicExample();
$obj->newProp = 42;
echo $obj->newProp; // 42
Пояснение: свойство newProp не было объявлено в классе, но оно создано. Это не рекомендуется из-за отсутствия контроля типов и сложностей отслеживания.
Проблема: в PHP 8.2+ возникает deprecated notice. Решение: явно объявлять все свойства в классе, особенно при работе в современных версиях PHP.
Цель: быстрая разработка прототипов, но не для продакшн-кода.
Расширенные примеры с пояснениями и результатами
Пример 1. Наследование и доступ к protected свойству
class ParentClass {
protected string $greeting = 'Hello';
}
class ChildClass extends ParentClass {
public function showGreeting(): void {
echo $this->greeting; // доступ разрешен
}
}
$child = new ChildClass();
$child->showGreeting(); // Hello
Hello
Пояснение: protected свойство $greeting доступно из дочернего класса, но не из внешнего кода. Попытка $child->greeting вне класса вызовет ошибку.
Пример 2. Статический счетчик объектов
class Product {
public static int $totalCreated = 0;
public string $name;
public function __construct(string $name) {
$this->name = $name;
self::$totalCreated++;
}
}
$p1 = new Product('Laptop');
$p2 = new Product('Mouse');
echo Product::$totalCreated; // 2
2
Пояснение: статическое свойство $totalCreated принадлежит классу, а не объекту, и увеличивается при каждом создании экземпляра.
Пример 3. Readonly свойство с типом и инициализацией в конструкторе
class UserProfile {
public readonly int $id;
public readonly string $email;
public function __construct(int $id, string $email) {
$this->id = $id;
$this->email = $email;
}
}
$profile = new UserProfile(42, 'user@example.com');
echo $profile->id; // 42
// $profile->id = 100; // Fatal error
42
Пояснение: readonly свойства нельзя изменить после завершения конструктора. Это делает объект неизменяемым после создания, что удобно для DTO (Data Transfer Object).
Пример 4. Строгая типизация и ошибка типа
declare(strict_types=1);
class StrictExample {
public int $value;
}
$obj = new StrictExample();
$obj->value = 3.14; // TypeError: Cannot assign float to property StrictExample::$value of type int
Fatal error: Uncaught TypeError: Cannot assign float to property StrictExample::$value of type int
Пояснение: при включенной строгой типизации нарушение типа приводит к фатальной ошибке. Без strict_types=1 произойдет неявное приведение к int (3.14 станет 3).