Как проверить конкретный тип объекта в PHP

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

public static function databaseConnect($pdo = null) { 

Я знаю is_object() чтобы проверить, является ли аргумент объектом, но я хочу проверить, является ли $pdo объектом PDO, а не только объектом.

Поскольку пользователь может легко ввести (по ошибке?) Другой тип объекта, mysqli или такой, и весь скрипт разломается.

Короче: как я могу проверить переменную для определенного типа объекта?

Вы можете использовать instanceof :

 if ($pdo instanceof PDO) { // it's PDO } 

Имейте в виду, однако, вы не можете отрицать, как !instanceof , так что вы бы сделали:

 if (!($pdo instanceof PDO)) { // it's not PDO } 

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

 function connect(PDO $pdo = null) { if (null !== $pdo) { // it's PDO since it can only be // NULL or a PDO object (or a sub-type of PDO) } } connect(new SomeClass()); // fatal error, if SomeClass doesn't extend PDO 

Типизированные аргументы могут быть обязательными или необязательными:

 // required, only PDO (and sub-types) are valid function connect(PDO $pdo) { } // optional, only PDO (and sub-types) and // NULL (can be omitted) are valid function connect(PDO $pdo = null) { } 

Нетипированные аргументы допускают гибкость при явных условиях:

 // accepts any argument, checks for PDO in body function connect($pdo) { if ($pdo instanceof PDO) { // ... } } // accepts any argument, checks for non-PDO in body function connect($pdo) { if (!($pdo instanceof PDO)) { // ... } } // accepts any argument, checks for method existance function connect($pdo) { if (method_exists($pdo, 'query')) { // ... } } 

Что касается последнего ( используя method_exists ), я немного смешался, на мой взгляд. Люди, приезжающие из Руби, посчитали бы знакомым respond_to? , лучше или хуже. Я лично напишу интерфейс и сделаю обычный тип-намек на это:

 interface QueryableInterface { function query(); } class MyPDO extends PDO implements QueryableInterface { } function connect(QueryableInterface $queryable) { } 

Однако это не всегда возможно; в этом примере объекты PDO не являются допустимыми параметрами, так как базовый тип не реализует QueryableInterface .

Также стоит упомянуть, что значения имеют типы , а не переменные, в PHP. Это важно, потому что null не сможет проверить instanceof .

 $object = new Object(); $object = null; if ($object instanceof Object) { // never run because $object is simply null } 

Значение теряет свой тип, когда оно становится null , отсутствие типа.

использование

  bool is_a ( object $object , string $class_name ) 

Это будет работать и для дочерних классов.

см. http://php.net/is-a

EDIT: Или вы можете использовать тип намека:

 public static function databaseConnect(PDO $pdo = null) {... 

Я думаю, вы можете использовать instanceof что-то вроде:

 if ($pdo instanceof YOUR_PDO_OBJECT_INSTANCE) { // it is... } 

Как указано в других ответах, instanceof , get_class и is_a – это, вероятно, то, что вы ищете.

Однако, вместо того, чтобы кодировать множество охранников, проверяющих тип, некоторые разработчики считают его более продуктивным (и более простым для чтения), чтобы позволить среде выполнения выполнять принудительное выполнение, особенно когда вы говорите о вызовах, которые будут делать другие программисты ( когда программист совершает ошибку, прикладывающие громкие жалобы, пожалуй, хорошая вещь).

Если вам действительно не нужно, чтобы сценарий разваливался, когда программист неправильно использовал ваш метод, заверните соответствующий раздел кода (в данном случае, возможно, внутри базы данных) в блоке try , возможно, используйте set_error_handler для исключения исключений при ошибках скрипта , а затем настройте один или несколько блоков catch, которые указывают, что делать, когда возникает условие исключения.