In PHP wird die Funktion is_a () häufig verwendet, um festzustellen, ob ein Objekt zu einer bestimmten Klasse gehört oder eine Schnittstelle implementiert. Wenn wir sie jedoch verwenden, um festzustellen, ob ein Objekt ein bestimmtes Merkmal verwendet, stellen wir häufig fest, dass das Ergebnis die Erwartungen nicht entspricht. Dieser Artikel wird sich in die Ursachen dieses Problems befassen und mehrere mögliche Lösungen bereitstellen.
Die Funktion is_a () wird verwendet, um zu überprüfen, ob ein Objekt eine Instanz der angegebenen Klasse ist oder ob es sich um eine Unterklasse der Klasse handelt. Die typische Verwendung ist wie folgt:
if (is_a($obj, 'SomeClass')) {
// $obj Ja SomeClass oder eine Instanz seiner Unterklasse
}
Die zugrunde liegende Schicht der Funktion IS_A () besteht tatsächlich darin, die Erbschaftskette des Objekts und die Implementierung des Objekts zu beurteilen.
Merkmal ist ein in PHP 5.4 eingeführter Code -Wiederverwendungsmechanismus, mit dem Codeblöcke in mehreren Klassen "kopieren". Merkmal ist keine Klasse oder Schnittstelle in der Natur. Es kann nicht separat instanziiert werden und erscheinen nicht in der Erbschaftskette.
Lassen Sie uns ein einfaches Beispiel geben:
trait Logger {
public function log($msg) {
echo $msg;
}
}
class User {
use Logger;
}
Obwohl die Benutzerklasse das Logger -Merkmal verwendet, ist Logger keine Klasse, sodass sie nicht in der Vererbungsstruktur des Objekts angezeigt wird.
Da IS_A () die Klasse- oder Schnittstellenbeziehung ist, die das Objekt bestimmt und Merkmal keine Klasse oder Schnittstelle ist, gibt IS_A ($ OBJ, 'Logger') false zurück.
$user = new User();
var_dump(is_a($user, 'Logger')); // false
Dies liegt daran, dass Logger weder eine Klasse noch eine Schnittstelle zum $ User Object ist, noch in seiner Erbschaftskette.
Da es unmöglich ist, das Merkmal mit IS_A () zu beurteilen, besteht eine gemeinsame Alternative darin, den Reflexionsmechanismus von PHP in Kombination mit der Funktion class_usses () zu verwenden.
class_uses () gibt ein Array aller von einer Klasse verwendeten Merkmale zurück (einschließlich ererbter Merkmale).
if (in_array('Logger', class_uses($user))) {
echo "User Gebraucht Logger trait";
}
Beachten Sie jedoch, dass Class_Uses () nur das von der aktuelle Klasse verwendete Merkmal zurückgibt und nicht das von der übergeordnete Klasse verwendete Merkmal enthält. Wenn Sie das von allen übergeordnete Klassen verwendete Merkmal erhalten müssen, können Sie eine benutzerdefinierte Funktion verwenden, um es rekursiv abzurufen:
function class_uses_recursive($class) {
$traits = [];
do {
$traits = array_merge($traits, class_uses($class));
} while ($class = get_parent_class($class));
return array_unique($traits);
}
if (in_array('Logger', class_uses_recursive($user))) {
echo "User Gebraucht Logger trait(Einschließlich der Elternklasse)";
}
<?php
trait Logger {
public function log($msg) {
echo $msg;
}
}
class Base {
use Logger;
}
class User extends Base {}
$user = new User();
// verwenden is_a Urteil trait Das Ergebnis ist false
var_dump(is_a($user, 'Logger')); // bool(false)
// verwenden class_uses_recursive Urteil trait
function class_uses_recursive($class) {
$traits = [];
do {
$traits = array_merge($traits, class_uses($class));
} while ($class = get_parent_class($class));
return array_unique($traits);
}
if (in_array('Logger', class_uses_recursive($user))) {
echo "User Gebraucht Logger trait";
} else {
echo "User 没有verwenden Logger trait";
}
is_a () kann nicht verwendet werden, um das Merkmal zu beurteilen, da Merkmale keine Klasse oder Schnittstelle sind.
Um festzustellen, ob Merkmal verwendet wird, können Sie die Funktion class_Uses () verwenden.
Wenn Sie das von der Elternklasse verwendete Merkmal überprüfen müssen, müssen Sie die Merkmale aller übergeordneten Klassen rekursiv erhalten.
Diese Methode ist einfach und effizient und für den täglichen Gebrauch geeignet.
Durch das Verständnis der Natur des Merkmals und des PHP -Systems können wir vernünftigerweise Methoden auswählen, um die Beziehung zwischen Objekt und Merkmal zu beurteilen und logische Fehler zu vermeiden, die durch den Missbrauch von IS_A () verursacht werden.