Объекты

Объекты в PHP — это просто ещё один тип данных. Объект позволяет хранить в переменной набор из свойств-значений, а также встроенные функции. Это делает объекты похожими по своей структуре со знакомыми ассоциативными массивами. Но отличие от массивов всё таки имеется и при этом достаточно важное — объекты могут иметь внутреннее состояние.

Особенности объектов и их отличия от массивов

Давай разберёмся что такое PHP-объект. Как сказано выше, объекты похожи на массивы, но со своими особенностями. Объекты могут содержать отдельные значения, каждое под своим ключом. Такие значения называются свойствами объекта.
Также объекты могут иметь внутри себя функции — их называют методами объекта. Методы могут обращаться к любым свойствам объекта, читать и записывать туда данные.

Значение свойства объекта может быть любого типа: число, строка, массив, другой объект. Но, в отличие от массива, объекты не позволяют добавлять в себя новые значения. То есть объект всегда имеет конечное число своих свойств и методов. Менять значения существующих свойств можно, а удалять и заменять их — нельзя. Что в корне отличается от поведения массива, ведь там добавлять и удалять значения можно в любое время.

Но самая большая особенность объектов — это то, как они создаются. Вспомним массив. Массив создается либо пустым, либо сразу с набором значений. Объекты устроены иначе. Дело в том, что объекты не существуют сами по себе. Чтобы создать новый объект, вам придётся вначале создать его описание — класс.
Класс — это как бы чертёж объекта. Класс описывает из чего состоит объект. Мы разберём классы чуть позже.

Анатомия объекта

Как же устроен объект изнутри? Содержимое объекта можно поделить на две группы: свойства и методы.
Свойства могут быть двух видов: публичные и скрытые. К публичным свойствам можно обращаться за пределами объекта, точно также как вы обращаетесь к элементам массива по его ключам.
Скрытые же свойства не имеют аналогов в массиве. Скрытые свойства доступны для чтения и изменения только внутри самого объекта — это могут делать его методы.

Вторая группа — это методы объекта.
Набор методов также называется поведением объекта. Как и свойства, методы бывают публичными и скрытыми. Публичные методы объекта можно вызывать из внешнего кода, а скрытые только из самого объекта. Методы способны свободно обращаться к свойствам объекта также просто, как если бы это были их внутренние переменные или аргументы.

Классы

Класс — это шаблон, по которому создаются объекты.

Напомню, что классы — это описания объектов. Мы не можем создать объект «на лету», как это происходит с массивами. Объект может быть создан только на основе своего описания — класса. Этим, кстати, реализация объектов в PHP отличается от JavaScript. В JS объектам не нужны никакие классы, и они могут быть созданы и модифицированы, когда угодно и, как угодно.

Класс как чертёж

Зачем же нужны классы и почему объекты не могут существовать без них?

Здесь аналогия очень простая: класс – это чертёж, максимально подробное описание того, как должно выглядеть изделие. Сам по себе класс не является чем-то физическим и осязаемым, то есть мы не можем использовать его в коде непосредственно. Вместо этого класс является схемой, структурой, на основе которой будет создан объект.

Жизненный цикл объекта

Вот из каких этапов состоит любая работа с объектами в PHP.
Начинается всё с создания класса. В классе мы фиксируем из каких свойств и методов будет состоять каждый его экземпляр. Также в классе можно задать начальные значения для каждого свойства.
Имея класс, возможно создать его экземпляр — объект.

Классы в PHP принято сохранять в отдельных файлах, поэтому вначале вы подключаете этот сценарий там, где он вам необходим. Затем вызываете процедуру создания нового объекта на основе этого класса.

Чтобы использовать объект в дальнейшем, его следует, как всегда, назначить переменной. Затем вы будете через переменную работать с объектом: вызывать его методы и обращаться к его свойствам.

Пример создания объекта на основе класса

Описание класса:

class WeatherEntry
{

    private $date;
    private $comment = "";
    private $temperature = 0;

    private $isRainy = false;

    public function __construct($date, string $comment, int $temperature)
    {
        $this->date = $date;
        $this->comment = $comment;
        $this->temperature = $temperature;
    }

    public function isCold()
    {
        return $this->temperature < 0;
    }

    public function setRainStatus($rain_status)
    {
        $this->isRainy = $rain_status;
    }

    public function getDayDescription()
    {
        $dt = strtotime($this->date);
        $delta = time() - $dt;
        $days = ceil($delta / 86400);

        $res = "Это было $days дней назад. В тот день было ";

        if ($this->isCold()) {
            $res .= "холодно. ";
        }
        else {
            $res .= "довольно тепло. ";
        }

        if ($this->isRainy) {
            $res .= "Семенил дождь.";
        }
        else {
            $res .= "На небе не было ни облачка.";
        }

        return $res;
    }
}

Создание объекта на основе класса:

$firstSeptember = new WeatherEntry("2018-09-01", "День знаний", 14);
$firstSeptember->setRainStatus(false);

print($firstSeptember->getDayDescription());

Разбор примера

Разберёмся с тем, что здесь происходит.
Начнём с целей создания данного класса. Его задача — хранить в объекте данные о погоде за конкретный день, а также предоставлять сводку за этот день в текстовом виде.

В классе определено четыре скрытых свойства. Это значит, что к ним не будет доступа за пределами объекта. Читать и записывать эти свойства могут только внутренние методы объекта. Сами свойства хранят температурные свойства (величина температуры, осадки), дату и дополнительный комментарий к записи. Некоторым свойствам задано значение по умолчанию.

Далее идёт перечисление методов. И начинается всё с метода, у которого особое имя и значение — __constructor.

Что такое конструктор объекта

Методы объекта вызываются из внешнего кода, при явном к ним обращении с указанием имени. Но если назвать один метод __constructor то он будет вызываться автоматически в момент создания объекта на основе класса.

Конструкторы объектов используются для инициализации каких либо значений и выполнении других подготовительных операций. В нашем примере конструктор устанавливает содержимое скрытых свойств.

Обращение к свойствам и методам объекта

Посмотрим как внутри метода происходит обращение к его свойствам.
Во-первых, для этого используется специальная переменная this, которая всегда присутствует внутри объекта и ссылается на него самого.

Во-вторых, для обращения к методам и свойствам объекта нужен специальный синтаксис: «стрелочка». Такая стрелочка отделяет имя свойства или метода от имени объекта. Это аналог квадратных скобок при работе с массивами.

Метод с именем isCold() нужен, чтобы узнать было ли холодно в тот день, основываясь на показаниях температуры в градусах.
Метод setRainStatus() устанавливает логическое значение, которое показывает статус осадков на день наблюдения.
И наконец метод getDayDescription() формирует текстовое описание погоды на заданную дату.

Создание объекта на основе класса

Написав класс, мы выполнили львиную часть из всего необходимого. Теперь нам предстоит создать новый объект на основе этого класса и показать, как с ним работать.
Новый объект создается с помощью ключевого слова new, после которого идёт имя его класса. В круглых скобках надо передать все аргументы в метод construct, когда такой имеется. Класс не обязан содержать этот метод, поэтому в таком случае круглые скобки не обязательны.

В коде мы передаём в конструктор почти все параметры погодных наблюдений. Затем уже для созданного объекта вызываются его методы: первый устанавливает осадки, а второй возвращает текстовое описание погоды.