¿Cómo obtengo el nombre de clase no calificado (corto) de un objeto?

153

¿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.

Greg Forbes
fuente
Parece casi inútil porque diferentes espacios de nombres podrían tener los mismos nombres de clase definidos dentro de ellos, entonces, ¿cómo manejará eso? Y eso es porque el nombre completo de la clase calificada se devuelve en su muestra
Alma Do
Estoy en un dispositivo móvil, así que no puedo enviar una respuesta decente, pero la solución es la reflexión, específicamente ReflectionClass :: getShortName - php.net/manual/en/reflectionclass.getshortname.php
lonesomeday
Para las personas que buscan una razón para querer esto: podría ser útil en una función auxiliar en una clase base común (es decir, los espacios de nombres múltiples nunca son un problema en esta situación).
Darren Cook

Respuestas:

182

Puedes hacer esto con reflexión. Específicamente, puede usar el ReflectionClass::getShortNamemétodo, que obtiene el nombre de la clase sin su espacio de nombres.

Primero, necesita crear una ReflectionClassinstancia y luego llamar al getShortNamemétodo de esa instancia:

$reflect = new ReflectionClass($object);
if ($reflect->getShortName() === 'Name') {
    // do this
}

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 con instanceof. (Puede hacerlo ReflectionClass, pero tendría un rendimiento mucho peor).

solitario
fuente
1
@ Greg.Forbes Porque Tenantno existe en el espacio de nombres actual. Intenta en su var_dump($tenant instanceof \Library\Entity\People\Tenant)lugar. ¡Además, investigue cómo usar el useoperador y el concepto general detrás de los espacios de nombres PHP!
solitario el
3
Tuve que agregar una barra al frente como esta$reflect = new \ReflectionClass($object);
prograhammer
77
En general, no me gusta hacer mucho vudú ReflectionClass en mi aplicación porque puede dar resultados inesperados si se usa incorrectamente (los métodos protegidos se hacen públicos, etc.). Se puede utilizar la sustitución de cadena simple en constantes mágicas de PHP en su lugar: str_replace(__NAMESPACE__ . '\\', '', __CLASS__);. También es mucho más rápido, en cuanto al rendimiento.
Franklin P Strube
2
@FranklinPStrube A menos que me falte algo, se obtiene el nombre corto de la clase actual, en lugar de la clase del objeto. Estoy de acuerdo en que el uso de la reflexión generalmente significa que lo estás haciendo mal.
lonesomeday
1
Muchas personas usan Reflections para anulaciones de visibilidad de miembros, lo cual es MALO. ¡No hagas eso! Pero afirmar que el uso de Reflections en general es Voodoo y Doing It Wrong da a la gente la impresión equivocada. No debe evitarlos, debe comprenderlos y saber cuándo son beneficiosos y en qué nivel de abstracción.
Vanja D.
131

(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

Reflection: 1.967512512207 s ClassA
Basename:   2.6840535163879 s ClassA
Explode:    2.6507515668869 s ClassA

Código

namespace foo\bar\baz;

class ClassA{
    public function getClassExplode(){
        return explode('\\', static::class)[0];
    }

    public function getClassReflection(){
        return (new \ReflectionClass($this))->getShortName();
    }

    public function getClassBasename(){
        return basename(str_replace('\\', '/', static::class));
    }
}

$a = new ClassA();
$num = 100000;

$rounds = 10;
$res = array(
    "Reflection" => array(),
    "Basename" => array(),
    "Explode" => array(),
);

for($r = 0; $r < $rounds; $r++){

    $start = microtime(true);
    for($i = 0; $i < $num; $i++){
        $a->getClassReflection();
    }
    $end = microtime(true);
    $res["Reflection"][] = ($end-$start);

    $start = microtime(true);
    for($i = 0; $i < $num; $i++){
        $a->getClassBasename();
    }
    $end = microtime(true);
    $res["Basename"][] = ($end-$start);

    $start = microtime(true);
    for($i = 0; $i < $num; $i++){
        $a->getClassExplode();
    }
    $end = microtime(true);
    $res["Explode"][] = ($end-$start);
}

echo "Reflection: ".array_sum($res["Reflection"])/count($res["Reflection"])." s ".$a->getClassReflection()."\n";
echo "Basename: ".array_sum($res["Basename"])/count($res["Basename"])." s ".$a->getClassBasename()."\n";
echo "Explode: ".array_sum($res["Explode"])/count($res["Explode"])." s ".$a->getClassExplode()."\n";

Los resultados realmente me sorprendieron. Pensé que la solución de explosión sería la forma más rápida de ir ...

Hirnhamster
fuente
1
Gran respuesta. Estaba ejecutando el mismo código pero obtuve un resultado diferente (Macbook Pro i7, 16 GB de RAM). Reflexión: 0.382, Nombre base: 0.380, Explotar: 0.399. Creo que depende de su sistema lo mejor ...
Tobias Nyholm
44
Ejecute PHP 10 000 veces con ese código y obtendrá un mejor resultado. Lo anterior puede obtener el reflejo de algún grupo, pero este no es el comportamiento habitual de las aplicaciones que existen. Solo lo necesitan una o dos veces.
LeMike
66
Me pregunto si esta prueba es cierta cuando se crea una instancia de ReflectionClass en un objeto más sustancial que el objeto pequeño de Clase A en su prueba ...
Joe Green
2
ejecutar solo una iteración en lugar de 100000 da un resultado muy diferente: Reflexión: 1.0967254638672 100000th / s ClassA Baseename: 0.81062316894531 100000th / s ClassA Explosión: 0.50067901611328 100000th / s ClassA
mcmurphy
1
explotar ('\\', static :: class) [0]? ¿No devuelve la primera parte del espacio de nombres? debería devolver la última parte, no la primera
2oppin
86

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.

$classNameWithNamespace=get_class($this);
return substr($classNameWithNamespace, strrpos($classNameWithNamespace, '\\')+1);

Resultados

Reflection: 0.068084406852722 s ClassA
Basename: 0.12301609516144 s ClassA
Explode: 0.14073524475098 s ClassA
Substring: 0.059865570068359 s ClassA 

Código

namespace foo\bar\baz;
class ClassA{
  public function getClassExplode(){
    $c = array_pop(explode('\\', get_class($this)));
    return $c;
  }

  public function getClassReflection(){
    $c = (new \ReflectionClass($this))->getShortName();
    return $c;
  }

  public function getClassBasename(){
    $c = basename(str_replace('\\', '/', get_class($this)));
    return $c;
  }

  public function getClassSubstring(){
    $classNameWithNamespace = get_class($this);
    return substr($classNameWithNamespace, strrpos($classNameWithNamespace, '\\')+1);
  }
}

$a = new ClassA();
$num = 100000;

$rounds = 10;
$res = array(
    "Reflection" => array(),
    "Basename" => array(),
    "Explode" => array(),
    "Substring" => array()
);

for($r = 0; $r < $rounds; $r++){

  $start = microtime(true);
  for($i = 0; $i < $num; $i++){
    $a->getClassReflection();
  }
  $end = microtime(true);
  $res["Reflection"][] = ($end-$start);

  $start = microtime(true);
  for($i = 0; $i < $num; $i++){
    $a->getClassBasename();
  }
  $end = microtime(true);
  $res["Basename"][] = ($end-$start);

  $start = microtime(true);
  for($i = 0; $i < $num; $i++){
    $a->getClassExplode();
  }
  $end = microtime(true);
  $res["Explode"][] = ($end-$start);

  $start = microtime(true);
  for($i = 0; $i < $num; $i++){
    $a->getClassSubstring();
  }
  $end = microtime(true);
  $res["Substring"][] = ($end-$start);
}

echo "Reflection: ".array_sum($res["Reflection"])/count($res["Reflection"])." s ".$a->getClassReflection()."\n";
echo "Basename: ".array_sum($res["Basename"])/count($res["Basename"])." s ".$a->getClassBasename()."\n";
echo "Explode: ".array_sum($res["Explode"])/count($res["Explode"])." s ".$a->getClassExplode()."\n";
echo "Substring: ".array_sum($res["Substring"])/count($res["Substring"])." s ".$a->getClassSubstring()."\n";

== ACTUALIZACIÓN ==

Como se menciona en los comentarios de @MrBandersnatch, incluso hay una forma más rápida de hacer esto:

return substr(strrchr(get_class($this), '\\'), 1);

Estos son los resultados actualizados de la prueba con "SubstringStrChr" (ahorra hasta aproximadamente 0.001 s):

Reflection: 0.073065280914307 s ClassA
Basename: 0.12585079669952 s ClassA
Explode: 0.14593172073364 s ClassA
Substring: 0.060415267944336 s ClassA
SubstringStrChr: 0.059880912303925 s ClassA
MaBi
fuente
55
Solo porque enumeramos por eficiencia, encontré que esta es la más rápida, comparación de la prueba proporcionada en esta solución substr (strrchr (get_class ($ obj), '\\'), 1); Reflexión: 0.084223914146423 s ClassA - Nombre base: 0.13206427097321 s ClassA - Explotar: 0.15331919193268 s ClassA - Substring: 0.068068099021912 s ClassA - Strrchar: 0.06472008228302 s ClassA -
ctatro85
Acabo de encontrar este hilo y agregué un punto de referencia adicional para probar 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
Franklin P Strube
1
@MrBandersnatch tienes razón. Probé su solución y me ahorró unos 0.001 s. ¡Actualicé mi respuesta con la tuya!
MaBi
3
Advertencia: ¡este código no funciona con clases en el espacio de nombres global (es decir, su nombre completo es igual a su nombre corto)! Consejo que a prueba algo como: if ($pos = strrchr(static::class, '\\')) { .. } else { ... }.
Tristan Jahier
1
Para que funcione también en el espacio de nombres global, simplemente anteponga el nombre de la clase con una barra invertida :) - es decir:$classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
rosell.dk
25

Aquí está una manera más fácil de hacer esto si está utilizando el framework PHP Laravel:

<?php

// usage anywhere
// returns HelloWorld
$name = class_basename('Path\To\YourClass\HelloWorld');

// usage inside a class
// returns HelloWorld
$name = class_basename(__CLASS__);
Spetsnaz
fuente
8
Esta no es una función php incorporada, parece una función auxiliar proporcionada por laravel.
Steve Buzonas
66
Creo que dijo eso
Scott
44
Gracias, estoy usando Laravel y esta respuesta me ahorró mucho tiempo.
Jeremy Wadhams
18

Yo uso esto:

basename(str_replace('\\', '/', get_class($object)));
arzzzen
fuente
También puede intentar: $ className = explotar ('\\', basename (get_class ($ this))); $ className = array_pop ($ className); para obtener el nombre de clase simple. O use substr.
Dompie
13
Funciona solo en Windows En Windows, tanto la barra diagonal (/) como la barra diagonal inversa () se utilizan como caracteres separadores de directorio. En otros entornos, es la barra diagonal (/) php.net/manual/en/function.basename.php
OzzyCzech
Lo he arreglado ahora. Gracias, @OzzyCzech.
Theodore R. Smith
1
@OzzyCzech Me encontré con esto mientras me movía de Windows a Ubuntu ... enloquecedor. Terminé usando la solución mencionada en la actualización de MaBi.
Chris Baker
@OzzyCzech ¿Cómo es que funciona solo en Windows? la pregunta era con respecto al nombre de espacio de nombres completo si no estoy equivocado también hace años, y los espacios de nombres no son específicos del sistema operativo, y siempre con una barra diagonal inversa como el separador de directorio de Windows.
FantomX1
16

Para obtener el nombre corto como una línea (desde PHP 5.4 ):

echo (new ReflectionClass($obj))->getShortName();

Es un enfoque limpio y razonablemente rápido .

flori
fuente
1
Me pregunto cómo se compara esto con una extracción de cadena en los puntos de referencia. Parece que esto sería mucho más lento.
Contacto no verificado
12

Me encontré en una situación única en la instanceofque 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.

$bench = new \xori\Benchmark(1000, 1000);     # https://github.com/Xorifelse/php-benchmark-closure
$shell = new \my\fancy\namespace\classname(); # Just an empty class named `classname` defined in the `\my\fancy\namespace\` namespace

$bench->register('strrpos', (function(){
    return substr(static::class, strrpos(static::class, '\\') + 1);
})->bindTo($shell));

$bench->register('safe strrpos', (function(){
    return substr(static::class, ($p = strrpos(static::class, '\\')) !== false ? $p + 1 : 0);
})->bindTo($shell));

$bench->register('strrchr', (function(){
    return substr(strrchr(static::class, '\\'), 1);
})->bindTo($shell));

$bench->register('reflection', (function(){
    return (new \ReflectionClass($this))->getShortName();
})->bindTo($shell));

$bench->register('reflection 2', (function($obj){
    return $obj->getShortName();
})->bindTo($shell), new \ReflectionClass($shell));

$bench->register('basename', (function(){
    return basename(str_replace('\\', '/', static::class));
})->bindTo($shell));

$bench->register('explode', (function(){
    $e = explode("\\", static::class);
    return end($e);
})->bindTo($shell));

$bench->register('slice', (function(){
    return join('',array_slice(explode('\\', static::class), -1));
})->bindTo($shell));    

print_r($bench->start());

Una lista del resultado completo está aquí, pero aquí están los aspectos más destacados:

  • Si usted va a utilizar la reflexión de todos modos, el uso $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.
  • Para hacer '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:

+-----------------+--------+
| registered name | speed  |
+-----------------+--------+
| reflection 2    | 70.75% |
| strrpos         | 60.38% |
| safe strrpos    | 57.69% |
| strrchr         | 54.88% |
| explode         | 46.60% |
| slice           | 37.02% |
| reflection      | 16.75% |
| basename        | 0.00%  |
+-----------------+--------+
Xorifelse
fuente
8

Puede usar explodepara separar el espacio de nombres y endobtener el nombre de la clase:

$ex = explode("\\", get_class($object));
$className = end($ex);
m13r
fuente
7

Yii way

\yii\helpers\StringHelper::basename(get_class($model));

Yii usa este método en su generador de código Gii

Documentación del método

Este método es similar a la función php basename () excepto que tratará los separadores de directorio \ y / as, independientemente del sistema operativo. Este método fue creado principalmente para trabajar en espacios de nombres php. Cuando trabaje con rutas de archivos reales, el nombre base de php () debería funcionar bien para usted. Nota: este método no conoce el sistema de archivos real o los componentes de ruta como "..".

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

marioviales
fuente
Bienvenido a Stack Overflow. Proporcione más información para su respuesta. ¿Qué hace esto y cómo se puede usar?
Jens
1
Esto funcionó para mí en Windows pero no en Linux, tal vez porque los espacios de nombres están en forma de barras inclinadas invertidas de directorios de Windows '\', mientras que Linux basename considera separadores de directorios barras diagonales '/'. Así que trabajé con strtr '. basename (strtr ($ class, '\\', '/'))
FantomX1
6

Aquí hay una solución simple para PHP 5.4+

namespace {
    trait Names {
        public static function getNamespace() {
            return implode('\\', array_slice(explode('\\', get_called_class()), 0, -1));
        }

        public static function getBaseClassName() {
            return basename(str_replace('\\', '/', get_called_class()));
        }
    }
}

¿Qué será el regreso?

namespace x\y\z {
    class SomeClass {
        use \Names;
    }

    echo \x\y\z\SomeClass::getNamespace() . PHP_EOL; // x\y\z
    echo \x\y\z\SomeClass::getBaseClassName() . PHP_EOL; // SomeClass
}

El nombre de clase extendido y el espacio de nombres funcionan bien para:

namespace d\e\f {

    class DifferentClass extends \x\y\z\SomeClass {

    }

    echo \d\e\f\DifferentClass::getNamespace() . PHP_EOL; // d\e\f
    echo \d\e\f\DifferentClass::getBaseClassName() . PHP_EOL; // DifferentClass
}

¿Qué pasa con la clase en el espacio de nombres global?

namespace {

    class ClassWithoutNamespace {
        use \Names;
    }

    echo ClassWithoutNamespace::getNamespace() . PHP_EOL; // empty string
    echo ClassWithoutNamespace::getBaseClassName() . PHP_EOL; // ClassWithoutNamespace
}
OzzyCzech
fuente
3

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

$calledClass = get_called_class();
$name = strpos($calledClass, '\\') === false ?
    $calledClass : substr($calledClass, strrpos($calledClass, '\\') + 1);

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:

<?php
namespace One\Two {
    class foo
    {
        public function foo()
        {
            $calledClass = get_called_class();
            $name = strpos($calledClass, '\\') === false ?
                $calledClass : substr($calledClass, strrpos($calledClass, '\\') + 1);

            var_dump($name);
        }
    }
}

namespace Three {
    class bar extends \One\Two\foo
    {
        public function bar()
        {
            $this->foo();
        }
    }
}

namespace {
    (new One\Two\foo)->foo();
    (new Three\bar)->bar();
}

// test.php:11:string 'foo' (length=3)
// test.php:11:string 'bar' (length=3)
Nino Škopac
fuente
2

Basado en la respuesta de @MaBi, hice esto:

trait ClassShortNameTrait
{
    public static function getClassShortName()
    {
        if ($pos = strrchr(static::class, '\\')) {
            return substr($pos, 1);
        } else {
            return static::class;
        }
    }
}

Que puedes usar así:

namespace Foo\Bar\Baz;

class A
{
    use ClassShortNameTrait;
}

A::classvuelve Foo\Bar\Baz\A, pero A::getClassShortName()vuelveA .

Funciona para PHP> = 5.5.

Tristan Jahier
fuente
2

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

namespace Foo\Bar\Baz;

class Test {
    public function getClass() {
        return str_replace(__NAMESPACE__.'\\', '', static::class);
    }
}
Seth
fuente
Desafortunadamente, eso solo funciona si lo está llamando en la clase cuyo nombre desea, no en cualquier nombre de clase como una cadena.
jurchiks
1

Encontrado en la página de documentación de get_class , donde lo publiqué en nwhiting dot com .

function get_class_name($object = null)
{
    if (!is_object($object) && !is_string($object)) {
        return false;
    }

    $class = explode('\\', (is_string($object) ? $object : get_class($object)));
    return $class[count($class) - 1];
}

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_classno sirve para nada. Es posible que desee consultar el operador instanceof.

GolezTrol
fuente
1

Puede obtener un resultado inesperado cuando la clase no tiene un espacio de nombres. Es decir , get_classvuelve Foo, entonces $baseClasssería oo.

$baseClass = substr(strrchr(get_class($this), '\\'), 1);

Esto se puede solucionar fácilmente mediante el prefijo get_classcon una barra diagonal inversa:

$baseClass = substr(strrchr('\\'.get_class($this), '\\'), 1);

Ahora también las clases sin un espacio de nombres devolverán el valor correcto.

Tim
fuente
1

Una buena expresión regular parece ser más rápida que la mayoría de los métodos mostrados anteriormente:

// both of the below calls will output: ShortClassName

echo preg_replace('/.*\\\\/', '', 'ShortClassName');
echo preg_replace('/.*\\\\/', '', 'SomeNamespace\SomePath\ShortClassName');

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.

Eugen Mihailescu
fuente
1

Debido a que "ReflectionClass" puede depender de la versión, solo use lo siguiente:

if(class_basename(get_class($object)) == 'Name') {
... do this ...
}

o incluso claro

if(class_basename(ClassName::class) == 'ClassName') {
... do this ...
}
Martin Tonev
fuente
0

Citando php.net:

En Windows, tanto la barra inclinada (/) como la barra invertida () se utilizan como caracteres separadores de directorio. En otros entornos, es la barra diagonal (/).

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 *:

<?php

if (basename(str_replace('\\', '/', get_class($object))) == 'Name') {
    // ... do this ...
}

Nota: Hice un punto de referencia de ReflectionClasscontra basename+str_replace+get_classy usar la reflexión es aproximadamente un 20% más rápido que usar el enfoque de nombre base, pero YMMV.

sangrado
fuente
0

La solución más rápida y fácil que funciona en cualquier entorno es:

<?php

namespace \My\Awesome\Namespace;

class Foo {

  private $shortName;

  public function fastShortName() {
    if ($this->shortName === null) {
      $this->shortName = explode("\\", static::class);
      $this->shortName = end($this->shortName);
    }
    return $this->shortName;
  }

  public function shortName() {
    return basename(strtr(static::class, "\\", "/"));
  }

}

echo (new Foo())->shortName(); // "Foo"

?>
Grillete de carne
fuente
1
Es por eso que desearía que PHP tuviera operadores de información de clase internos. Crear instancias de un reflector externo para hacer lo que debería ser tan simple como $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.
AgmLauncher
PHP sin funciones "concretas" (o deberíamos llamarlas de procedimiento) es imposible. Esperemos a PHP 6 (bueno, si alguna vez llega).
Fleshgrinder
0
$shortClassName = join('',array_slice(explode('\\', $longClassName), -1));
malhal
fuente
0

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:

$base_class = preg_replace('/^([\w\\\\]+\\\\)?([^\\\\]+)$/', '$2', get_class($myobject));

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.

Scott
fuente
0

Más rápido que encontré aquí para PHP 7.2elUbubntu 18.04

preg_replace('/^(\w+\\\)*/', '', static::class)
Vasilii Suricov
fuente