मुझे किसी वस्तु का अयोग्य (संक्षिप्त) वर्ग नाम कैसे मिलेगा?


153

मैं पूर्ण नाम स्थान वर्ग निर्दिष्ट किए बिना PHP नाम स्थान वाले वातावरण के भीतर किसी वस्तु के वर्ग की जांच कैसे करूं।

उदाहरण के लिए मान लीजिए कि मेरे पास एक वस्तु पुस्तकालय / इकाई / अनुबंध / नाम था।

निम्न कोड काम नहीं करता है क्योंकि get_class पूरा नामांकित वर्ग देता है।

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

नेमस्पेस मैजिक कीवर्ड वर्तमान नामस्थान को लौटाता है, जिसका कोई और उपयोग नहीं है यदि परीक्षण किए गए ऑब्जेक्ट में कोई अन्य नामस्थान है।

मैं केवल नामस्थान के साथ पूर्ण वर्गनाम निर्दिष्ट कर सकता हूं, लेकिन यह कोड की संरचना में लॉक लगता है। इसके अलावा, अगर मैं नाम स्थान को गतिशील रूप से बदलना चाहता हूं तो बहुत अधिक उपयोग का नहीं।

क्या कोई ऐसा करने का कुशल तरीका सोच सकता है। मुझे लगता है कि एक विकल्प रेगेक्स है।


यह व्यर्थ के निकट लगता है क्योंकि विभिन्न नामस्थानों में समान श्रेणी के नाम उनके अंदर परिभाषित हो सकते हैं, इसलिए आप इसे कैसे संभालेंगे? और ऐसा इसलिए है क्योंकि आपके नमूने में पूर्ण योग्य वर्ग नाम लौटाया गया है
अल्मा दो

मैं एक मोबाइल डिवाइस पर हूँ, इसलिए मैं एक सभ्य जवाब नहीं भेज पाते हैं, लेकिन समाधान प्रतिबिंब, विशेष रूप से ReflectionClass :: getShortName है - php.net/manual/en/reflectionclass.getshortname.php
lonesomeday

ऐसा करने के लिए एक कारण की तलाश में लोगों के लिए: यह एक सामान्य आधार वर्ग (यानी कई नामस्थान इस स्थिति में एक मुद्दा कभी नहीं है) में एक सहायक समारोह में उपयोगी हो सकता है।
डैरेन कुक

जवाबों:


182

आप इसे प्रतिबिंब के साथ कर सकते हैं। विशेष रूप से, आप उस ReflectionClass::getShortNameविधि का उपयोग कर सकते हैं , जिसे इसके नाम स्थान के बिना वर्ग का नाम मिलता है।

सबसे पहले, आपको एक ReflectionClassउदाहरण बनाने की आवश्यकता है , और फिर getShortNameउस उदाहरण की विधि को कॉल करें :

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

हालाँकि, मैं कई परिस्थितियों की कल्पना नहीं कर सकता जहाँ यह वांछनीय होगा। यदि आप यह चाहते हैं कि ऑब्जेक्ट एक निश्चित वर्ग का सदस्य है, तो यह परीक्षण करने का तरीका है instanceof। यदि आप कुछ बाधाओं को इंगित करने के लिए अधिक लचीला तरीका चाहते हैं, तो ऐसा करने का तरीका एक इंटरफ़ेस लिखना है और इसके लिए कोड को उस इंटरफ़ेस को लागू करना होगा। फिर, ऐसा करने का सही तरीका है instanceof। (आप इसके साथ कर सकते हैं ReflectionClass, लेकिन इसका प्रदर्शन बहुत बुरा होगा।)


1
@ ग्रेग.फोर्ब्स क्योंकि Tenantमौजूदा नामस्थान में मौजूद नहीं है। var_dump($tenant instanceof \Library\Entity\People\Tenant)इसके बजाय कोशिश करें । इसके अलावा, जाँच करें कि कैसे useऑपरेटर का उपयोग करें , और PHP नामस्थान के पीछे की सामान्य अवधारणा!
लोन्सोमेडेई

3
मुझे इस तरह से एक स्लैश जोड़ना पड़ा$reflect = new \ReflectionClass($object);
प्रागैमर

7
मैं आम तौर पर अपने आवेदन में बहुत कुछ परावर्तनक्लास वूडू करना पसंद नहीं करता हूं क्योंकि यह गलत परिणाम (यदि सार्वजनिक होने के तरीके संरक्षित) आदि हो तो अप्रत्याशित परिणाम हो सकते हैं। आप इसके बजाय PHP जादू स्थिरांक पर सरल स्ट्रिंग प्रतिस्थापन का उपयोग कर सकते हैं str_replace(__NAMESPACE__ . '\\', '', __CLASS__);:। यह बहुत तेज़ है, प्रदर्शन-वार है।
फ्रैंकलिन पी स्ट्रब

2
@FranklinPStrube जब तक मैं कुछ याद कर रहा हूँ, जो वस्तु के वर्ग के बजाय वर्तमान वर्ग का संक्षिप्त नाम है। मैं मानता हूं कि प्रतिबिंब का उपयोग आमतौर पर आप गलत कर रहे हैं इसका मतलब है।
लोनसोमेदेय

1
बहुत से लोग सदस्य दृश्यता ओवरराइड्स के लिए प्रतिबिंब का उपयोग करते हैं, जो कि बीएडी है। ऐसा मत करो! लेकिन यह दर्शाता है कि सामान्य तौर पर रिफ्लेक्शंस का उपयोग वूडू और डूइंग इट गलत है जो लोगों को गलत धारणा देता है। आपको उनसे बचना नहीं चाहिए, आपको उन्हें समझना चाहिए और पता होना चाहिए कि वे कब लाभकारी हैं और किस स्तर के अमूर्त हैं।
वंजा डी।

131

(new \ReflectionClass($obj))->getShortName(); प्रदर्शन के संबंध में सबसे अच्छा समाधान है।

मैं उत्सुक था कि प्रदान किए गए समाधानों में से कौन सा सबसे तेज़ है, इसलिए मैंने एक साथ थोड़ा परीक्षण किया है।

परिणाम

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

कोड

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

परिणामों ने वास्तव में मुझे चौंका दिया। मैंने सोचा था कि विस्फोट समाधान सबसे तेज़ रास्ता होगा ...


1
बहुत बढ़िया जवाब। मैं एक ही कोड चला रहा था लेकिन मुझे एक अलग परिणाम मिला (मैकबुक प्रो i7, 16 जीबी रैम)। परावर्तन: 0.382, बेसनैम: 0.380, विस्फोट: 0.399। मुझे लगता है कि यह आपके सिस्टम पर निर्भर करता है कि क्या सबसे अच्छा है ...
टोबियास न्योरहोम

4
उस कोड के साथ PHP 10 000 बार चलाएं और आपको बेहतर परिणाम मिले। ऊपर कुछ पूल से प्रतिबिंब ला सकता है, लेकिन यह वहाँ के अनुप्रयोगों का सामान्य व्यवहार नहीं है। उन्हें केवल एक या दो बार इसकी आवश्यकता होती है।
लेमीक

6
मुझे आश्चर्य है कि जब आपके परीक्षण में कक्षा ए की छोटी वस्तु की तुलना में अधिक ठोस वस्तु पर एक ReflectionClass पर तत्काल प्रभाव डालने पर यह परीक्षण सही होता है ...
जो ग्रीन

2
100000 के बजाय सिर्फ एक चलना चलने से बहुत अलग परिणाम मिलता है: परावर्तन: 1.0967254638672 100000 वां / एस क्लासए बेसनैम: 0.81062316894531 100000 वां / एस क्लासए एक्सप्लोड: 0.6767901611328 100000 वां /
वर्गवार

1
विस्फोट ('\\', स्थिर :: वर्ग) [0]? क्या यह नामस्थान के पहले भाग को वापस नहीं करता है? अंतिम भाग पर लौटना चाहिए, पहले नहीं
ओपिन

86

मैंने https://stackoverflow.com/a/25472778/2386943 के परीक्षण में सामग्री जोड़ी और यह सबसे तेज़ तरीका है जिससे मैं एक i5 के साथ दोनों (CentOS PHP 5.3.3, Ubuntu PHP 5.5.9) का परीक्षण कर सकता हूं।

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

परिणाम

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

कोड

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

== अद्यतन ==

जैसा कि @MrBandersnatch द्वारा टिप्पणियों में उल्लेख किया गया है, ऐसा करने का एक तेज़ तरीका भी है:

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

यहां "सबस्ट्रिंगस्ट्रक" के साथ अपडेट किए गए परीक्षा परिणाम हैं (लगभग 0.001 सेकेंड तक बचाता है):

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
सिर्फ इसलिए कि हम दक्षता के लिए लिस्टिंग करते हैं मैंने इसे सबसे तेज पाया, इस समाधान पदार्थ (स्ट्रच्र (get_class ($ obj), '\\')), 1) में प्रदान किए गए परीक्षण से तुलना; चिंतन: .084223914146423 रों ClassA - बेसनाम: .13206427097321 रों ClassA - विस्फोट: .15331919193268 रों ClassA - सबस्ट्रिंग: .068068099021912 रों ClassA - Strrchar: .06472008228302 रों ClassA -
ctatro85

मैं बस इस धागे के पार आया और परीक्षण के लिए एक अतिरिक्त बेंचमार्क जोड़ा str_replace(__NAMESPACE__ . '\\', '', __CLASS__);। एक कमजोर वर्चुअल मशीन के परिणामों ने दिखाया कि यह इन सभी के मुकाबले लगभग दोगुना है। 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
फ्रैंकलिन पी स्ट्राबे

1
@MrBandersnatch आप सही हैं। मैंने आपके समाधान का परीक्षण किया और इसने मुझे लगभग 0.001 सेकेंड बचाया। मैंने अपना जवाब आपके साथ अपडेट किया है!
माबी

3
चेतावनी: यह कोड वैश्विक नामस्थान में कक्षाओं के साथ काम नहीं करता है (यानी: उनका पूरा नाम उनके संक्षिप्त नाम के बराबर है)! मुझे सलाह है कि जैसे कुछ परीक्षण करें if ($pos = strrchr(static::class, '\\')) { .. } else { ... }:।
ट्रिस्टन जहीर

1
इसे ग्लोबल नेमस्पेस में भी काम करने के लिए, बस $classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
क्लासनेम को

25

यदि आप 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
यह बिलियन php फंक्शन नहीं है, यह लार्वा द्वारा प्रदान किए गए एक हेल्पर फंक्शन जैसा दिखता है।
स्टीव बुज़ोनास 1

6
मुझे लगता है कि उन्होंने कहा कि
स्कॉट

4
धन्यवाद, मैं लारवेल का उपयोग कर रहा हूं और इस उत्तर ने मुझे समय का एक समूह बचा लिया।
जेरेमी वाधम्स


18

मैं इसका उपयोग करता हूं:

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

आप यह भी कोशिश कर सकते हैं: $ className = विस्फोट ('\\', basename (get_class ($ यह)))); $ className = array_pop ($ className); सादे वर्गनाम पाने के लिए। या रूट का उपयोग करें।
डॉमेस्टी

13
केवल विंडोज पर विंडोज पर काम करता है, दोनों स्लैश (/) और बैकस्लैश () का उपयोग निर्देशिका विभाजक चरित्र के रूप में किया जाता है। अन्य वातावरणों में, यह फॉरवर्ड स्लैश (/) php.net/manual/en/function.basename.php
OzzyCeshop

मैंने इसे अब ठीक कर दिया है। धन्यवाद, @ ऑज़ीकॉच।
थियोडोर आर। स्मिथ

1
@OzzyCeshop मैं विंडोज से उबंटू की ओर बढ़ते समय बस इसमें भाग गया .... पागल। MaBi के अपडेट में उल्लिखित समाधान का उपयोग करके जख्म।
क्रिस बेकर

@OzzyCgate केवल विंडोज पर कैसे काम करता है? सवाल पूरी तरह से योग्य नाम स्थान के नाम के बारे में था अगर मैं वर्षों पहले भी गलत नहीं हूं, और नाम स्थान ओएस विशिष्ट नहीं हैं, और हमेशा विंडोज निर्देशिका विभाजक की तरह बैकस्लैश के साथ।
फनटोमएक्स

16

एक-लाइनर के रूप में संक्षिप्त नाम प्राप्त करने के लिए ( PHP 5.4 के बाद से ):

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

यह एक स्वच्छ दृष्टिकोण और उचित उपवास है


1
मुझे आश्चर्य है कि यह कैसे बेंचमार्क में एक स्ट्रिंग निष्कर्षण के खिलाफ तुलना करता है। ऐसा लगता है कि यह बहुत धीमा होगा।
अघोषित संपर्क

12

मैंने खुद को एक अनोखी स्थिति में पाया, जहां instanceofइस्तेमाल नहीं किया जा सकता था (विशेष रूप से नामांकित लक्षण) और मुझे सबसे कुशल तरीके से संक्षिप्त नाम की आवश्यकता थी इसलिए मैंने अपना खुद का एक छोटा बेंचमार्क किया है। इसमें इस प्रश्न के उत्तर से सभी विभिन्न विधियां और विविधताएं शामिल हैं।

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

संपूर्ण परिणाम की एक सूची यहां है, लेकिन यहां पर प्रकाश डाला गया है:

  • अगर आप वैसे भी उपयोग प्रतिबिंब लिए जा रहे हैं, का उपयोग करते हुए $obj->getShortName()सबसे तेज तरीका है लेकिन ; केवल संक्षिप्त नाम प्राप्त करने के लिए प्रतिबिंब का उपयोग करना लगभग सबसे धीमा तरीका है।
  • 'strrpos'यदि कोई नेमस्पेस में नहीं है तो एक गलत मान लौटा सकता है, जबकि 'safe strrpos'एक छोटा सा धीमा है, मैं कहूंगा कि यह विजेता है।
  • 'basename'लिनक्स और विंडोज के बीच सुसंगत बनाने के लिए आपको उपयोग करने की आवश्यकता है str_replace()जो इस पद्धति को उन सभी में सबसे धीमा बनाता है।

परिणामों की एक सरल तालिका, गति को सबसे धीमी विधि की तुलना में मापा जाता है:

+-----------------+--------+
| 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

आप explodeनाम स्थान को अलग करने और endवर्ग नाम प्राप्त करने के लिए उपयोग कर सकते हैं :

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

7

Yii रास्ता

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

Yii अपने Gii कोड जनरेटर में इस पद्धति का उपयोग करता है

विधि प्रलेखन

यह विधि php फंक्शन बेसनेम () के समान है, सिवाय इसके कि यह ऑपरेटिंग सिस्टम से स्वतंत्र दोनों और / जैसे डायरेक्टरी सेपरेटर का इलाज करेगा। यह विधि मुख्य रूप से php नाम स्थान पर काम करने के लिए बनाई गई थी। वास्तविक फ़ाइल पथों के साथ काम करते समय, php के बेसनेम () को आपके लिए ठीक काम करना चाहिए। नोट: यह विधि वास्तविक फाइल सिस्टम, या पथ घटकों जैसे ".." से अवगत नहीं है।

अधिक जानकारी:

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


ढेर अतिप्रवाह में आपका स्वागत है। कृपया अपने उत्तर के लिए अधिक जानकारी प्रदान करें। यह क्या करता है और इसका उपयोग कैसे किया जा सकता है।
जेन्स

1
यह मेरे लिए विंडोज पर काम करता था लेकिन लिनक्स पर नहीं, शायद इसलिए कि नाम स्थान विंडोज निर्देशिका बैकस्लैश '\' के रूप में हैं, जबकि लिनक्स बेसन ने निर्देशिका विभाजकों को आगे की स्लैश '/' माना है। इसलिए मैंने इसे स्ट्रेट के साथ काम किया। ' बेसन (स्ट्रेट ($ वर्ग, '\\', '/'))
फनटोमएक्स

6

यहाँ 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()));
        }
    }
}

क्या होगा रिटर्न?

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
}

विस्तारित वर्ग का नाम और नाम स्थान अच्छी तरह से काम करता है:

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
}

वैश्विक नाम स्थान में वर्ग के बारे में क्या?

namespace {

    class ClassWithoutNamespace {
        use \Names;
    }

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

3

यदि आपको उस वर्ग के नाम को जानने की आवश्यकता है जिसे किसी कक्षा के अंदर से बुलाया गया था, और नाम स्थान नहीं चाहते हैं, तो आप इस का उपयोग कर सकते हैं

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

यह महान है जब आपके पास एक वर्ग के अंदर एक विधि होती है जो अन्य वर्गों द्वारा विस्तारित होती है। इसके अलावा, यह भी काम करता है अगर नाम स्थान का उपयोग नहीं किया जाता है।

उदाहरण:

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

@MaBi के उत्तर के आधार पर, मैंने इसे बनाया:

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

जो आप इस तरह का उपयोग कर सकते हैं:

namespace Foo\Bar\Baz;

class A
{
    use ClassShortNameTrait;
}

A::classलौटता है Foo\Bar\Baz\A, लेकिन A::getClassShortName()लौटता हैA

PHP> = 5.5 के लिए काम करता है।


2

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन यह वही है जो मैं उपयोग करता हूं - ऊपर पोस्ट किए गए सभी से तेज़, बस अपनी कक्षा से इस पद्धति को कॉल करें, प्रतिबिंब का उपयोग करने की तुलना में बहुत तेज

namespace Foo\Bar\Baz;

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

दुर्भाग्य से यह केवल तभी काम करता है जब आप इसे उस कक्षा में बुला रहे हों जिसका नाम आप चाहते हैं, न कि केवल किसी वर्ग के नाम पर एक स्ट्रिंग के रूप में।
जर्किक्स

1

Get_class के डॉक्यूमेंटेशन पेज पर मिला , जहाँ यह मेरे द्वारा nwhiting डॉट कॉम पर पोस्ट किया गया था ।

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];
}

लेकिन नाम स्थान का विचार आपके कोड को संरचना देना है। इसका मतलब यह भी है कि आपके पास कई नामस्थानों में समान नाम वाली कक्षाएं हो सकती हैं। इसलिए सैद्धांतिक रूप से, आपके द्वारा पास की गई वस्तु का नाम (छीन लिया गया) वर्ग नाम हो सकता है, जबकि अभी भी आपकी अपेक्षा से बिलकुल अलग वस्तु है।

इसके अलावा, आप एक विशिष्ट आधार वर्ग की जांच करना चाहते हैं , जिस स्थिति में get_classयह चाल बिल्कुल नहीं चलेगी। आप ऑपरेटर की जांच कर सकते हैं instanceof


1

जब क्लास में नेमस्पेस नहीं होता है तो आपको एक अप्रत्याशित परिणाम मिल सकता है। यानी get_classरिटर्न Foo, तब $baseClassहोगा oo

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

इसे आसानी से get_classबैकस्लैश के साथ जोड़कर तय किया जा सकता है :

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

अब बिना नाम के वर्ग भी सही मान लौटाएगा।


1

एक अच्छा पुराना रेगेक्स पिछले दिखाए गए तरीकों की तुलना में अधिक तेज़ लगता है:

// both of the below calls will output: ShortClassName

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

इसलिए यह तब भी काम करता है जब आप एक छोटे वर्ग का नाम या पूरी तरह से योग्य (विहित) वर्ग नाम प्रदान करते हैं।

रेगेक्स क्या करता है कि यह पिछले विभाजक पाए जाने तक (जो भी भस्म होता है) सभी पिछले चार्ट का उपभोग करता है। तो शेष स्ट्रिंग शॉर्ट क्लास नाम होगा।

यदि आप एक अलग विभाजक (जैसे। /) का उपयोग करना चाहते हैं, तो इसके बजाय बस उस विभाजक का उपयोग करें। याद रखें कि इनपुट पैटर्न में बैकस्लैश (यानी। \) और पैटर्न चार (यानी। /) से बचकर रहें।


1

क्योंकि "ReflectionClass" संस्करण पर निर्भर हो सकता है, बस अनुसरण का उपयोग करें:

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

या यहां तक ​​कि स्पष्ट है

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

0

उद्धरण उद्धृत करना:

विंडोज पर, स्लैश (/) और बैकस्लैश () दोनों का उपयोग डायरेक्टरी सेपरेटर कैरेक्टर के रूप में किया जाता है। अन्य वातावरणों में, यह फॉरवर्ड स्लैश (/) है।

इस जानकारी के आधार पर और arzzzen जवाब से विस्तार करने पर यह विंडोज और निक्स दोनों सिस्टम पर काम करना चाहिए:

<?php

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

नोट: मैंने ReflectionClassविरोध किया basename+str_replace+get_classऔर प्रतिबिंब का उपयोग करने का आधार बेसन दृष्टिकोण का उपयोग करने की तुलना में लगभग 20% तेज है, लेकिन YMMV।


0

किसी भी वातावरण में काम करने वाला सबसे तेज़ और imho सबसे आसान समाधान है:

<?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
यही कारण है कि मैं चाहता हूं कि PHP में आंतरिक वर्ग के जानकारी ऑपरेटर थे। बाहरी परावर्तक को करने के लिए जो सरल होना चाहिए, वह $Object->__class->getShortName()वास्तव में मुझे पीएचपी के बारे में बताता है। आपका दृष्टिकोण काम करता है, लेकिन अब आप अपनी कक्षाओं में ठोस तरीके डाल रहे हैं ताकि यह पता चले कि भाषा का निर्माण क्या होना चाहिए।
AgmLauncher 15:14

"ठोस" के बिना PHP (या हमें उन्हें प्रक्रियात्मक कहना चाहिए) कार्य असंभव है। आइए PHP 6 के लिए प्रतीक्षा करें (ठीक है, अगर यह कभी आता है)।
फ्लेमग्रिंडर


0

यदि आप केवल नाम स्थान छीन रहे हैं और अंतिम नाम के बाद वर्ग नाम के साथ कुछ भी चाहते हैं (या सिर्फ नाम यदि कोई '\' नहीं है) तो आप ऐसा कुछ कर सकते हैं:

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

मूल रूप से यह वर्णों या बैकस्लैश के किसी भी संयोजन को प्राप्त करने के लिए regex है और अंतिम बैकस्लैश तक केवल गैर-बैकस्लैश वर्णों को वापस करने और स्ट्रिंग के अंत तक वापस आने के लिए। जोड़ना? पहले ग्रुपिंग के बाद यदि पैटर्न मैच मौजूद नहीं है, तो यह पूर्ण स्ट्रिंग लौटाता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.