Comment vérifier la classe d'un objet dans l'environnement d'espacement des noms PHP sans spécifier la classe d'espacement de noms complète.
Par exemple, supposons que j'ai une bibliothèque d'objets / Entité / Contrat / Nom.
Le code suivant ne fonctionne pas car get_class renvoie la classe d'espace de noms complète.
If(get_class($object) == 'Name') {
... do this ...
}
Le mot-clé namespace magic renvoie l'espace de noms actuel, ce qui ne sert à rien si l'objet testé a un autre espace de noms.
Je pourrais simplement spécifier le nom de classe complet avec les espaces de noms, mais cela semble verrouiller la structure du code. Aussi peu utile si je voulais changer l'espace de noms de manière dynamique.
Quelqu'un peut-il penser à un moyen efficace de le faire. Je suppose qu'une option est regex.
la source
Réponses:
Vous pouvez le faire avec la réflexion. Plus précisément, vous pouvez utiliser la
ReflectionClass::getShortName
méthode, qui obtient le nom de la classe sans son espace de noms.Tout d'abord, vous devez créer une
ReflectionClass
instance, puis appeler lagetShortName
méthode de cette instance:Cependant, je ne peux pas imaginer de nombreuses circonstances où cela serait souhaitable. Si vous voulez exiger que l'objet soit membre d'une certaine classe, la façon de le tester est avec
instanceof
. Si vous voulez une manière plus flexible de signaler certaines contraintes, la manière de le faire est d'écrire une interface et d'exiger que le code implémente cette interface. Encore une fois, la bonne façon de faire est avecinstanceof
. (Vous pouvez le faire avecReflectionClass
, mais les performances seraient bien pires.)la source
Tenant
n'existe pas dans l'espace de noms actuel. Essayez à lavar_dump($tenant instanceof \Library\Entity\People\Tenant)
place. Découvrez également comment utiliser l'use
opérateur et le concept général des espaces de noms PHP!$reflect = new \ReflectionClass($object);
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. C'est aussi beaucoup plus rapide en termes de performances.(new \ReflectionClass($obj))->getShortName();
est la meilleure solution en termes de performances.J'étais curieux de savoir laquelle des solutions proposées était la plus rapide, j'ai donc préparé un petit test.
Résultats
Code
Les résultats m'ont surpris. Je pensais que la solution exploser serait le moyen le plus rapide d'aller ...
la source
J'ai ajouté substr au test de https://stackoverflow.com/a/25472778/2386943 et c'est la manière la plus rapide que j'ai pu tester (CentOS PHP 5.3.3, Ubuntu PHP 5.5.9) à la fois avec un i5.
Résultats
Code
== MISE À JOUR ==
Comme mentionné dans les commentaires de @MrBandersnatch, il existe un moyen encore plus rapide de le faire:
Voici les résultats des tests mis à jour avec "SubstringStrChr" (enregistre jusqu'à environ 0,001 s):
la source
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Les résultats sur une machine virtuelle faible ont montré qu'elle était presque deux fois plus rapide que tout cela.php -f bench.php Reflection: 0.44037771224976 s ClassA Basename: 0.48089025020599 s ClassA Explode: 0.54955270290375 s ClassA Substring: 0.38200764656067 s ClassA Frank's Custom Benchmark: 0.22782742977142 s ClassA
if ($pos = strrchr(static::class, '\\')) { .. } else { ... }
.$classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
Voici un moyen plus simple de le faire si vous utilisez le framework PHP Laravel:
la source
J'utilise ceci:
la source
Pour obtenir le nom court en une seule ligne (depuis PHP 5.4 ):
C'est une approche propre et raisonnable rapide .
la source
Je me suis retrouvé dans une situation unique où
instanceof
je ne pouvais pas être utilisé (en particulier les traits d'espacement de noms) et j'avais besoin du nom court de la manière la plus efficace possible, alors j'ai fait un petit benchmark par moi-même. Il comprend toutes les différentes méthodes et variations des réponses à cette question.Une liste de l'ensemble du résultat est ici mais voici les faits saillants:
$obj->getShortName()
est la méthode la plus rapide cependant ; en utilisant la réflexion uniquement pour obtenir le nom court, c'est presque la méthode la plus lente.'strrpos'
peut renvoyer une valeur erronée si l'objet n'est pas dans un espace de noms, alors que'safe strrpos'
c'est un tout petit peu plus lent, je dirais que c'est le gagnant.'basename'
compatible entre Linux et Windows, vous devez utiliserstr_replace()
ce qui fait de cette méthode la plus lente de toutes.Un tableau de résultats simplifié, la vitesse est mesurée par rapport à la méthode la plus lente:
la source
Vous pouvez utiliser
explode
pour séparer l'espace de noms etend
pour obtenir le nom de la classe:la source
Voie Yii
Yii utilise cette méthode dans son générateur de code Gii
Documentation de la méthode
Plus d'information:
https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseStringHelper.php http://www.yiiframework.com/doc-2.0/yii-helpers-basestringhelper.html#basename()-detail
la source
Voici une solution simple pour PHP 5.4+
Quel sera le retour?
Le nom de classe et l'espace de noms étendus fonctionnent bien pour:
Qu'en est-il de la classe dans l'espace de noms global?
la source
Si vous avez besoin de connaître le nom de la classe qui a été appelée depuis l'intérieur d'une classe et que vous ne voulez pas l'espace de noms, vous pouvez utiliser celui-ci
C'est génial lorsque vous avez une méthode dans une classe qui est étendue par d'autres classes. De plus, cela fonctionne également si les espaces de noms ne sont pas du tout utilisés.
Exemple:
la source
Sur la base de la réponse de @MaBi, j'ai fait ceci:
Que vous pouvez utiliser comme ça:
A::class
revientFoo\Bar\Baz\A
, maisA::getClassShortName()
revientA
.Fonctionne pour PHP> = 5.5.
la source
Je sais que c'est un vieil article mais c'est ce que j'utilise - Plus rapide que tout ce qui est posté ci-dessus, appelez simplement cette méthode depuis votre classe, beaucoup plus rapidement que d'utiliser Reflection
la source
Trouvé sur la page de documentation de get_class , où il a été posté par moi à nwhiting dot com .
Mais l'idée des espaces de noms est de structurer votre code. Cela signifie également que vous pouvez avoir des classes avec le même nom dans plusieurs espaces de noms. Donc, théoriquement, l'objet que vous passez pourrait avoir le nom de classe (dépouillé), tout en étant un objet totalement différent de celui que vous attendez.
En plus de cela, vous voudrez peut-être rechercher une classe de base spécifique , auquel cas
get_class
ne fait pas du tout l'affaire. Vous voudrez peut-être vérifier l'opérateurinstanceof
.la source
Vous pouvez obtenir un résultat inattendu lorsque la classe n'a pas d'espace de noms. Ie
get_class
retourneFoo
, alors$baseClass
seraitoo
.Cela peut facilement être corrigé en préfixant
get_class
avec une barre oblique inverse:Désormais, les classes sans espace de noms renverront également la bonne valeur.
la source
Une bonne vieille regex semble être plus rapide que la plupart des méthodes précédentes montrées:
Cela fonctionne donc même lorsque vous fournissez un nom de classe court ou un nom de classe complet (canonique).
Ce que fait l'expression régulière, c'est qu'il consomme tous les caractères précédents jusqu'à ce que le dernier séparateur soit trouvé (qui est également consommé). La chaîne restante sera donc le nom court de la classe.
Si vous souhaitez utiliser un séparateur différent (par exemple. /), Utilisez simplement ce séparateur à la place. N'oubliez pas d'échapper la barre oblique inverse (c'est-à-dire. \) Et également le caractère de motif (c'est-à-dire. /) Dans le modèle d'entrée.
la source
Parce que "ReflectionClass" peut dépendre de la version, utilisez simplement ce qui suit:
ou même clair
la source
Citant php.net:
Sur la base de ces informations et de l'expansion de la réponse arzzzen, cela devrait fonctionner sur les systèmes Windows et Nix *:
Remarque: j'ai fait un benchmark de
ReflectionClass
contrebasename+str_replace+get_class
et l'utilisation de la réflexion est environ 20% plus rapide que l'utilisation de l'approche du nom de base, mais YMMV.la source
La solution la plus rapide et la plus simple qui fonctionne dans n'importe quel environnement est:
la source
$Object->__class->getShortName()
vraiment me fait chier à propos de PHP. Votre approche fonctionne, mais maintenant vous mettez des méthodes concrètes dans vos classes juste pour exposer ce qui devrait être une construction de langage.la source
Si vous supprimez simplement les espaces de nom et que vous voulez quelque chose après le dernier \ dans un nom de classe avec un espace de noms (ou juste le nom s'il n'y a pas de '\'), vous pouvez faire quelque chose comme ceci:
Fondamentalement, c'est regex pour obtenir n'importe quelle combinaison de caractères ou de barres obliques inverses vers le haut et jusqu'à la dernière barre oblique inverse, puis de ne renvoyer que les caractères sans barre oblique inverse jusqu'à la fin de la chaîne. Ajout du? après le premier regroupement, cela signifie que si la correspondance de modèle n'existe pas, elle renvoie simplement la chaîne complète.
la source
Plus rapide que j'ai trouvé ici pour
PHP 7.2
leUbubntu 18.04
la source