Классы и объекты
Чему вы научитесь:
- описывать класс со свойствами и методами и создавать по нему объекты через
new; - задавать начальные значения в конструкторе и закрывать свойства словом
private; - объяснять, почему
$b = $aне копирует объект, и копировать его черезclone; - пользоваться статическими свойствами, константами класса,
readonlyи__toString.

Представьте чертёж дома. На нём размечены комнаты, окна и двери, но жить в чертеже нельзя. По одному чертежу строят сколько угодно домов: устроены они одинаково, а мебель и жильцы в каждом свои.
В PHP чертёж называется классом, а построенный по нему дом — объектом. Эта картинка пройдёт через всю тему: чертёж, дома по нему и адреса этих домов.
Зачем нужен чертёж, если данные можно хранить в массиве? Например, товар в массиве: ['title' => 'tea', 'price' => 5]. Но у массива есть слабые места:
- массив не знает, какие ключи у него должны быть, и опечатку в ключе PHP заметит только при чтении;
- функции для работы с товаром живут отдельно от данных и примут любой массив.
Класс собирает в одном месте, какие данные есть у объекта и что с ним можно делать.
Класс и объект
Давайте опишем счётчик посещений страницы:
<?php
class Counter
{
public int $value = 0;
}
$visits = new Counter();
$visits->value = $visits->value + 1;
echo $visits->value, "\n"; // 1Разберём программу по шагам:
class Counterобъявляет класс с именемCounter. Его тело стоит в фигурных скобках, и открывающая скобка занимает отдельную строку.public int $value = 0;объявляет свойство$valueтипаintс начальным значением0. Словоpublicзначит, что свойство доступно из любого места программы.new Counter()строит объект по классу, и он попадает в переменную$visits.- Стрелка
->открывает доступ к свойству этого объекта:$visits->valueчитается как «valueобъекта из$visits». - Программа увеличивает счётчик на единицу и печатает
1.
Класс — описание, по которому строят объекты: какие у них данные и что с ними можно делать. Объект — значение, построенное по классу через new, его ещё называют экземпляром класса. Свойство — переменная внутри объекта; объявляют её в классе.
Имена классов пишут с заглавной буквы, и каждое следующее слово в имени тоже: Counter, ShoppingCart.
У свойств три правила:
- тип пишут перед именем, как у параметра функции:
int,string,array,?string; - начальное значение получает каждый новый объект;
- тип проверяется при каждой записи, как у параметра функции в режиме приведения:
'5'станет5, а$visits->value = 'many'закончится ошибкойTypeError.
Один new — один объект
Каждый new строит по тому же чертежу новый дом. Свойства у каждого объекта свои:
$home = new Counter();
$about = new Counter();
$home->value = 7;
echo $home->value, ' ', $about->value, "\n"; // 7 0$home и $about — два разных объекта класса Counter. Число 7 попало только в свойство объекта из $home, а у объекта из $about осталось начальное 0.
Этот вопрос часто задают на собеседовании: «Чем класс отличается от объекта?» Ответ: класс — это описание, а объект — конкретный экземпляр, построенный по нему через new. Объектов одного класса может быть сколько угодно, и у каждого свои значения свойств.
Метод и $this
Класс описывает не только данные, но и действия с ними. Функцию, объявленную внутри класса, называют методом. Вот корзина покупок с методом add:
<?php
class Cart
{
public array $items = [];
public function add(string $item): void
{
$this->items[] = $item;
}
}
$cart = new Cart();
$cart->add('tea');
echo implode(' ', $cart->items), "\n"; // teaДавайте разберём:
public function add(string $item): voidобъявляет метод. Он устроен как обычная функция, только живёт внутри класса.$cart->add('tea')вызывает метод на объекте из$cartчерез ту же стрелку->.- Внутри метода
$this— объект, на котором метод вызвали. В этом вызове$this— тот же объект, что лежит в$cart. $this->items[] = $item;добавляет'tea'в свойствоitemsэтого объекта, аecho implode(' ', $cart->items)печатаетtea.
Здесь картинка с чертежом неточна. Метод не встроен в каждый дом: он описан в классе один раз. С каким домом работать, метод при каждом вызове узнаёт из $this.
Частая ошибка
Внутри метода к свойству обращаются без $this->:
<?php
class Cart
{
public array $items = [];
public function add(string $item): void
{
$items[] = $item; // ✗
}
}
$cart = new Cart();
$cart->add('tea');
echo count($cart->items), "\n"; // 0PHP не сообщает об ошибке, и программа печатает 0. Как вы уже знаете из темы о функциях, у тела функции своя область видимости, и у метода тоже. $items здесь — новая локальная переменная метода, а не свойство объекта: PHP создаёт её, кладёт в неё 'tea' и забывает после вызова.
К свойству объекта внутри метода всегда обращаются через $this: $this->items[] = $item;.
Главное
- Класс — чертёж, а
new Counter()строит по нему отдельный объект со своими свойствами. - Свойство объявляют в классе с типом и начальным значением, а читают и меняют через
->. - Метод — функция внутри класса, и
$thisв нём — объект, на котором метод вызвали. - Без
$this->имя внутри метода — локальная переменная, а не свойство.