2008-08-28 13 views
8

मैं इस प्रश्न के प्रारूप के साथ कुछ करने की कोशिश कर रहा हूं और मैं इसे संभालने के बेहतर तरीके के बारे में सुझावों के लिए बहुत खुला हूं।क्या PHP वर्ग में गेटर्स/सेटर्स को संभालने का यह एक उचित तरीका है?

मैं इस प्रश्न में कोड का एक गुच्छा डंप नहीं करना चाहता था इसलिए मैंने कक्षा के लिए कोड को refactormycode पर पोस्ट किया है।

base class for easy class property handling

मेरे बारे में सोचा है कि लोगों को भी कर सकते हैं पोस्ट कोड यहाँ के टुकड़े या उनके refactorings को refactormycode और बाद लिंक पर परिवर्तन कर रहा था। मैं अपवॉट कर दूंगा और उस पर आधारित एक जवाब स्वीकार करूँगा (माना जाता है कि एक स्पष्ट "विजेता" है)।

किसी भी दर

, वर्ग ही पर:

मैं गेटर/सेटर वर्ग के तरीकों के बारे में बहस का एक बहुत देखते हैं और यह बेहतर बस सीधे सरल संपत्ति चर तक पहुँचने के लिए या हर वर्ग स्पष्ट प्राप्त/सेट होना चाहिए है विधियों परिभाषित, ब्ला ब्ला ब्लाह। यदि आपको बाद में अधिक तर्क जोड़ना है तो मुझे स्पष्ट तरीकों के बारे में विचार पसंद है। फिर आपको कक्षा का उपयोग करने वाले किसी भी कोड को संशोधित करने की आवश्यकता नहीं है। हालांकि मैं एक लाख कार्यों कि इस तरह दिखना होने से नफरत है:

public function getFirstName() 
{ 
    return $this->firstName; 
} 
public function setFirstName($firstName) 
{ 
    return $this->firstName; 
} 

अब मुझे यकीन है कि मैं इस (मैं आशा करती हूं कि किसी को यह कर सकते हैं यह करने का एक बेहतर तरीका है कि ऐसा करने के लिए पहले व्यक्ति नहीं हूँ हूँ मुझे सुझाव दें)।

असल में, प्रॉपर्टी हैंडलर क्लास में __call जादू विधि है। "Get" या "set" से शुरू होने वाले __call के माध्यम से आने वाली कोई भी विधि तब उन फ़ंक्शंस पर जाती है जो किसी एसोसिएटिव सरणी में मान सेट या पुनर्प्राप्त करती हैं। सरणी में कुंजी कॉल या सेट के बाद कॉलिंग विधि का नाम है। इसलिए, यदि __call में आने वाली विधि "getFirstName" है, तो सरणी कुंजी "फर्स्टनाम" है।

मुझे __call का उपयोग करना पसंद आया क्योंकि यह स्वचालित रूप से उस मामले का ख्याल रखेगा जहां सबक्लास के पास पहले से ही "getFirstName" विधि परिभाषित है। मेरी धारणा (और मैं गलत हो सकता हूं) यह है कि __get & __set जादू विधियां ऐसा नहीं करती हैं।

तो यहाँ है कि यह कैसे काम करेगा का एक उदाहरण है:

class PropTest extends PropertyHandler 
{ 
    public function __construct() 
    { 
     parent::__construct(); 
    } 
} 

$props = new PropTest(); 

$props->setFirstName("Mark"); 
echo $props->getFirstName(); 

सूचना है कि PropTest वास्तव में "setFirstName" या "getFirstName" विधियां नहीं हैं और न PropertyHandler करता है। जो कुछ भी कर रहा है वह सरणी मानों में हेरफेर कर रहा है।

दूसरा मामला वह होगा जहां आपका सबक्लास पहले से ही कुछ और विस्तार कर रहा है। चूंकि आप PHP में वास्तविक एकाधिक विरासत नहीं प्राप्त कर सकते हैं, इसलिए आप अपने सबक्लास को एक निजी चर के रूप में एक संपत्ति हैंडलर उदाहरण बना सकते हैं। आपको एक और फ़ंक्शन जोड़ना होगा लेकिन फिर चीजें ठीक उसी तरह व्यवहार करती हैं।

class PropTest2 
{ 
    private $props; 

    public function __construct() 
    { 
     $this->props = new PropertyHandler(); 
    } 

    public function __call($method, $arguments) 
    { 
     return $this->props->__call($method, $arguments); 
    } 
} 

$props2 = new PropTest2(); 

$props2->setFirstName('Mark'); 
echo $props2->getFirstName(); 

सूचना कैसे उपवर्ग एक __call विधि है कि बस PropertyHandler __call विधि के साथ सब कुछ गुजरता है।


गेटर्स और सेटर्स को संभालने के खिलाफ एक और अच्छा तर्क यह है कि यह दस्तावेज़ को वास्तव में कठिन बनाता है।

असल में, किसी भी तरह के दस्तावेज़ जनरेशन टूल का उपयोग करना मूल रूप से असंभव है क्योंकि दस्तावेजों को दस्तावेज करने के लिए स्पष्ट तरीके मौजूद नहीं हैं।

मैं काफी अब के लिए इस दृष्टिकोण त्याग दिया है। यह एक दिलचस्प सीखने का अभ्यास था, लेकिन मुझे लगता है कि यह बहुत स्पष्टता बलिदान देता है।

+0

जिज्ञासा से, अब आप किस विधि का उपयोग करते हैं? – SeanJA

+0

एक ही कक्षा में गेटर्स ** और ** सेटर्स होने का संकेत यह है कि कक्षा में इसका कोड गुम है। उस कोड की जांच करें जो वर्ग 'गेटर्स और सेटर्स का उपयोग करती है और इसे कक्षा के अंदर ले जाती है क्योंकि यह वह जगह है जहां यह संबंधित है। – axiac

उत्तर

5

तरह से मैं इसे निम्नलिखित है:

class test { 
    protected $x=''; 
    protected $y=''; 

    function set_y ($y) { 
     print "specific function set_y\n"; 
     $this->y = $y; 
    } 

    function __call($function , $args) { 
     print "generic function $function\n"; 
     list ($name , $var) = split ('_' , $function); 
     if ($name == 'get' && isset($this->$var)) { 
      return $this->$var; 
     } 
     if ($name == 'set' && isset($this->$var)) { 
      $this->$var= $args[0]; 
      return; 
     } 
     trigger_error ("Fatal error: Call to undefined method test::$function()"); 
    } 
} 

$p = new test(); 
$p->set_x(20); 
$p->set_y(30); 
print $p->get_x(); 
print $p->get_y(); 

$p->set_z(40); 

कौन सा निर्गम (पंक्ति विराम स्पष्टता के लिए जोड़ा) होगा

generic function set_x 
specific function set_y 

generic function get_x 
20 
generic function get_y 
30 

generic function set_z 
Notice: Fatal error: Call to undefined method set_z() in [...] on line 16 
+0

(ओपी से टिप्पणी बढ़ रहा है): @Pat यह दिलचस्प है। निश्चित रूप से बहुत कम कोड। लेकिन आपको अभी भी प्रत्येक अंतर्निहित संपत्ति चर स्पष्ट रूप से घोषित करना होगा, है ना? –

+0

"विभाजन" को PHP 5.3.0 –

2

हाँ यह सही है चर मैन्युअल घोषित किया जाना है, लेकिन मैं लगता है इससे बेहतर है कि मैं सेटर

$props2->setFristName('Mark'); 

एक टाइपिंग में एक टाइपो से डरता है (फर्स्टनाम के बजाय FristName) जो डीबगिंग को कठिन बना देगा।

1

मुझे सार्वजनिक क्षेत्रों का उपयोग करने के बजाय विधियों को भी पसंद है, लेकिन PHP की डिफ़ॉल्ट कार्यान्वयन के साथ मेरी समस्या (__get() और __set() का उपयोग करके) या आपका कस्टम कार्यान्वयन यह है कि आप गेटर्स और सेटर्स को स्थापित नहीं कर रहे हैं एक प्रति संपत्ति आधार। इस के साथ मेरी समस्या "बाद में अधिक तर्क" जोड़ने की आवश्यकता है कि यह है कि आप गेटर/सेटर के साथ पहुँचा सभी संपत्तियों के लिए या आप यदि का उपयोग करें या जो संपत्ति आप तक पहुँच रहे हैं, ताकि आप आवेदन कर सकते हैं का मूल्यांकन करने के बयान के लिए स्विच है कि लागू होने वाला कंबल तर्क जोड़ने है विशिष्ट तर्क

मुझे आपका समाधान पसंद है, और मैं इसके लिए आपको सराहना करता हूं - मैं केवल उन सीमाओं से संतुष्ट नहीं हूं जब PHP में निहित एक्सेसर विधियों की बात आती है।

+0

(ओपी से चलती टिप्पणी) के रूप में बहिष्कृत कर दिया गया है @Brian यह एक दिलचस्प बिंदु है। मुझे थोड़ा सा झुकाव करना होगा। –

3

@Brian

इस के साथ मेरी समस्या "बाद में अधिक तर्क" जोड़ने की आवश्यकता है कि यह है कि आप गेटर/सेटर के साथ या आप का उपयोग करने वाले पहुँचा सभी गुण पर लागू होने वाला कंबल तर्क जोड़ने है अगर आप जिस संपत्ति का उपयोग कर रहे हैं उसका मूल्यांकन करने के लिए कथन स्विच करें ताकि आप विशिष्ट तर्क लागू कर सकें।

काफी सच नहीं है यही कारण है कि। मेरा पहला उदाहरण लें:

class PropTest extends PropertyHandler 
{ 
    public function __construct() 
    { 
     parent::__construct(); 
    } 
} 

$props = new PropTest(); 

$props->setFirstName("Mark"); 
echo $props->getFirstName(); 

मान लीजिए कि मैं FirstNames सत्यापित करने के लिए कुछ तर्क जोड़ने की जरूरत हैं। मुझे बस इतना करना है कि मेरे सबक्लास में एक सेट फर्स्टनाम विधि जोड़ें और उस विधि का स्वचालित रूप से उपयोग किया जाता है।

class PropTest extends PropertyHandler 
{ 
    public function __construct() 
    { 
     parent::__construct(); 
    } 

    public function setFirstName($name) 
    { 
     if($name == 'Mark') 
     { 
      echo "I love you, Mark!"; 
     } 
    } 
} 

मैं बस जब यह अंतर्निहित एक्सेसर तरीकों की बात आती है सीमाओं से संतुष्ट पीएचपी है कि नहीं कर रहा हूँ।

मैं पूरी तरह से सहमत हैं। मुझे इसे संभालने के पाइथन तरीके पसंद हैं (मेरा कार्यान्वयन सिर्फ इसके लिए एक बेकार चीर है)।

1

@Mark

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

+0

सभी गुण जो मूल गेटर/सेटर के साथ ठीक हैं, वे जादू कॉल का उपयोग करेंगे। अगर उसे अतिरिक्त कोड जोड़ने की ज़रूरत है तो वह केवल उन गुणों के लिए गेटर्स/सेटर्स बना सकता है। फिर, यह कुछ भ्रम पैदा कर सकता है, लेकिन यह एक विकल्प है। – Galen

0

मैंने हमेशा इस समस्या को __call के समान ही संभाला है जो मेरे कई वर्गों में बॉयलर प्लेट कोड के रूप में बहुत अधिक समाप्त होता है। हालांकि, यह कॉम्पैक्ट है, और प्रतिबिंब वर्गों का उपयोग केवल उन गुणों के लिए गेटर्स/सेटर्स को जोड़ने के लिए करता है जिन्हें आप पहले से सेट कर चुके हैं (नए जोड़े नहीं जोड़ेंगे)। बस गेटर/सेटर जोड़ना स्पष्ट रूप से अधिक जटिल कार्यक्षमता जोड़ देगा।

/** 
* Handles default set and get calls 
*/ 
public function __call($method, $params) { 

    //did you call get or set 
    if (preg_match("|^[gs]et([A-Z][\w]+)|", $method, $matches)) { 

     //which var? 
     $var = strtolower($matches[1]); 

     $r = new ReflectionClass($this); 
     $properties = $r->getdefaultProperties(); 

     //if it exists 
     if (array_key_exists($var,$properties)) { 
      //set 
      if ('s' == $method[0]) { 
       $this->$var = $params[0]; 
      } 
      //get 
      elseif ('g' == $method[0]) { 
       return $this->$var; 
      } 
     } 
    } 
} 

एक वर्ग जहां की तरह डिफ़ॉल्ट गुण घोषणा की है करने के लिए इस जोड़ना:: यह

कोड इस तरह दिखता है यह उम्मीद

class MyClass { 
    public $myvar = null; 
} 

$test = new MyClass; 
$test->setMyvar = "arapaho"; 

echo $test->getMyvar; //echos arapaho  

प्रतिबिंब वर्ग के लिए उपयोग की कुछ जोड़ सकते हैं क्या आप प्रस्ताव दे रहे थे। साफ समाधान @ मार्क।

0

हाल ही में, मैंने आपके द्वारा सुझाए गए मार्गों और सेटर्स को संभालने के बारे में भी सोचा था (दूसरा दृष्टिकोण मेरा पसंदीदा था, यानी निजी $ प्रोपर्स सरणी), लेकिन मैंने इसे छोड़ दिया क्योंकि यह मेरे ऐप में काम नहीं करता ।

मैं एक बड़े साबुन सर्वर आधारित अनुप्रयोग पर काम कर रहा हूं और PHP 5 के साबुन इंटरफ़ेस वर्ग में मौजूदा या गैर-मौजूदा गुणों के बारे में परेशान किए बिना, सीधे वर्ग में साबुन के माध्यम से प्रेषित मानों को इंजेक्ट करता है।

0

मैं अपने 2 सेंट में डाल मदद नहीं कर सकता ...

मैं इस मनोर http://gist.github.com/351387 (रास्ता है कि सिद्धांत यह है के समान) में __get और __set उपयोग करते हुए, उसके बाद ही कभी गुण तक पहुँचने के लिए ले लिया है कक्षा के बाहर $obj->var के माध्यम से। इस तरह आप बच्चों की कक्षाओं में __get या __set फ़ंक्शन, या __get और __set ओवरराइड करने के बजाय आवश्यक कार्यक्षमता को ओवरराइड कर सकते हैं।

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

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