2012-07-04 6 views
42

मैं एक ही नाम है कि स्थिर प्रणाली को बुलाती है के साथ एक स्थिर और nonstatic विधि दोनों के रूप में एक वस्तु में एक प्रणाली की घोषणा कर सकते हैं क्या है?पीएचपी - यह संभव एक प्रणाली की घोषणा करने के लिए स्थिर और nonstatic

मैं एक वर्ग एक स्थिर विधि "भेजें" और एक nonstatic विधि स्थिर फ़ंक्शन को कॉल किया है कि बनाना चाहते हैं। उदाहरण के लिए:

class test { 
    private $text; 
    public static function instance() { 
     return new test(); 
    } 

    public function setText($text) { 
     $this->text = $text; 
     return $this; 
    } 

    public function send() { 
     self::send($this->text); 
    } 

    public static function send($text) { 
     // send something 
    } 
} 

मैं इन दोनों पर समारोह कॉल करने के लिए सक्षम होना चाहते हैं

test::send("Hello World!"); 

और

test::instance()->setText("Hello World")->send(); 

यह संभव है किया गया था?

+4

यदि मैं पूछूं तो आप ऐसा क्यों करना चाहेंगे? – PeeHaa

+0

[क्या स्थिर सदस्य नॉनस्टैटिक सदस्यों का उपयोग कर सकते हैं और इसके विपरीत?] (Http://stackoverflow.com/questions/2204128/could-static-members-use-nonstatic-members-and-vice-versa) –

+0

उत्तर कोई btw नहीं है , लेकिन मैं वास्तव में उत्सुक हूं कि आपको ऐसा क्यों लगता है कि आप ऐसा करना चाहते हैं। – PeeHaa

उत्तर

55

आप कर सकते हैं, लेकिन यह थोड़ा मुश्किल है। आपको ओवरलोडिंग के साथ ऐसा करना है: the __call and __callStatic जादू विधियां।

class test { 
    private $text; 
    public static function instance() { 
     return new test(); 
    } 

    public function setText($text) { 
     $this->text = $text; 
     return $this; 
    } 

    public function sendObject() { 
     self::send($this->text); 
    } 

    public static function sendText($text) { 
     // send something 
    } 

    public function __call($name, $arguments) { 
     if ($name === 'send') { 
      call_user_func(array($this, 'sendObject')); 
     } 
    } 

    public function __callStatic($name, $arguments) { 
     if ($name === 'send') { 
      call_user_func(array('test', 'sendText'), $arguments[0]); 
     } 
    } 
} 

यह एक आदर्श समाधान है, क्योंकि यह अपने कोड कठिन पालन करने के लिए बनाता है नहीं है, लेकिन यह काम करेगा, बशर्ते आपके पास पीएचपी> = 5.3।

+24

यह मेरी आंखों को बनाता है b̢̗̫͕l͓̫͈e҉͍̖͙ḙ̣̭̦̫̞͟d̼। मैं इसे कम नहीं करूँगा, क्योंकि आपने उसे चेतावनी दी है कि इस प्रकार की कोडिंग उसके जीवन को कम नहीं करेगी, और यह सहायक है। लेकिन फिर भी: < –

+10

@lonesomeday वोटिंग सिर्फ इसलिए कि आपके पास कोड लिखने का धैर्य है जो कि बहुत अधिक उपयोग नहीं करता है! अभी तक सवाल का जवाब :-) –

+3

@ ट्रुथ हां। यह होना चाहिए "आप यह कर सकते हैं, लेकिन आप *** वास्तव में *** नहीं करना चाहिए।" – lonesomeday

3

नहीं, आपके पास एक ही नाम के साथ दो विधियां नहीं हो सकती हैं। आप तरीकों में से एक का नाम बदलकर मूल रूप से वही काम कर सकते हैं। test::send("Hello World!"); से test::sendMessage("Hello World!"); का नाम बदलना काम करेगा। मैं सिर्फ एक वैकल्पिक पाठ तर्क के साथ एक एकल प्रेषण विधि बनाउंगा जो विधि को कैसे कार्य करता है बदलता है।

public function send($text = false) { 
    if (!$text) { 
     $text = $this -> text; 
    } 

    // Send something 
} 

मैं करने के लिए कारण है कि आप स्थिर समारोह में सभी की जरूरत के रूप में courious।

+3

स्थैतिक विधि का नाम बदलना निश्चित रूप से ऐसा करने का समझदार तरीका है। – lonesomeday

-1

पुराने धागे को बंप करने के लिए खेद है, लेकिन मैं @lonesomeday के उत्तर पर विस्तार करना चाहता हूं। (धन्यवाद प्रारंभिक कोड नमूने के लिए @lonesomeday।)

मैं भी इस के साथ प्रयोग किया गया था के रूप में अच्छी तरह से है, लेकिन के रूप में वह उन्हें मूल पोस्ट में कहा जाता है तरीकों कॉल करने के लिए नहीं चाहता था।

class Emailer { 

    private $recipient; 

    public function to($recipient) 
    { 
     $this->recipient = $recipient; 
     return $this; 
    } 

    public function sendNonStatic() 
    { 
     self::mailer($this->recipient); 
    } 

    public static function sendStatic($recipient) 
    { 
     self::mailer($recipient); 
    } 

    public function __call($name, $arguments) 
    { 
     if ($name === 'send') { 
      call_user_func(array($this, 'sendNonStatic')); 
     } 
    } 

    public static function mailer($recipient) 
    { 
     // send() 
     echo $recipient . '<br>'; 
    } 

    public static function __callStatic($name, $arguments) 
    { 
     if ($name === 'send') { 
      call_user_func(array('Emailer', 'sendStatic'), $arguments[0]); 
     } 
    } 
} 

Emailer::send('[email protected]'); 

$Emailer = new Emailer; 
$Emailer->to('[email protected]'); 
$Emailer->send(); 
-1

मैं मानता हूँ कि यह हर हालत में बचा जाना चाहिए, लेकिन कुछ मामलों में जहां यह उपयोगी हो सकता है कर रहे हैं: इसके बजाय मैं निम्नलिखित है, जो लगता है काम करना है।

ज्यादातर मामलों में यह आपके कोड को अपठनीय और अप्रबंधनीय बना देगा।

मेरा विश्वास करो, मैं उस रास्ते से नीचे गया हूं।

यहां एक केस केस परिदृश्य के साथ एक उदाहरण है जहां यह अभी भी व्यावहारिक हो सकता है।

मैं केकपीएचपी 3.0 की फाइल क्लास को अपनी डिफ़ॉल्ट फ़ाइल हैंडलिंग क्लास के रूप में विस्तारित कर रहा हूं।

मैं एक स्थिर माइम प्रकार अनुमानक को रखना चाहता था।

कुछ मामलों में मैं एक फ़ाइल नाम के बजाय एक वास्तविक फ़ाइल है और कुछ मान्यताओं इस मामले में किए जाने के लिए की जरूरत है।(यदि फ़ाइल मौजूद है, तो इसके द्वारा माइम प्राप्त करने का प्रयास करें और प्रदान किए गए फ़ाइल नाम के विस्तार का उपयोग करें)

अन्य बार यदि मैं वास्तव में किसी ऑब्जेक्ट को तुरंत चालू करता हूं तो डिफ़ॉल्ट माइम() विधि को काम करना चाहिए, लेकिन अगर यह विफल हो जाता है तो फ़ाइल नाम निकालने की आवश्यकता होती है ऑब्जेक्ट से और स्थैतिक विधि को इसके बजाय बुलाया जाना चाहिए।

स्टेटिक:

NS\File::type('path/to/file.txt') 

वस्तु के रूप में

$f = new NS\File('path/to/file.txt'); 
$f->type(); 

यहाँ है

भ्रम से बचने के लिए मेरे उद्देश्य एक ही विधि को फोन करके माइम प्रकार मिल गया था मेरा उदाहरण विस्तारित वर्ग:

<?php 

namespace NS; 

class File extends \Cake\Utility\File 
{ 

    public function __call($method, $args) { 
     return call_user_func_array([get_called_class(), 'obj'.ucfirst($method)], $args); 
    } 
    public static function __callStatic($method, $args) { 
     return call_user_func_array([get_called_class(), 'static'.ucfirst($method)], $args); 
    } 

    public function objType($filename=null){ 
     $mime = false; 
     if(!$filename){ 
      $mime = $this->mime(); 
      $filename = $this->path; 
     } 
     if(!$mime){ 
      $mime = static::getMime($filename); 
     } 
     return $mime; 
    } 

    public static function staticType($filename=null){ 
     return static::getMime($filename); 
    } 

    public static function getMime($filename = null) 
    { 
     $mimes = [ 
      'txt' => 'text/plain', 
      'htm' => 'text/html', 
      'html' => 'text/html', 
      'php' => 'text/html', 
      'ctp' => 'text/html', 
      'twig' => 'text/html', 
      'css' => 'text/css', 
      'js' => 'application/javascript', 
      'json' => 'application/json', 
      'xml' => 'application/xml', 
      'swf' => 'application/x-shockwave-flash', 
      'flv' => 'video/x-flv', 
      // images 
      'png' => 'image/png', 
      'jpe' => 'image/jpeg', 
      'jpeg' => 'image/jpeg', 
      'jpg' => 'image/jpeg', 
      'gif' => 'image/gif', 
      'bmp' => 'image/bmp', 
      'ico' => 'image/vnd.microsoft.icon', 
      'tiff' => 'image/tiff', 
      'tif' => 'image/tiff', 
      'svg' => 'image/svg+xml', 
      'svgz' => 'image/svg+xml', 
      // archives 
      'zip' => 'application/zip', 
      'rar' => 'application/x-rar-compressed', 
      'exe' => 'application/x-msdownload', 
      'msi' => 'application/x-msdownload', 
      'cab' => 'application/vnd.ms-cab-compressed', 
      // audio/video 
      'mp3' => 'audio/mpeg', 
      'qt' => 'video/quicktime', 
      'mov' => 'video/quicktime', 
      // adobe 
      'pdf' => 'application/pdf', 
      'psd' => 'image/vnd.adobe.photoshop', 
      'ai' => 'application/postscript', 
      'eps' => 'application/postscript', 
      'ps' => 'application/postscript', 
      // ms office 
      'doc' => 'application/msword', 
      'rtf' => 'application/rtf', 
      'xls' => 'application/vnd.ms-excel', 
      'ppt' => 'application/vnd.ms-powerpoint', 
      // open office 
      'odt' => 'application/vnd.oasis.opendocument.text', 
      'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 
     ]; 
     $e = explode('.', $filename); 
     $ext = strtolower(array_pop($e)); 
     if (array_key_exists($ext, $mimes)) { 
      $mime = $mimes[$ext]; 
     } elseif (function_exists('finfo_open') && is_file($filename)) { 
      $finfo = finfo_open(FILEINFO_MIME); 
      $mime = finfo_file($finfo, $filename); 
      finfo_close($finfo); 
     } else { 
      $mime = 'application/octet-stream'; 
     } 
     return $mime; 
    } 
} 
0

मैं निर्माता के रूप में एक छिपा वर्ग बनाने के लिए और माता पिता के वर्ग स्थिर तरीकों छिपा वर्ग तरीकों के बराबर है कि अंदर है कि छिपा वर्ग वापसी होगी:

// Parent class 

class Hook { 

    protected static $hooks = []; 

    public function __construct() { 
     return new __Hook(); 
    } 

    public static function on($event, $fn) { 
     self::$hooks[$event][] = $fn; 
    } 

} 


// Hidden class 

class __Hook { 

    protected $hooks = []; 

    public function on($event, $fn) { 
     $this->hooks[$event][] = $fn; 
    } 

} 

यह स्थिर कॉल करने के लिए:

Hook::on("click", function() {}); 

यह गतिशील कॉल करने के लिए:

0

एक बहुत आसान तरीका है।

class MyClass { 

    private $r = "I'm regular!"; 

    private static $s = "I'm static!"; 

    public function method() { 
     if (isset($this) && $this instanceof self) { 
      // Regular call 
      echo $this->r; 
     } else { 
      // Static call 
      echo static::$s; 
     } 
    } 

} 

अब आप आसानी से कर सकते हैं:

(new MyClass())->method(); 
// I'm regular! 

या

MyClass::method(); 
// I'm static! 

आप सब कुछ आप प्रश्न में वर्णन प्राप्त करने के लिए इस ढांचे का उपयोग कर सकते हैं।

संबंधित मुद्दे