# Сравнение объектов в ООП на PHP

Сейчас мы с вами научимся сравнивать объекты с помощью операторов `==` и `===`.

Вы должны уже знать, что для примитивов (то есть не объектов) оператор `==` сравнивает данные по значению без учета типа, а оператор `===` - учитывая тип:

`<?php var_dump(3 == 3); // выведет true var_dump(3 == '3'); // выведет true var_dump(3 === 3); // выведет true var_dump(3 === '3'); // выведет false ?>`

Давайте теперь посмотрим, как работает сравнение объектов.

При использовании оператора `==` для сравнения двух объектов выполняется сравнение свойств объектов: два объекта равны, если они имеют одинаковые свойства и их значения (значения свойств сравниваются через ==) и являются экземплярами одного и того же класса.

При сравнении через `===`, переменные, содержащие объекты, считаются равными только тогда, когда они ссылаются на один и тот же экземпляр одного и того же класса.

Давайте посмотрим на примере. Пусть у нас дан вот такой класс `User`:

`<?php class User { private $name; private $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function getName() { return $this->name; } public function getAge() { return $this->age; } } ?>`

Создадим два объекта нашего класса с одинаковыми значениями свойств и сравним созданные объекты:

`<?php $user1 = new User('john', 30); $user2 = new User('john', 30); var_dump($user1 == $user2); // выведет true ?>`

Пусть теперь значения свойств одинаковые, но у них разный тип:

`<?php $user1 = new User('john', 30); // возраст - число $user2 = new User('john', '30'); // возраст - строка var_dump($user1 == $user2); // выведет true ?>`

Пусть значения свойств разные:

`<?php $user1 = new User('john', 30); $user2 = new User('john', 25); var_dump($user1 == $user2); // выведет false ?>`

Давайте теперь сравним два наших объекта через `===`:

`<?php $user1 = new User('john', 30); $user2 = new User('john', 30); var_dump($user1 === $user2); // выведет false ?>`

Чтобы две переменных с объектами действительно были равными при сравнении через `===`, они должны указывать на один и тот же объект. Давайте сделаем, чтобы это было так, и сравним переменные:

`<?php $user1 = new User('john', 30); $user2 = $user1; // передача объекта по ссылке var_dump($user1 === $user2); // выведет true ?>`

Сделайте функцию `compare`, которая параметром будет принимать два объекта и возвращать `true`, если они имеют одинаковые свойства и значения являются экземплярами одного и того же класса, и `false`, если это не так.

Сделайте функцию `compare`, которая параметром будет принимать два объекта и возвращать `true`, если переданные переменные ссылаются на один и тот же объект, и `false`, если на разные.

Сделайте функцию `compare`, которая параметром будет принимать два объекта и сравнивать их.

Функция должна возвращать `1`, если переданные переменные ссылаются на один и тот же объект.

Функция должна возвращать `0`, если объекты разные, но одного и того же класса и с теми же свойствами и их значениями.

Функция должна возвращать `-1` в противном случае.

## Применение

Давайте рассмотрим применение изученной теории. Пусть у нас дан вот такой класс `Employee`:

`<?php class Employee { private $name; private $salary; public function __construct($name, $salary) { $this->name = $name; $this->salary = $salary; } public function getName() { return $this->name; } public function getSalary() { return $this->salary; } } ?>`

Пусть также дан такой класс `EmployeesCollection` для хранения коллекции работников:

`<?php class EmployeesCollection { private $employees = []; // массив работников // Добавляем нового работника: public function add($newEmployee) { $this->employees[] = $newEmployee; } // Получаем всех работников в виде массива: public function get() { return $this->employees; } } ?>`

Давайте сделаем так, чтобы работник, который уже есть в нашем наборе, не добавлялся еще раз. Для этого сделаем вспомогательный метод `exists`, который будет принимать объект с новым работником и проверять его наличие в массиве `$this->employees`:

`<?php private function exists($newEmployee) { foreach ($this->employees as $employee) { if ($employee == $newEmployee) { // сравниваем через == return true; } } return false; } ?>`

Давайте применим новый метод в нашем классе:

`<?php class EmployeesCollection { private $employees = []; public function add($newEmployee) { // Если такого работника нет - то добавляем: if (!$this->exists($newEmployee)) { $this->employees[] = $newEmployee; } } public function get() { return $this->employees; } private function exists($newEmployee) { foreach ($this->employees as $employee) { if ($employee == $newEmployee) { return true; } } return false; } } ?>`

Давайте проверим работу нашего класса:

`<?php $employeesCollection = new EmployeesCollection; $employeesCollection->add(new Employee('john', 100)); $employeesCollection->add(new Employee('john', 100)); // второго такого же не добавит var_dump($employeesCollection->get()); // убедимся в этом ?>`

В общем-то, мы получили устраивающий нас код. Но давайте попробуем поиграться с ним: поменяем при сравнении двойное равно на тройное:

`<?php private function exists($newEmployee) { foreach ($this->products as $product) { if ($product === $newEmployee) { // сравниваем через === return true; } } return false; } ?>`

Теперь при попытке добавить нового работника с такими же значениями свойств он будет добавляться:

`<?php $employeesCollection = new EmployeesCollection; $employeesCollection->add(new Employee('john', 100)); $employeesCollection->add(new Employee('john', 100)); // добавит var_dump($employeesCollection->get()); ?>`

Но если попытаться добавить тот же объект, то добавления не произойдет:

`<?php $employeesCollection = new EmployeesCollection; $employee = new Employee('john', 100); $employeesCollection->add($employee); $employeesCollection->add($employee); // не добавит, тк тот же объект var_dump($employeesCollection->get()); ?>`

Скопируйте мой код класса `Employee`, затем самостоятельно реализуйте описанный класс `EmployeesCollection`, проверьте его работу.

## Функция in_array

На самом деле код метода `exists` можно заменить стандартной PHP функцией `in_array`. Нужно только знать, как она выполняет сравнение - по двойному равно или по тройному.

Из документации следует, что эта функция имеет третий необязательный параметр. Если он не установлен или равен `false` - функция сравнивает по двойному равно, а равен `true` - то по тройному.

Давайте упростим код класса при условии сравнения объектов через двойное равно:

`<?php class EmployeesCollection { private $employees = []; public function add($newEmployee) { if (!in_array($newEmployee, $this->employees, false)) { $this->employees[] = $newEmployee; } } public function get() { return $this->employees; } } ?>`

А теперь при условии сравнения на тройное равно:

`<?php class EmployeesCollection { private $employees = []; public function add($newEmployee) { // Эквивалентно методу exists с === if (!in_array($newEmployee, $this->employees, true)) { $this->employees[] = $newEmployee; } } public function get() { return $this->employees; } } ?>`

Упростите ваш класс `EmployeesCollection` с использованием функции `in_array`, проверьте его работу.

←→
↑