Когда использовать self, а когда $this в PHP? Разбираемся с областью видимости
Ключевое различие: статический контекст vs контекст объекта
Главное правило, которое нужно запомнить: $this работает с экземпляром класса (объектом), а self — с самим классом (статический контекст). Отсюда вытекают все остальные различия.
Когда использовать $this?
$this — это псевдопеременная, которая ссылается на текущий объект. Она доступна только внутри нестатических методов. С её помощью вы обращаетесь к:
- Нестатическим свойствам (
$this->color) - Нестатическим методам (
$this->drive())
Важно: $this всегда ссылается на тот объект, из которого был вызван метод. Это особенно важно при наследовании.
Когда использовать self?
self — это ссылка на текущий класс в том месте, где он написан (лексическая область видимости). Используется для доступа к:
- Константам класса (
self::WHEELS) - Статическим свойствам (
self::$count) - Статическим методам (
self::create())
Практический пример с наследованием
Вот тут и проявляется хитрость. Смотрите, что произойдёт, если мы создадим дочерний класс:
class Car {
const WHEELS = 4;
public static $count = 0;
public function showSelf() {
echo self::WHEELS; // Всегда выведет 4 (из класса Car)
echo self::$count; // Всегда выведет значение из класса Car
}
public function showStatic() {
echo static::WHEELS; // Выведет то, что определил поздний класс
echo static::$count; // Позднее статическое связывание
}
}
class Truck extends Car {
const WHEELS = 6;
public static $count = 10;
}
$truck = new Truck();
$truck->showSelf(); // Выведет: 4 и 0 (self замкнут на Car)
$truck->showStatic(); // Выведет: 6 и 10 (static использует позднее связывание)
Что нельзя делать?
$this::WHEELS— работать будет, но это плохая практика.$thisтут используется как ссылка на класс объекта, но логически это сбивает с толку.self::$color— ошибка! Нельзя использоватьselfдля доступа к нестатическому свойству.$this->WHEELS— тоже ошибка. Константы не являются свойствами объекта.
Простое правило для запоминания
Задайте себе два вопроса:
- «Это значение может быть разным для разных объектов?» → используйте
$this(свойство объекта). - «Это значение одинаково для всех объектов или вообще не привязано к объекту?» → используйте
self(константа, статическое свойство/метод).
И помните про static:: — если вы пишете код, который должен работать с наследованием и подменой значений в дочерних классах, используйте позднее статическое связывание вместо self.
Дополнение про статические методы и self
Стоит добавить важный нюанс: self часто используется внутри статических методов, где $this вообще недоступен. Например:
class Logger {
private static $log = [];
public static function add($msg) {
self::$log[] = $msg; // Нельзя написать $this->log
}
public static function show() {
foreach (self::$log as $entry) {
echo $entry . "\n";
}
}
}
Logger::add('Ошибка');
Logger::show();
Ещё один частый сценарий — фабричные методы или синглтон:
class Database {
private static $instance = null;
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self(); // self() создаёт экземпляр текущего класса
}
return self::$instance;
}
}
Обратите внимание на new self() — это создание объекта того класса, где написан код. Если вам нужно, чтобы при наследовании создавался объект дочернего класса, используйте new static().
Итог: $this — для работы с данными конкретного объекта, self — для работы с классом как с сущностью (константы, статика). Не путайте их, и ваш код будет предсказуемым.