Come posso ottenere il nome di classe (breve) non qualificato di un oggetto?


153

Come posso controllare la classe di un oggetto all'interno dell'ambiente con spaziatura tra nomi PHP senza specificare la classe con spaziatura completa.

Ad esempio supponiamo che avessi una libreria di oggetti / Entità / Contratto / Nome.

Il codice seguente non funziona poiché get_class restituisce la classe con spazio completo per i nomi.

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

La parola chiave magica dello spazio dei nomi restituisce lo spazio dei nomi corrente, che è inutile se l'oggetto testato ha un altro spazio dei nomi.

Potrei semplicemente specificare il nome completo della classe con spazi dei nomi, ma questo sembra bloccare la struttura del codice. Inoltre, non sarebbe molto utile se volessi cambiare dinamicamente lo spazio dei nomi.

Qualcuno può pensare a un modo efficace per farlo. Immagino che un'opzione sia regex.


Sembra quasi inutile perché diversi spazi dei nomi potrebbero avere gli stessi nomi di classe definiti al loro interno, quindi come lo gestirai? E questo perché il nome completo della classe viene restituito nell'esempio
Alma Do,

Sono su un dispositivo mobile, quindi non posso presentare una risposta decente, ma la soluzione è la riflessione, in particolare ReflectionClass :: getShortName - php.net/manual/en/reflectionclass.getshortname.php
lonesomeday

Per le persone in cerca di un motivo per volerlo: potrebbe essere utile in una funzione di supporto in una classe base comune (vale a dire che più spazi dei nomi non è mai un problema in questa situazione).
Darren Cook,

Risposte:


182

Puoi farlo con la riflessione. In particolare, è possibile utilizzare il ReflectionClass::getShortNamemetodo, che ottiene il nome della classe senza il suo spazio dei nomi.

Innanzitutto, è necessario creare ReflectionClassun'istanza, quindi chiamare il getShortNamemetodo di tale istanza:

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

Tuttavia, non riesco a immaginare molte circostanze in cui ciò sarebbe desiderabile. Se vuoi richiedere che l'oggetto sia un membro di una determinata classe, il modo per testarlo è con instanceof. Se si desidera un modo più flessibile per segnalare determinati vincoli, il modo per farlo è scrivere un'interfaccia e richiedere che il codice implementi tale interfaccia. Ancora una volta, il modo corretto per farlo è con instanceof. (Puoi farlo con ReflectionClass, ma avrebbe prestazioni molto peggiori.)


1
@ Greg.Forbes Perché Tenantnon esiste nello spazio dei nomi corrente. Prova var_dump($tenant instanceof \Library\Entity\People\Tenant)invece. Inoltre, scopri come utilizzare l' useoperatore e il concetto generale dietro gli spazi dei nomi PHP!
lunedì

3
Ho dovuto aggiungere una barra in questo modo$reflect = new \ReflectionClass($object);
prograhammer

7
In genere non mi piace fare molto voodoo ReflectionClass nella mia applicazione perché può portare a risultati imprevisti se usato male (metodi protetti che diventano pubblici, ecc.). È possibile utilizzare la semplice sostituzione stringa su magici costanti PHP invece: str_replace(__NAMESPACE__ . '\\', '', __CLASS__);. È anche molto più veloce, dal punto di vista delle prestazioni.
Franklin P Strube,

2
@FranklinPStrube A meno che non manchi qualcosa, questo ottiene il nome breve della classe corrente, piuttosto che la classe dell'oggetto. Sono d'accordo che l'uso della riflessione di solito significa che lo stai facendo male.
lunedì

1
Molte persone usano Reflections per le sostituzioni di visibilità dei membri, che è MALE. Non farlo! Ma affermare che l'uso di Reflections in generale è Voodoo e Doing It Wrong dà alla gente un'impressione sbagliata. Non dovresti evitarli, dovresti capirli e sapere quando sono benefici e a quale livello di astrazione.
Vanja D.

131

(new \ReflectionClass($obj))->getShortName(); è la migliore soluzione per quanto riguarda le prestazioni.

Ero curioso di sapere quale delle soluzioni fornite è la più veloce, quindi ho messo insieme un piccolo test.

risultati

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

Codice

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";

I risultati mi hanno davvero sorpreso. Pensavo che la soluzione dell'esplosione sarebbe stata la strada più veloce per andare ...


1
Bella risposta. Stavo eseguendo lo stesso codice ma ho ottenuto un risultato diverso (Macbook Pro i7, 16 GB di RAM). Riflessione: 0.382, Nome base: 0.380, Esplode: 0.399. Penso che dipenda dal tuo sistema ciò che è meglio ...
Tobias Nyholm,

4
Esegui PHP 10.000 volte con quel codice e otterrai un risultato migliore. Quanto sopra potrebbe recuperare il riflesso da qualche pool, ma questo non è il solito comportamento delle applicazioni là fuori. Ne hanno bisogno solo una o due volte.
LeMike,

6
Mi chiedo se questo test sia vero quando si crea un'istanza di una ReflectionClass su un oggetto più sostanziale rispetto al piccolo oggetto di classe A nel test ...
Joe Green

2
eseguendo una sola iterazione invece di 100000 si ottiene un risultato molto diverso: Riflessione: 1.0967254638672 100000th / s ClassA Basename: 0.81062316894531 100000th / s ClassA Explode: 0.50067901611328 100000th / s ClassA
mcmurphy

1
explode ('\\', static :: class) [0]? non restituisce la prima parte dello spazio dei nomi? dovrebbe restituire l'ultima parte, non la prima
2

86

Ho aggiunto substr al test di https://stackoverflow.com/a/25472778/2386943 e questo è il modo più veloce che ho potuto testare (CentOS PHP 5.3.3, Ubuntu PHP 5.5.9) entrambi con un i5.

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

risultati

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

Codice

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";

== AGGIORNAMENTO ==

Come menzionato nei commenti di @MrBandersnatch c'è anche un modo più veloce per farlo:

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

Ecco i risultati dei test aggiornati con "SubstringStrChr" (risparmia fino a circa 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

5
Solo perché abbiamo elencato per efficienza ho scoperto che questo è il più veloce, confronto dal test fornito in questo substr della soluzione (strrchr (get_class ($ obj), '\\'), 1); Riflessione: 0.084223914146423 s ClassA - Nome base: 0.13206427097321 s ClassA - Esplode: 0.15331919193268 s ClassA - Sottostringa: 0.068068099021912 s ClassA - Strrchar: 0.06472008228302 s ClassA -
ctatro85

Mi sono appena imbattuto in questo thread e ho aggiunto un benchmark aggiuntivo per testare str_replace(__NAMESPACE__ . '\\', '', __CLASS__);. I risultati su una macchina virtuale debole hanno mostrato che è quasi due volte più veloce di tutti questi. 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 hai ragione. Ho testato la tua soluzione e mi ha risparmiato circa 0,001 s. Ho aggiornato la mia risposta con la tua!
MaBi,

3
Attenzione: questo codice non funziona con le classi nello spazio dei nomi globale (ovvero: il loro nome completo è uguale al loro nome breve)! Io consiglio a prova di qualcosa come: if ($pos = strrchr(static::class, '\\')) { .. } else { ... }.
Tristan Jahier,

1
Per farlo funzionare anche nello spazio dei nomi globale, basta anteporre il nome della classe con una barra rovesciata :) - ovvero:$classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
rosell.dk

25

Ecco un modo più semplice per farlo se stai usando il framework Laravel PHP:

<?php

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

// usage inside a class
// returns HelloWorld
$name = class_basename(__CLASS__);

8
Questa non è una funzione PHP integrata, sembra una funzione di supporto fornita da laravel.
Steve Buzonas,

6
Penso che l'abbia detto
Scott,

4
Grazie, sto usando Laravel e questa risposta mi ha fatto risparmiare un sacco di tempo.
Jeremy Wadhams,


18

Io lo uso questo:

basename(str_replace('\\', '/', get_class($object)));

Puoi anche provare: $ className = explode ('\\', basename (get_class ($ this))); $ className = array_pop ($ className); per ottenere il semplice nome di classe. Oppure usa substr.
dompie,

13
Funziona solo su Windows Su Windows, sia la barra (/) che la barra rovesciata () vengono utilizzate come carattere di separazione directory. In altri ambienti, è la barra (/) php.net/manual/en/function.basename.php
OzzyCzech

L'ho risolto ora. Grazie, @OzzyCzech.
Theodore R. Smith,

1
@OzzyCzech Mi sono appena imbattuto in questo mentre mi spostavo da Windows a Ubuntu .... esasperante. Completati con la soluzione menzionata nell'aggiornamento di MaBi.
Chris Baker,

@OzzyCzech Come funziona funziona solo su Windows? la domanda riguardava il nome dello spazio dei nomi completo se non sbaglio anche anni fa, e gli spazi dei nomi non sono specifici del sistema operativo e sempre con una barra rovesciata come il separatore di directory di Windows.
FantomX1

16

Per ottenere il nome breve come one-liner (dal PHP 5.4 ):

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

È un approccio pulito e abbastanza veloce .


1
Mi chiedo come si paragona a un'estrazione di stringhe nei benchmark. Sembra che questo sarebbe molto più lento.
Contatto non verificato

12

Mi sono trovato in una situazione unica in cui instanceofnon potevo essere usato (in particolare tratti spaziali) e avevo bisogno del nome breve nel modo più efficiente possibile, quindi ho fatto un piccolo punto di riferimento. Include tutti i diversi metodi e variazioni dalle risposte a questa domanda.

$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());

Un elenco di tutto il risultato è qui ma ecco i punti salienti:

  • Se avete intenzione di utilizzare la riflessione in ogni modo, utilizzando $obj->getShortName()sia il metodo più veloce però ; usando la riflessione solo per ottenere il nome breve è quasi il metodo più lento.
  • 'strrpos'può restituire un valore errato se l'oggetto non si trova in uno spazio dei nomi, quindi mentre 'safe strrpos'è un po 'più lento direi che questo è il vincitore.
  • Per rendere 'basename'compatibile tra Linux e Windows devi usare ciò str_replace()che rende questo metodo il più lento di tutti.

Una tabella di risultati semplificata, la velocità viene misurata rispetto al metodo più 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%  |
+-----------------+--------+

8

È possibile utilizzare explodeper separare lo spazio dei nomi e endper ottenere il nome della classe:

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

7

Yii way

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

Yii utilizza questo metodo nel suo generatore di codice Gii

Documentazione del metodo

Questo metodo è simile alla funzione php basename () tranne per il fatto che tratterà entrambi \ e / come separatori di directory, indipendentemente dal sistema operativo. Questo metodo è stato creato principalmente per funzionare su spazi dei nomi php. Quando lavori con percorsi di file reali, il basename di php () dovrebbe funzionare bene per te. Nota: questo metodo non è a conoscenza del file system attuale o dei componenti del percorso come "..".

Maggiori informazioni:

https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseStringHelper.php http://www.yiiframework.com/doc-2.0/yii-helpers-basestringhelper.html#basename()-detail


Benvenuto in Stack Overflow. Fornisci ulteriori informazioni per la tua risposta. Cosa fa questo e come si può usare.
Jens,

1
Questo ha funzionato per me su Windows ma non su Linux, forse perché gli spazi dei nomi sono in una forma di barre rovesciate delle directory di Windows "\", mentre il nome di base di Linux considera i separatori di directory in avanti delle barre "/". Quindi ho lavorato con strtr. ' basename (strtr ($ class, '\\', '/'))
FantomX1

6

Ecco una soluzione semplice per 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()));
        }
    }
}

Quale sarà il ritorno?

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
}

Il nome della classe estesa e lo spazio dei nomi funzionano bene per:

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
}

Che dire della classe nello spazio dei nomi globale?

namespace {

    class ClassWithoutNamespace {
        use \Names;
    }

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

3

Se devi conoscere il nome della classe che è stato chiamato all'interno di una classe e non vuoi lo spazio dei nomi, puoi usare questo

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

Questo è fantastico quando hai un metodo all'interno di una classe che è esteso da altre classi. Inoltre, questo funziona anche se gli spazi dei nomi non vengono utilizzati affatto.

Esempio:

<?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)

2

Sulla base della risposta di @MaBi, ho fatto questo:

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

Che puoi usare così:

namespace Foo\Bar\Baz;

class A
{
    use ClassShortNameTrait;
}

A::classritorna Foo\Bar\Baz\A, ma A::getClassShortName()ritorna A.

Funziona con PHP> = 5.5.


2

So che questo è un vecchio post, ma questo è quello che uso: più veloce di tutti quelli pubblicati sopra, chiamo questo metodo dalla tua classe, molto più velocemente dell'uso di Reflection

namespace Foo\Bar\Baz;

class Test {
    public function getClass() {
        return str_replace(__NAMESPACE__.'\\', '', static::class);
    }
}

Sfortunatamente questo funziona solo se lo chiami nella classe di cui vuoi il nome, non su qualsiasi nome di classe come stringa.
Jurchiks

1

Trovato nella pagina della documentazione di get_class , dove è stato pubblicato da me su 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];
}

Ma l'idea degli spazi dei nomi è strutturare il tuo codice. Ciò significa anche che puoi avere classi con lo stesso nome in più spazi dei nomi. Quindi teoricamente, l'oggetto che passi potrebbe avere il nome della classe (stripped), pur essendo un oggetto totalmente diverso da quello che ti aspetti.

Oltre a ciò, potresti voler verificare una specifica classe base , nel qual caso get_classnon funziona affatto. Potresti voler controllare l'operatore instanceof.


1

È possibile ottenere un risultato imprevisto quando la classe non ha uno spazio dei nomi. Cioè get_classritorna Foo, quindi $baseClasssarebbe oo.

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

Questo può essere facilmente risolto con il prefisso get_classcon una barra rovesciata:

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

Ora anche le classi senza spazio dei nomi restituiranno il valore corretto.


1

Un buon vecchio regex sembra essere più veloce della maggior parte dei metodi mostrati in precedenza:

// both of the below calls will output: ShortClassName

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

Quindi funziona anche quando si fornisce un nome di classe breve o un nome di classe (canonico) completo.

Quello che fa la regex è che consuma tutti i caratteri precedenti fino a quando non viene trovato l'ultimo separatore (che viene anche consumato). Quindi la stringa rimanente sarà il nome della classe breve.

Se si desidera utilizzare un separatore diverso (ad es. /), Utilizzare semplicemente quel separatore. Ricordare di sfuggire alla barra rovesciata (ad es. \) E anche al carattere del carattere (ad es. /) Nel motivo di input.


1

Perché "ReflectionClass" può dipendere dalla versione basta usare il seguente:

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

o addirittura chiaro

if(class_basename(ClassName::class) == 'ClassName') {
... do this ...
}

0

Citando php.net:

Su Windows, sia la barra (/) che la barra rovesciata () vengono utilizzate come carattere di separazione directory. In altri ambienti, è la barra (/).

Sulla base di queste informazioni e l'espansione dalla risposta arzzzen dovrebbe funzionare su entrambi i sistemi Windows e Nix *:

<?php

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

Nota: ho fatto un benchmark di ReflectionClasscontro basename+str_replace+get_classe l'utilizzo di reflection è circa il 20% più veloce rispetto all'uso dell'approccio basename, ma YMMV.


0

La soluzione più semplice e veloce che funziona in qualsiasi ambiente è:

<?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"

?>

1
Questo è il motivo per cui vorrei che PHP avesse operatori di informazioni di classe interne. Creare un'istanza di un riflettore esterno per fare ciò che dovrebbe essere tanto semplice da $Object->__class->getShortName()farmi davvero incazzare con PHP. Il tuo approccio funziona, ma ora stai mettendo metodi concreti nelle tue classi solo per esporre quello che dovrebbe essere un costrutto linguistico.
AgmLauncher,

PHP senza funzioni “concrete” (o dovremmo chiamarle procedurali) è impossibile. Aspettiamo PHP 6 (beh, se mai arriva).
Fleshgrinder

0
$shortClassName = join('',array_slice(explode('\\', $longClassName), -1));

0

Se stai solo spogliando gli spazi dei nomi e vuoi qualcosa dopo l'ultimo \ in un nome di classe con spazio dei nomi (o solo il nome se non c'è '\') puoi fare qualcosa del genere:

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

Fondamentalmente è regex ottenere una qualsiasi combinazione di caratteri o barre rovesciate e fino all'ultima barra rovesciata quindi restituire solo i caratteri non barra rovesciata e fino alla fine della stringa. Aggiunta del? dopo il primo raggruppamento significa che se la corrispondenza del modello non esiste, restituisce solo la stringa completa.


0

Il più veloce che ho trovato qui per PHP 7.2ilUbubntu 18.04

preg_replace('/^(\w+\\\)*/', '', static::class)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.