2010-02-23 15 views
25

में सुपर क्लास से बच्चे कक्षा नाम स्थान प्राप्त मान लिया जाये कि मैं अलग फ़ाइलों में निम्नलिखित वर्गों की है।पीएचपी

क्या इस विधि को फिर से शुरू किए बिना बाल वर्ग से वर्तमान नामस्थान प्राप्त करने का कोई तरीका है?

मैंने प्रत्येक वर्ग में एक स्थिर $ नामस्थान चर बनाने और super::$namespace का उपयोग करके इसका संदर्भ देने का सहारा लिया है, लेकिन यह बहुत ही सुरुचिपूर्ण महसूस नहीं करता है।

+0

विशेष रूप से आप के लिए नहीं कहा हालांकि यह भी 'namespace' कीवर्ड में रुचि हो सकती, http://doc.php.net/language.namespaces.nsconstants उदा 'echo नेमस्पेस \ MyClass :: myFunction();' – VolkerK

+0

धन्यवाद, मुझे इसके बारे में पता है लेकिन दुर्भाग्य से यह इस स्थिति में काम नहीं करता है! :) –

उत्तर

19

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

एक विकल्प के रूप में, आप एक वर्ग के नाम स्थान नाम पाने के लिए प्रतिबिंब का उपयोग कर सकते हैं:

$reflector = new ReflectionClass('A\\Foo'); // class Foo of namespace A 
var_dump($reflector->getNamespaceName()); 

अधिक (अधूरा) प्रलेखन के लिए the PHP manual देखें। ध्यान दें कि प्रतिबिंब का उपयोग करने के लिए आपको PHP 5.3.0 या बाद में होना आवश्यक होगा।

+0

धन्यवाद, यह समझ में आता है, मैं यहां प्रतिबिंब का उपयोग करके पूरी तरह अनदेखा कर रहा हूं! –

+0

बहुत उपयोगी। धन्यवाद ! – Caio

12

आप भी अपनी getNamespace में ऐसा कर सकते हैं() विधि:

return get_class($this); 

जब childclass से कहा जाता है, परिणाम होगा:

MyNS\SubNS\childclass 

आप वर्ग के नाम पर नहीं करना चाहते हैं अंत, आखिरी \ से अंत तक सब कुछ काट लें।

4

मेरे मामले में, मुझे मूल वर्ग में एक विधि बनाने की आवश्यकता है, जो कुछ सबक्लास में call_user_func() के साथ स्थिर विधि को कॉल कर सकता है। यदि आप पूर्ण श्रेणी के नाम को जानते हैं, तो आप call_user_func() कोई समस्या नहीं कर सकते हैं। चाल उपclass 'नामस्थान में एक स्थिर विधि कॉल करने के लिए था।

तो हम अर्थात

\MyTools\AbstractParent 
\Something\Else\Foo extends \MyTools\AbstractParent 
\Something\Else\Bar extends \MyTools\AbstractParent 

अब हम AbstractParent में एक विधि की जरूरत है। उप-वर्ग Foo से यह विधि Bar::doMe() को अपना नामस्थान तैयार करके कॉल करने में सक्षम होगी।

namespace MyTools; 
abstract class AbstractParent { 
    public static method doMe(){} 

    public function callSomethingStaticInClass($class){ 
     // current namespace IS NOT MyTools 
     // so you cannot use __NAMESPACE__ 
     $currentClass = get_class($this); 
     $refl = new ReflectionClass($currentClass); 
     $namespace = $refl->getNamespaceName(); 

     // now we know what the subclass namespace is... 
     // so we prefix the short class name 
     $class = $namespace . '\\' . $class; 
     $method = 'doMe'; 

     return call_user_func(array($class, $method)); 
    } 

}; 

namespace Something\Else; 
class Foo extends AbstractParent { } 
class Bar extends AbstractParent { } 

$foo = new Foo(); 
$foo->callSomethingStaticInClass('Bar'); 

तो वह एक स्थिर कॉल के साथ काम के साथ get_called_class()

+0

यह जवाब होना चाहिए। – Tek

1

आशा इस मदद करता है get_class($this) की जगह बनाने के लिए:

यहाँ कैसे आप इसे गतिशील कॉल के साथ क्या है।

/* First Namespace */ 
namespace MyNS { 
    class superclass { 
     /* Functions to get the current namespace 
     * If $object is null then return the 
     * namespace of the class where the 
     * method exists, if not null, return 
     * the namespace of the class called. 
     */ 
     public static function get_namespace($object = null) { 
      if($object !== null) { 
       $tmp = (($object != "self") && (get_called_class() != get_class($object))) ? get_class($object) : get_called_class(); 
       $tmparr = explode("\\", $tmp); 
       $class = array_pop($tmparr); 
       return join("\\", $tmparr); 
      } else { 
       return __NAMESPACE__; 
      } 
     } 
     public static function get_current_namespace() { 
      return self::get_namespace(self); 
     } 

     public function call_static_method($class_name, $method_name, $arguments = array()) { 
      $class = "\\" . $this->get_namespace($this) . "\\{$class_name}"; 
      if(method_exists($class, $method_name)) { 
       if(count($arguments) > 0) return $class::$method_name($arguments); 
       return $class::$method_name(); 
      } 
      return "Method ({$method_name}) Does not exist in class ({$class})"; 
     } 

     public function call_user_method($object, $method_name, $arguments = array()) { 
      if(method_exists($object, $method_name)) { 
       if(count($arguments) > 0) return $object->$method_name($arguments); 
       return $object->$method_name(); 
      } 
     } 
    } 

    class superclass2 extends superclass { 
     public static function foo() { 
      return "superclass2 foo"; 
     } 
     public function bar() { 
      return "superclass2 bar"; 
     } 
    } 
} 

/* Second Namespace */ 
namespace MyNS\SubNS { 
    class childclass extends \MyNS\superclass { } 

    class childclass2 extends \MyNS\superclass { 
     public static function foo() { 
      return "childclass2 foo"; 
     } 
     public function bar() { 
      return "childclass2 bar"; 
     } 
    } 
} 

/* Back to Root Namespace */ 
namespace { 
    /* Returns 'MyNS' */ 
    echo \MyNS\superclass::get_namespace() . "<br />"; 
    echo \MyNS\SubNS\childclass::get_namespace() . "<br />"; 

    /* Returns 'MyNS' */ 
    echo \MyNS\superclass::get_current_namespace() . "<br />"; 

    /* Returns 'MyNS\SubNS' */ 
    echo \MyNS\SubNS\childclass::get_current_namespace() . "<br />"; 


    /* Or this way */ 


    $super = new \MyNS\superclass(); 
    $child = new \MyNS\SubNS\childclass(); 

    /* Returns 'MyNS' */ 
    echo $super->get_namespace() . "<br />"; 
    echo $child->get_namespace() . "<br />"; 

    /* Returns 'MyNS' */ 
    echo $super->get_namespace($super) . "<br />"; 

    /* Returns 'MyNS\SubNS' */ 
    echo $child->get_namespace($child) . "<br />"; 

    /* Returns 'superclass2 foo' */ 
    echo $super->call_static_method("superclass2", "foo") . "<br />"; 

    /* Returns 'superclass2 bar' */ 
    $super2 = new \MyNS\superclass2(); 
    echo $super->call_user_method($super2, "bar") . "<br />"; 

    /* Returns 'superclass2 foo' */ 
    echo $child->call_static_method("childclass2", "foo") . "<br />"; 

    /* Returns 'superclass2 bar' */ 
    $child2 = new \MyNS\SubNS\childclass2(); 
    echo $child->call_user_method($child2, "bar") . "<br />"; 
} 

Artur Bodera के जवाब में संपादित जोड़ने के लिए कार्यक्षमता 'कॉल'

3

पीएचपी 5.3 के रूप में आप इस लक्ष्य को हासिल करने के लिए get_called_class और कुछ स्ट्रिंग कार्यों का उपयोग कर सकते हैं।

substr(get_called_class(), 0, strrpos(get_called_class(), "\\"))

+0

यह सही और सर्वोत्तम उत्तर है। अधिक सरल नहीं हो सकता है, और यह काम करता है – Andrew

0

आप भी अपने सुपर क्लास में के रूप में एक ही कोड के साथ अपने बच्चे को कक्षा में getNamespace विधि के ऊपर लिख सकते हैं।

फिर, $ --- getNamespace() को अपने सुपरक्लास में किसी अन्य विधि में कॉल करने से ऑब्जेक्ट से संबंधित वर्ग का नामस्थान वापस आ जाएगा।

<?php 
namespace MyNS; 

class superclass { 

    public function getNamespace(){ 
     return __NAMESPACE__; 
    } 

    public function foo() { 
     echo $this->getNamespace(); 
    } 
} 
?> 

<?php 
namespace MyNS\SubNS; 

class childclass extends \MyNS\superclass { 
    public function getNamespace(){ 
     return __NAMESPACE__; 
    } 
} 
?> 

A = new MyNS\superclass(); 
B = new MyNS\subNS\childclass(); 

A->foo() will display "MyNS" 
B->foo() will display "MyNS\SubNS"