¿Cómo verifico la clase de un objeto dentro del entorno espaciado de nombre de PHP sin especificar la clase de espacio de nombres completo?
Por ejemplo, supongamos que tengo una biblioteca de objetos / Entidad / Contrato / Nombre.
El siguiente código no funciona ya que get_class devuelve la clase de espacio de nombres completo.
If(get_class($object) == 'Name') {
... do this ...
}
La palabra clave mágica del espacio de nombres devuelve el espacio de nombres actual, que no sirve de nada si el objeto probado tiene otro espacio de nombres.
Simplemente podría especificar el nombre de clase completo con espacios de nombres, pero esto parece bloquear la estructura del código. Tampoco es de mucha utilidad si quisiera cambiar el espacio de nombres dinámicamente.
¿Alguien puede pensar en una manera eficiente de hacer esto? Supongo que una opción es regex.
fuente
Respuestas:
Puedes hacer esto con reflexión. Específicamente, puede usar el
ReflectionClass::getShortName
método, que obtiene el nombre de la clase sin su espacio de nombres.Primero, necesita crear una
ReflectionClass
instancia y luego llamar algetShortName
método de esa instancia:Sin embargo, no puedo imaginar muchas circunstancias en las que esto sería deseable. Si desea exigir que el objeto sea miembro de una determinada clase, la forma de probarlo es con
instanceof
. Si desea una forma más flexible de señalar ciertas restricciones, la forma de hacerlo es escribir una interfaz y requerir que el código implemente esa interfaz. Nuevamente, la forma correcta de hacer esto es coninstanceof
. (Puede hacerloReflectionClass
, pero tendría un rendimiento mucho peor).fuente
Tenant
no existe en el espacio de nombres actual. Intenta en suvar_dump($tenant instanceof \Library\Entity\People\Tenant)
lugar. ¡Además, investigue cómo usar eluse
operador y el concepto general detrás de los espacios de nombres PHP!$reflect = new \ReflectionClass($object);
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. También es mucho más rápido, en cuanto al rendimiento.(new \ReflectionClass($obj))->getShortName();
es la mejor solución con respecto al rendimiento.Tenía curiosidad por saber cuál de las soluciones proporcionadas es la más rápida, así que hice una pequeña prueba.
Resultados
Código
Los resultados realmente me sorprendieron. Pensé que la solución de explosión sería la forma más rápida de ir ...
fuente
Agregué substr a la prueba de https://stackoverflow.com/a/25472778/2386943 y esa es la forma más rápida que podría probar (CentOS PHP 5.3.3, Ubuntu PHP 5.5.9), ambos con un i5.
Resultados
Código
== ACTUALIZACIÓN ==
Como se menciona en los comentarios de @MrBandersnatch, incluso hay una forma más rápida de hacer esto:
Estos son los resultados actualizados de la prueba con "SubstringStrChr" (ahorra hasta aproximadamente 0.001 s):
fuente
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Los resultados en una máquina virtual débil mostraron que era casi el doble de rápido que todos estos.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);
Aquí está una manera más fácil de hacer esto si está utilizando el framework PHP Laravel:
fuente
Yo uso esto:
fuente
Para obtener el nombre corto como una línea (desde PHP 5.4 ):
Es un enfoque limpio y razonablemente rápido .
fuente
Me encontré en una situación única en la
instanceof
que no se podía usar (rasgos específicamente con espacios de nombres) y necesitaba el nombre corto de la manera más eficiente posible, así que he hecho un pequeño punto de referencia propio. Incluye todos los diferentes métodos y variaciones de las respuestas en esta pregunta.Una lista del resultado completo está aquí, pero aquí están los aspectos más destacados:
$obj->getShortName()
es el método más rápido , sin embargo ; usando solo reflexión para obtener el nombre corto, es casi el método más lento.'strrpos'
puede devolver un valor incorrecto si el objeto no está en un espacio de nombres, así que mientras'safe strrpos'
es un poco más lento, diría que este es el ganador.'basename'
compatible entre Linux y Windows, debe usarstr_replace()
que hace que este método sea el más lento de todos.Una tabla de resultados simplificada, la velocidad se mide en comparación con el método más lento:
fuente
Puede usar
explode
para separar el espacio de nombres yend
obtener el nombre de la clase:fuente
Yii way
Yii usa este método en su generador de código Gii
Documentación del método
Más información:
https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseStringHelper.php http://www.yiiframework.com/doc-2.0/yii-helpers-basestringhelper.html#basename()-detail
fuente
Aquí hay una solución simple para PHP 5.4+
¿Qué será el regreso?
El nombre de clase extendido y el espacio de nombres funcionan bien para:
¿Qué pasa con la clase en el espacio de nombres global?
fuente
Si necesita saber el nombre de la clase que se llamó desde dentro de una clase y no desea el espacio de nombres, puede usar este
Esto es genial cuando tienes un método dentro de una clase que se extiende por otras clases. Además, esto también funciona si los espacios de nombres no se utilizan en absoluto.
Ejemplo:
fuente
Basado en la respuesta de @MaBi, hice esto:
Que puedes usar así:
A::class
vuelveFoo\Bar\Baz\A
, peroA::getClassShortName()
vuelveA
.Funciona para PHP> = 5.5.
fuente
Sé que esta es una publicación antigua, pero esto es lo que uso: más rápido que todo lo publicado anteriormente, solo llame a este método desde su clase, mucho más rápido que usar Reflection
fuente
Encontrado en la página de documentación de get_class , donde lo publiqué en nwhiting dot com .
Pero la idea de los espacios de nombres es estructurar su código. Eso también significa que puede tener clases con el mismo nombre en múltiples espacios de nombres. Entonces, teóricamente, el objeto que pasa podría tener el nombre de clase (despojado), sin dejar de ser un objeto totalmente diferente de lo que espera.
Además de eso, es posible que desee verificar una clase base específica , en cuyo caso
get_class
no sirve para nada. Es posible que desee consultar el operadorinstanceof
.fuente
Puede obtener un resultado inesperado cuando la clase no tiene un espacio de nombres. Es decir ,
get_class
vuelveFoo
, entonces$baseClass
seríaoo
.Esto se puede solucionar fácilmente mediante el prefijo
get_class
con una barra diagonal inversa:Ahora también las clases sin un espacio de nombres devolverán el valor correcto.
fuente
Una buena expresión regular parece ser más rápida que la mayoría de los métodos mostrados anteriormente:
Esto funciona incluso cuando proporciona un nombre de clase corto o un nombre de clase totalmente calificado (canónico).
Lo que hace la expresión regular es que consume todos los caracteres anteriores hasta que se encuentra el último separador (que también se consume). Entonces la cadena restante será el nombre corto de la clase.
Si desea usar un separador diferente (p. Ej. /), Simplemente use ese separador en su lugar. Recuerde escapar de la barra diagonal inversa (es decir, \) y también del patrón char (es decir, /) en el patrón de entrada.
fuente
Debido a que "ReflectionClass" puede depender de la versión, solo use lo siguiente:
o incluso claro
fuente
Citando php.net:
Según esta información y expandiendo desde la respuesta de arzzzen, esto debería funcionar tanto en los sistemas Windows como en los sistemas Nix *:
Nota: Hice un punto de referencia de
ReflectionClass
contrabasename+str_replace+get_class
y usar la reflexión es aproximadamente un 20% más rápido que usar el enfoque de nombre base, pero YMMV.fuente
La solución más rápida y fácil que funciona en cualquier entorno es:
fuente
$Object->__class->getShortName()
realmente me molesta sobre PHP. Su enfoque funciona, pero ahora está poniendo métodos concretos en sus clases solo para exponer lo que debería ser una construcción del lenguaje.fuente
Si solo está eliminando espacios de nombres y desea algo después del último \ en un nombre de clase con espacio de nombres (o solo el nombre si no hay '\'), puede hacer algo como esto:
Básicamente, es una expresión regular para obtener cualquier combinación de caracteres o barras invertidas y hasta la última barra invertida y luego devolver solo los caracteres que no son barras invertidas y hasta el final de la cadena. Agregar el? después de la primera agrupación significa que si la coincidencia de patrón no existe, solo devuelve la cadena completa.
fuente
Más rápido que encontré aquí para
PHP 7.2
elUbubntu 18.04
fuente