Установление класса объекта в PHP: полное руководство с примерами

Раздел: Объектно-ориентированное программирование в PHP -> Классы в PHP

Определение класса объекта в PHP

В PHP существует несколько способов узнать, к какому классу принадлежит объект. Основным и наиболее универсальным решением является функция get_class(). Она возвращает строку с именем класса, экземпляром которого является переданный объект.


class Car {}
$obj = new Car();
echo get_class($obj); // Car

Php узнать класс (определение класса объекта в php)

Эта функция подходит для любой версии PHP (начиная с 5.0) и работает как с пользовательскими, так и со встроенными классами. Если вызвать get_class() без аргумента внутри метода объекта, она вернёт имя класса этого объекта.


class Animal {
    public function whoAmI() {
        return get_class(); // вернёт 'Animal'
    }
}
$animal = new Animal();
echo $animal->whoAmI();

Типичная ошибка: передача в get_class() не объекта, а примитивного типа (числа, строки). В PHP 8.0 это вызовет TypeError, в более ранних версиях - ошибку уровня E_WARNING. Всегда проверяйте, что аргумент является объектом с помощью is_object().


$value = 123;
if (is_object($value)) {
    echo get_class($value);
} else {
    echo 'Не объект';
}

Цель использования: получить точное имя класса объекта для логирования, сериализации, динамического вызова статических методов или проверки типа при наследовании.

Как проверить, является ли объект экземпляром определённого класса?

Оператор instanceof позволяет узнать, принадлежит ли объект заданному классу или его наследникам. Он возвращает true/false.


class Vehicle {}
class Car extends Vehicle {}
$car = new Car();
var_dump($car instanceof Car);      // bool(true)
var_dump($car instanceof Vehicle);  // bool(true) - наследование

Проблема: оператор не различает интерфейсы и классы - он работает с любым типом (класс, интерфейс, трейт). Для интерфейсов поведение аналогично.

Использование: условное выполнение кода в зависимости от типа объекта, например в шаблонах проектирования (Strategy, Factory).

Как определить, является ли объект экземпляром класса с учётом только прямого класса (без наследников)?

Можно использовать функцию is_a() с третьим параметром allow_string и передать false для отключения проверки наследования. Однако проще сравнить результат get_class() с нужным именем.


class Base {}
class Derived extends Base {}
$obj = new Derived();
$isExactlyBase = (get_class($obj) === 'Base'); // false

Как получить полную информацию о классе объекта (методы, свойства, константы)?

Класс ReflectionClass из расширения Reflection предоставляет детальный анализ. Пример получения всех публичных методов:


class Sample {
    public $prop = 1;
    public function foo() {}
    private function bar() {}
}
$ref = new ReflectionClass(new Sample());
$methods = $ref->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
    echo $method->getName() . "\n"; // foo
}

Ошибка: создание ReflectionClass от несуществующего класса или примитива вызовет ReflectionException. Рекомендуется предварительно проверять класс функцией class_exists().

Цель: реализация документации, отладки, генерации кода, аннотаций.

Как узнать имя родительского класса объекта?

Функция get_parent_class() принимает объект или строку с именем класса и возвращает имя родительского класса или false.


class ParentClass {}
class ChildClass extends ParentClass {}
$child = new ChildClass();
echo get_parent_class($child); // ParentClass

Если наследования нет, возвращается false. Для цепочек наследования можно использовать class_parents().


class A {}
class B extends A {}
class C extends B {}
$obj = new C();
print_r(class_parents($obj)); // ['B' => 'B', 'A' => 'A']

Как динамически проверить, реализует ли объект интерфейс?

Функция class_implements() возвращает массив интерфейсов, реализуемых классом объекта.


interface LoggerInterface {}
class FileLogger implements LoggerInterface {}
$logger = new FileLogger();
$interfaces = class_implements($logger);
var_dump(isset($interfaces['LoggerInterface'])); // bool(true)

Альтернатива - оператор instanceof с именем интерфейса: $logger instanceof LoggerInterface.

Как узнать, какие трейты использует класс объекта?

Функция class_uses() возвращает массив трейтов, задействованных в классе (включая родительские).


trait Loggable {}
class Service {
    use Loggable;
}
$service = new Service();
print_r(class_uses($service)); // ['Loggable' => 'Loggable']

Расширенные примеры определения класса объекта

Ниже приведены нестандартные и подробные примеры использования средств определения класса, включая работу с анонимными классами, динамическими проверками и рефлексией.

1. Определение класса анонимного объекта

Пример

$anonymous = new class {
    public $value = 42;
};
echo get_class($anonymous); // class@anonymous\0x... (сгенерированное имя)
Результат: class@anonymous/var/www/.../script.php0x7f...

Пояснение: Анонимные классы получают уникальное имя, включающее путь к файлу и адрес в памяти. get_class() корректно возвращает его. Для проверки принадлежности к анонимному классу можно использовать сравнение с маской: str_starts_with(get_class($obj), 'class@anonymous').

2. Проверка принадлежности к нескольким типам одновременно

Пример

interface Flyable {}
interface Swimmable {}
class Duck implements Flyable, Swimmable {}
$duck = new Duck();
$isBoth = ($duck instanceof Flyable) && ($duck instanceof Swimmable);
echo $isBoth ? 'Да' : 'Нет'; // Да
Результат: Да

Используется, когда требуется убедиться, что объект поддерживает несколько контрактов одновременно.

3. Получение класса объекта через ReflectionObject (ReflectionClass для объекта)

Пример

class Config {
    private $settings = ['db' => 'mysql'];
    public function getSettings() { return $this->settings; }
}
$cfg = new Config();
$reflection = new ReflectionObject($cfg);
echo $reflection->getName(); // Config
echo $reflection->getShortName(); // Config
// Получение свойств, включая private:
$properties = $reflection->getProperties();
foreach ($properties as $prop) {
    $prop->setAccessible(true);
    echo $prop->getName() . ': ' . $prop->getValue($cfg) . "\n";
}
Config
Config
settings: Array

ReflectionObject - производный от ReflectionClass, специализированный для работы с экземплярами. Позволяет манипулировать приватными данными (с осторожностью).

4. Динамическое определение класса на основе пространства имён

Пример

namespace App\Models;
class User {}

$object = new User();
$fullClass = get_class($object); // App\Models\User
$parts = explode('\\', $fullClass);
$shortName = end($parts); // User
echo $shortName;
User

Полезно для генерации URL, маршрутизации или логирования с сокращёнными именами.

5. Использование class_alias для перенаправления get_class

Пример

class OriginalClass {}
class_alias('OriginalClass', 'AliasClass');
$obj = new OriginalClass();
echo get_class($obj); // OriginalClass (не AliasClass)
// alias не меняет реальный класс объекта
OriginalClass

Важно знать, что class_alias создаёт псевдоним для автозагрузчика, но get_class всегда возвращает оригинальное имя.

6. Получение всех предков класса (включая интерфейсы и трейты) одной функцией

Пример

interface Loggable {}
trait Timestampable {}
class Entity implements Loggable {
    use Timestampable;
}
class User extends Entity {}

$user = new User();
$parents = class_parents($user);
$interfaces = class_implements($user);
$traits = class_uses($user);
print_r($parents);
print_r($interfaces);
print_r($traits);
Array
(
    [Entity] => Entity
)
Array
(
    [Loggable] => Loggable
)
Array
(
    [Timestampable] => Timestampable
)

Эти функции рекурсивно собирают все типы, задействованные в иерархии класса. Применяется при построении ORM, генерации миграций.

7. Проверка, является ли объект экземпляром класса с использованием is_a() с allow_string

Пример

class Vehicle {}
class Car extends Vehicle {}
$car = new Car();
var_dump(is_a($car, 'Vehicle'));        // bool(true)
var_dump(is_a($car, 'Vehicle', true));  // bool(true) - по умолчанию true
var_dump(is_a($car, 'Car', false));     // bool(true) - только точный класс?
// Третий параметр allow_string (true - разрешить строку класса, не влияет на проверку наследования)
bool(true)
bool(true)
bool(true)

Для точной проверки без учёта наследования следует сравнивать имена классов через get_class().

8. Использование get_called_class() в статическом контексте (позднее статическое связывание)

Пример

class Base {
    public static function who() {
        return get_called_class();
    }
}
class Child extends Base {}
echo Base::who();  // Base
echo Child::who(); // Child
BaseChild

Позволяет в статическом методе узнать имя класса, который был вызван (в отличие от __CLASS__, который всегда равен имени класса, где определён метод).

Определение класса объекта в PHP - comments

En
Php узнать класс (php)