web-dev-qa-db-fra.com

Comment vérifier un type d'objet spécifique dans PHP

J'ai une méthode qui accepte un objet PDO comme argument, pour permettre à l'utilisateur d'utiliser une connexion existante plutôt que la méthode pour en ouvrir une nouvelle et économiser des ressources:

public static function databaseConnect($pdo = null) {

Je connais is_object() pour vérifier si l'argument est un objet, mais je veux vérifier si $pdo Est un objet PDO, et pas seulement un objet.

Parce que l'utilisateur peut facilement entrer (par erreur?) Un autre type d'objet, un mysqli ou autre, et le script entier se séparera.

En bref: comment puis-je vérifier une variable pour un type d'objet spécifique?

62
Madara Uchiha

Vous pouvez utiliser instanceof :

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

Attention cependant, vous ne pouvez pas nier comme !instanceof, vous feriez donc plutôt:

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

De plus, en examinant votre question, vous pouvez utiliser l'indicateur de type d'objet, ce qui aide à appliquer les exigences, ainsi qu'à simplifier votre logique de vérification:

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

Les arguments saisis peuvent être obligatoires ou facultatifs:

// 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) { }

Les arguments non typés permettent une flexibilité grâce à des conditions explicites:

// 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')) {
        // ...
    }
}

Comme pour ce dernier ( en utilisant method_exists), je suis un peu mitigée à mon avis. Les personnes venant de Ruby trouveraient cela familier à respond_to? , pour le meilleur ou pour le pire. J'écrirais personnellement une interface et effectuerais un indice de type normal contre cela:

interface QueryableInterface
{ 
    function query();
}

class MyPDO extends PDO implements QueryableInterface { }

function connect(QueryableInterface $queryable) { }

Cependant, ce n'est pas toujours faisable; dans cet exemple, les objets PDO ne sont pas des paramètres valides car le type de base n'implémente pas QueryableInterface.

Il convient également de mentionner que les valeurs ont des types , pas des variables, en PHP. Ceci est important car null échouera à une vérification instanceof.

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

La valeur perd son type lorsqu'elle devient null, un manque de type.

85
Dan Lugg

utilisation

 bool is_a ( object $object , string $class_name )

Cela fonctionnera également pour les classes enfants.

voir http://php.net/is-a

EDIT: Ou vous pouvez utiliser l'indication de type:

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

Je pense que vous pouvez utiliser instanceof quelque chose comme:

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

Comme indiqué dans d'autres réponses, instanceof, get_class, et is_a sont probablement ce que vous cherchez.

Cependant, plutôt que de coder dans de nombreuses protections qui testent le type, certains développeurs trouvent plus productif (et plus facile à lire) de laisser le runtime gérer l'application, en particulier lorsque vous parlez d'appels que d'autres programmeurs effectueront ( quand un programmeur fait une erreur, les plaintes bruyantes de rupture d'application sont sans doute une bonne chose).

Si vous n'avez vraiment pas besoin que le script s'effondre lorsqu'un programmeur utilise votre méthode de manière incorrecte, enveloppez la section de code appropriée (dans ce cas, probablement à l'intérieur de databaseConnect) dans un try block , peut-être utilisez set_error_handler pour lever des exceptions sur les erreurs de script, puis configurer un ou plusieurs blocs catch qui indiquent ce qu'il faut faire lorsqu'une condition d'exception se produit.

2
Weston C