Comment puis-je obtenir un objet non qualifiés (court) nom de la classe?
Comment puis-je vérifier la classe d'un objet, dans le nom de PHP espacés environnement sans spécifier la totalité des espaces de classe.
Par exemple, supposons que j'avais une bibliothèque d'objet/Entité/Contrat/Nom.
Le code suivant ne fonctionne pas comme get_class retourne la totalité des espaces de classe.
If(get_class($object) == 'Name') {
... do this ...
}
L'espace de noms de la magie mot-clé renvoie l'espace de noms courant, qui n'est d'aucune utilité si l'objet testé est un autre espace de noms.
Je pourrais simplement spécifier le nom de la classe avec des espaces de noms, mais cela semble de verrouillage dans la structure du code. Également pas d'une grande utilité si je voulais changer l'espace de noms dynamiquement.
Peut-on penser d'une façon efficace pour ce faire. Je suppose qu'une option est regex.
- Il semble près inutile, parce que les différents espaces de noms pourraient avoir les mêmes noms de classes définies à l'intérieur d'eux, alors comment allez-vous gérer cela? Et c'est parce que pleinement qualifié de la classe nom est retourné dans votre échantillon
- Je suis sur un appareil mobile, donc je ne peux pas soumettre un décent réponse, mais la solution est la réflexion, plus précisément ReflectionClass::getShortName - php.net/manual/en/reflectionclass.getshortname.php
- Pour les personnes qui cherchent une raison que cela: il pourrait être utile dans une fonction d'aide dans une classe de base commune (c'est à dire de plusieurs espaces de noms n'est jamais un problème dans cette situation).
Vous devez vous connecter pour publier un commentaire.
Vous pouvez le faire avec la réflexion. Plus précisément, vous pouvez utiliser le
ReflectionClass::getShortName
méthode, qui prend le nom de la classe sans son espace de noms.Tout d'abord, vous avez besoin pour construire un
ReflectionClass
instance, puis en appel legetShortName
méthode de cette instance:Cependant, je ne peux pas imaginer de nombreuses situations, ce qui serait souhaitable. Si vous voulez exiger que l'objet est un membre d'une certaine classe, pour le tester c'est avec
instanceof
. Si vous voulez un moyen plus souple de signal de certaines contraintes, la façon de le faire est d'écrire une interface et d'exiger que le code à implémenter cette interface. De nouveau, la bonne façon de le faire est avecinstanceof
. (Vous pouvez le faire avecReflectionClass
, mais il aurait pu avoir bien pire performance.)Tenant
n'existe pas dans l'espace de noms courant. Essayezvar_dump($tenant instanceof \Library\Entity\People\Tenant)
à la place. Aussi, d'enquêter sur la façon d'utiliser leuse
de l'opérateur, et le concept général derrière PHP espaces de noms!$reflect = new \ReflectionClass($object);
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Il est également beaucoup plus rapide, en terme de performance.explode("\\", get_class($object));
?(new \ReflectionClass($obj))->getShortName();
est la meilleure solution en ce qui concerne les performances.J'étais curieux de savoir laquelle des solutions est la plus rapide, donc je vous ai concocté un petit test.
Résultats
Code
Vraiment les résultats m'ont surpris. Je pensais que les exploser solution serait le moyen le plus rapide pour aller...
J'ai ajouté substr à l'épreuve de https://stackoverflow.com/a/25472778/2386943
et c'est la fastet 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 y a même un moyen plus rapide pour ce faire:
Voici la mise à jour des résultats de test avec "SubstringStrChr" (permet d'économiser jusqu'à environ 0,001 s):
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Les résultats sur la faiblesse de la machine virtuelle ont montré qu'il est presque deux fois plus rapide que tous les de ces.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
__CLASS__
et aussi__NAMESPACE__
qui pointent vers le fichier en cours). Par conséquent, il est plus rapide. Pour être juste, j'ai ajouté votre suggestion pour le test et il a couru. Gardez à l'espritstr_replace
est plus lent quesubstr
. Voici les résultats:Reflection: 0.070202589035034 s TestController Basename: 0.12093763881259 s TestController Explode: 0.12268789609273 s TestController Substring: 0.061004797617594 s TestController Consts: 0.057392239570618 s TestController
Votre fonction est la "Consts".substr(strrchr(get_called_class(), '\\'), 1)
par exemple lorsque vous voulez obtenir un nom de Classe dans la classe parent, traits, etc.if ($pos = strrchr(static::class, '\\')) { .. } else { ... }
.strtolower(substr(strrchr(MyClass::class, '\\'), 1));
return substr(strrchr(get_class($this), '\'), 1);
$classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
Ici est un moyen plus facile de le faire si vous utilisez le framework PHP Laravel :
J'utilise ceci:
Pour obtenir le nom court comme un one-liner (depuis PHP 5.4):
Il est propre approche et rapide raisonnable.
Je me suis retrouvé dans une situation unique où
instanceof
ne pouvait pas être utilisé spécifiquement à des espaces de traits) et je nécessaire le nom court de la manière la plus efficace possible, j'ai donc fait un petit benchmark de mon propre. Il comprend toutes les différentes méthodes & des variations dans les réponses à cette question.Une liste de la de la tout le résultat est ici, mais voici les faits saillants:
$obj->getShortName()
est la méthode la plus rapide cependant; l'aide de la réflexion seulement pour obtenir le nom court c'est presque la méthode la plus lente.'strrpos'
peut retourner une valeur erronée si l'objet n'est pas dans un espace de noms ainsi, alors que'safe strrpos'
est un tout petit peu plus lent, je dirais que c'est le vainqueur.'basename'
compatibles entre Linux et Windows, vous devez utiliserstr_replace()
ce qui rend cette méthode le plus lent de tous.Un tableau simplifié des résultats, la vitesse est mesurée par rapport à la méthode la plus lente:
Ici est la solution la plus simple pour PHP 5.4+
Ce qui sera de retour?
Prolongée nom de la classe et de l'espace de noms fonctionne bien pour:
Qu'en classe dans l'espace de noms global?
Vous pouvez utiliser
explode
pour la séparation de l'espace de noms etend
pour obtenir le nom de la classe:Yii façon
Yii utilise cette méthode dans son Gii générateur de code
Documentation de la méthode
Plus d'informations:
https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseStringHelper.php
http://www.yiiframework.com/doc-2.0/yii-helpers-basestringhelper.html#basename()-détail
Si vous avez besoin de savoir le nom de la classe qui a été appelé à partir de l'intérieur de la classe et ne veulent pas l'espace de noms, vous pouvez utiliser ce un
C'est super quand vous avez une méthode à l'intérieur d'une classe, qui est prolongé par d'autres classes. En outre, cela fonctionne aussi si les espaces de noms ne sont pas utilisés du tout.
Exemple:
Basé sur @MaBi 's réponse, j'ai fait ceci:
Que vous pouvez utiliser comme ça:
A::class
retourneFoo\Bar\Baz\A
, maisA::getClassShortName()
retourneA
.Fonctionne pour PHP >= 5.5.
Trouvé sur le page de documentation du get_class, où il a été posté par moi à nwhiting dot com.
Mais l'idée d'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, en théorie, l'objet que vous passez peut avoir le nom (stripped) nom de la classe, tout en étant un tout autre objet que vous attendez.
En outre, vous voudrez peut-être consulter pour un de la classe de base, auquel cas
get_class
ne pas faire l'affaire à tous les. Vous pourriez vouloir vérifier l'opérateurinstanceof
.Vous pouvez obtenir un résultat inattendu lorsque la classe ne dispose pas d'un espace de noms. I. e.
get_class
retourneFoo
, puis$baseClass
seraitoo
.Cela peut être facilement fixé par la préfixation de
get_class
avec une barre oblique inverse:Maintenant également des classes sans un espace de noms sera de retour la valeur de droite.
Citant php.net:
Basé sur cette info et l'expansion à partir de arzzzen réponse cela devrait fonctionner sur Windows et Nix* systèmes:
Remarque: j'ai fait un test de
ReflectionClass
contrebasename+str_replace+get_class
et en utilisant la réflexion est environ 20% plus rapide que d'utiliser le nom de base de l'approche, mais YMMV.Le plus rapide et le plus simple à mon humble avis la solution qui fonctionne dans n'importe quel environnement:
$Object->__class->getShortName()
pisse vraiment me off sur PHP. Votre approche fonctionne, mais maintenant vous êtes de mettre en béton méthodes dans vos classes juste pour exposer ce que devrait être une construction du langage.Si vous êtes juste de décapage des espaces de noms et de vouloir quoi que ce soit après le dernier \ dans un nom de classe avec l'espace de noms (ou juste le nom si il n'y a pas de '\') vous pouvez faire quelque chose comme ceci:
Fondamentalement, c'est l'expression régulière regex pour obtenir n'importe quelle combinaison de caractères ou des barres obliques inverses et jusqu'à la dernière barre oblique inverse et de ne renvoyer que les non-barres obliques inverses et jusqu'à la fin de la chaîne. L'ajout de l' ? après le premier regroupement est dire si la mise en correspondance du modèle n'existe pas, elle retourne la chaîne de caractères complète.
Un bon vieux regex semble être plus rapide que la plupart des anciens montré méthodes:
Si cela fonctionne même lorsque vous fournissez un court nom de la classe ou complet (canonique) nom de la classe.
Ce que la regex n'est qu'elle consomme tous les précédents caractères jusqu'à la dernière séparateur (ce qui est également consommée). Si la chaîne restante sera court nom de la classe.
Si vous souhaitez utiliser un autre séparateur (eg. /) ensuite, il suffit d'utiliser un séparateur à la place. N'oubliez pas d'échapper à la barre oblique inverse (ie. \) et également le modèle de char (ie. /) dans le modèle d'entrée.
Je sais que c'est un vieux post, mais c'est ce que j'utilise plus Rapide que tous posté ci-dessus suffit d'appeler cette méthode à partir de votre classe, beaucoup plus rapide que l'utilisation de la Réflexion