Как проверить наличие определенного типа объекта в PHP


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

public static function databaseConnect($pdo = null) {

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

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

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

4 56

4 ответа:

можно использовать 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

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

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

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

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

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

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

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