2009-07-21 15 views
5

मुझे रेल एक्टिव रिकार्ड, PHP के लिए सिद्धांत (और इसी तरह के ओआरएम) के पीछे कुछ डिज़ाइन में दिलचस्पी है।दृश्यों के पीछे: एक ओआरएम "सोच" कैसे करता है?

  • ओआरएम कैसे जंजीर एक्सेसर्स जैसी सुविधाओं को पूरा करने में कामयाब होता है और उन्हें आम तौर पर काम करने की अपेक्षा कितनी गहरी होती है?
  • ओआरएम आंतरिक रूप से प्रश्नों का निर्माण कैसे करता है?
  • ओआरएम उन सभी की मनमानी प्रकृति को बनाए रखने के दौरान प्रश्नों का प्रबंधन कैसे करता है?

स्पष्ट रूप से यह एक अकादमिक प्रश्न है, लेकिन उत्तरों के सभी स्वरूपों का स्वागत है! सेटर विधि से return $this आप:

(पसंद का मेरी भाषा OO PHP5.3 है!)

+7

एंथ्रोपोमोर्फिस कंप्यूटर न करें। वे इसे पसंद नहीं करते हैं। – finnw

उत्तर

3

जंजीर विधि कॉल ORM प्रश्न के orthogonal हैं, वे सब OOP में जगह इस्तेमाल कर रहे हैं। एक श्रृंखला-सक्षम विधि केवल वर्तमान ऑब्जेक्ट का संदर्भ देता है, जिससे वापसी मूल्य को कॉल किया जा सकता है। PHP

class A { 
    public function b() { 
     ... 
     return $this; 
    } 

    public function c($param) { 
     ... 
     return $this; 
    }  
} 


$foo = new A(); 
$foo->b()->c('one'); 
// chaining is equivilant to 
// $foo = $foo->b(); 
// $foo = $foo->c(); 

प्रश्नों के निर्माण के तरीके के रूप में, दो विधियां हैं। ActiveRecord जैसे ORMs में कोड है जो डेटाबेस के मेटा-डेटा की जांच करता है। इस मेटा-डेटा को देखने के लिए अधिकांश डेटाबेस में किसी प्रकार का SQL या SQL कमांड होता है। (MySQL का DESCRIBE TABLE, ओरेकल की USER_TAB_COLUMNS तालिका, आदि)

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

एक तालिका के नाम और डेटा-प्रकार ज्ञात हैं, व्यावहारिक रूप से एक SQL क्वेरी लिखना बहुत आसान है जो सभी पंक्तियों या पंक्तियों का एक विशिष्ट सेट देता है जो एक निश्चित मानदंड को पूरा करते हैं।

अपने आखिरी सवाल का सवाल है,

कैसे एक ORM जबकि सभी है कि यह उम्मीद की जाती है के मनमाने स्वरूप को बनाए रखने के प्रश्नों का प्रबंधन करता है?

मैं जवाब का तर्क था "बहुत अच्छी तरह से नहीं है।" एक बार जब आप एक-टेबल, एक-ऑब्जेक्ट रूपक से आगे बढ़ जाते हैं, तो प्रत्येक ओआरएम के पास एक अलग दृष्टिकोण होता है कि ऑब्जेक्ट्स को मॉडल करने के लिए SQL क्वेरी का उपयोग कैसे किया जाना चाहिए। हालांकि, संक्षेप में, यह ओआरएम (यानी Zend_Db_Table की "findManyToManyRowset" विधि)

+0

धन्यवाद! यह वास्तव में एक महान जवाब है। तो सच में, एक ओआरएम अपनी जटिलता को उन सरलताओं से प्राप्त करता है जो इसे एक सरल सरलीकृत क्वेरी जनरेटर के शीर्ष पर प्रदान करते हैं? –

+0

यह डालने का एक तरीका है। हालांकि मैं "ओआरएम" शब्द से सावधान रहूंगा। ऐसे बहुत से लोग हैं जो AcrtiveRecord जैसी चीजों को एक वास्तविक ओआरएम पर विचार नहीं करते हैं, बल्कि ओआरएम को लागू करने के लिए एक उपकरण है। यहां http://kore-nordmann.de/blog/why_active_record_sucks.html –

+0

यह निश्चित रूप से सच है। मैं सिर्फ एक ओओ डेटा एक्सेस रैपर या बेस ओओ डेटा क्लास को कॉल करता हूं। जानकारी के लिए धन्यवाद :) मुझे प्रश्नों को स्वयं उत्पन्न करने के तरीके के बारे में एक और विशिष्ट सवाल करना पड़ सकता है। यह निर्धारित करना कि कौन से कॉलम लाने के लिए आसान है। लेकिन मुझे यकीन है कि WHERE क्लॉज और अन्य स्थितियों को उत्पन्न करने के लिए कुछ जटिल प्रक्रिया है ... –

0

जंजीर accessors वास्तव में एक बड़ी बात नहीं कर रहे हैं। बूम, किया, आप जितना चाहें उतने स्तर पर काम करता है।

+0

क्या आपका मतलब "गेटटर" विधि है? तो क्या आप अनुरोध की गई विधि के राज्य को संग्रहीत करते हैं और मूल ऑब्जेक्ट को और अधिक tweaks प्राप्त करने के लिए वापस लाते हैं? PHP में कहें, यह जानने का एक अच्छा तरीका क्या होगा कि आप एक श्रृंखला के अंत में हैं - और इस प्रकार "इस" के बजाय परिणाम लौटाना चाहिए? –

+0

नहीं, मेरा मतलब है सेटटर विधियां। * लिखने * एक्सेसर्स के बजाय * पढ़ने * एक्सेसर्स पर एक्सेसर चेनिंग, मेरे लिए बकवास है। – chaos

+0

दिलचस्प, मैं बस गलत शब्द का उपयोग कर सकता हूं। क्या आप समझा सकते हैं कि कैसे आते हैं? –

1

पर आधारित एक नई प्रस्तुतियां बनाने के समान सरल है जो मैंने एक PHP डेटामैपर बनाने के विषय पर एक प्रस्तुति बनाई है जो हो सकता है आप के लिए दिलचस्पयह ओक्लाहोमा सिटी कोवर्किंग सहयोगात्मक पर वीडियो पर दर्ज किया गया था जब मैं यह पीएचपी उपयोगकर्ता समूह के लिए वहाँ प्रस्तुत:

वीडियो: http://blip.tv/file/2249586/

प्रस्तुति स्लाइड: http://www.slideshare.net/vlucas/building-data-mapper-php5-presentation

प्रस्तुति मूल रूप से जल्दी अवधारणा थी phpDataMapper का, हालांकि बहुत कुछ बदल गया है।

आशा है कि वे आपको ओआरएम की आंतरिक कार्यप्रणाली को थोड़ा बेहतर समझने में मदद करें।

2

एक ओआरएम कैसे जंजीर एक्सेसर्स जैसी सुविधाओं को पूरा करने में कामयाब होता है और उन्हें आम तौर पर कितनी गहरी काम करने की उम्मीद है?

कोई भी इसका उत्तर नहीं दिया है। मैं जल्दी से वर्णन कर सकता हूं कि PHP में यह सिद्धांत कैसे करता है।

सिद्धांत में, किसी ऑब्जेक्ट मॉडल पर जो फ़ील्ड आप देखते हैं, वास्तव में उस वर्ग के लिए परिभाषित नहीं किया जाता है। तो आपके उदाहरण में, $ कार-> मालिकों, $ कार के वर्ग में परिभाषित 'मालिक' नामक कोई वास्तविक क्षेत्र नहीं है।

इसके बजाय, ओआरएम __get and __set जैसे जादू विधियों का उपयोग करता है। तो जब आप $ car-> रंग जैसे अभिव्यक्ति का उपयोग करते हैं, आंतरिक रूप से PHP कॉल करते हैं Doctrine_Record #__ get ('color')।

इस बिंदु पर ओआरएम किसी भी तरह से इसे संतुष्ट करने के लिए स्वतंत्र है। यहां बहुत सारे संभावित डिज़ाइन हैं। यह इन मानों को $ _values ​​नामक सरणी में संग्रहीत कर सकता है, उदाहरण के लिए, और उसके बाद $ -> _ मान ['रंग'] वापस लौटाएं। विशेष ट्रैक में सिद्धांत न केवल प्रत्येक रिकॉर्ड के लिए मूल्य, बल्कि डेटाबेस में दृढ़ता के सापेक्ष इसकी स्थिति भी ट्रैक करता है।

इसका एक उदाहरण अंतर्ज्ञानी नहीं है सिद्धांत के संबंधों के साथ है। जब आपको $ कार का संदर्भ मिलता है, तो इसका उन लोगों के साथ संबंध होता है जिन्हें 'मालिक' कहा जाता है। तो $ कार-> मालिकों के लिए डेटा वास्तव में $ कार के डेटा से अलग तालिका में संग्रहीत किया जाता है। इसलिए ओआरएम में दो विकल्प हैं:

  1. प्रत्येक बार जब आप $ उपयोगकर्ता लोड करते हैं, तो ओआरएम स्वचालित रूप से सभी संबंधित तालिकाओं में शामिल होता है और उस जानकारी को ऑब्जेक्ट में पॉप्युलेट करता है। अब जब आप $ कार-> मालिक करते हैं, तो वह डेटा पहले से मौजूद है। हालांकि, यह विधि धीमी है, क्योंकि वस्तुओं के कई रिश्ते हो सकते हैं, और उन रिश्तों में खुद के संबंध हो सकते हैं। तो आप जोड़ रहे होंगे में बहुत से जुड़ते हैं और जरूरी नहीं कि उस जानकारी का उपयोग भी किया जाए।
  2. प्रत्येक बार जब आप $ उपयोगकर्ता लोड करते हैं, तो ORM नोटिस करता है कि कौन से फ़ील्ड उपयोगकर्ता तालिका से लोड की जाती हैं और यह उन्हें पॉप्युलेट करती है, लेकिन संबंधित तालिकाओं से लोड किए गए किसी भी फ़ील्ड को लोड नहीं किया जाता है। इसके बजाए, उन फ़ील्ड से कुछ मेटाडाटा संलग्न हैं जिन्हें उन्हें 'लोड नहीं किया गया है, लेकिन उपलब्ध' के रूप में चिह्नित किया गया है। अब जब आप $ car-> मालिकों को अभिव्यक्ति लिखते हैं, तो ओआरएम देखता है कि 'मालिकों' रिश्ते को लोड नहीं किया गया है, और यह उस जानकारी को प्राप्त करने के लिए एक अलग क्वेरी जारी करता है, इसे ऑब्जेक्ट में जोड़ता है, और उसके बाद उस डेटा को वापस कर देता है। यह सब बिना पारदर्शी रूप से होता है जब आपको इसे महसूस करने की आवश्यकता होती है।

बेशक, सिद्धांत # 2 का उपयोग करता है, क्योंकि # 1 मध्यम जटिलता वाले किसी वास्तविक उत्पादन साइट के लिए अनावश्यक हो जाता है। लेकिन इसका दुष्प्रभाव भी है। यदि आप $ कार पर कई रिश्ते का उपयोग कर रहे हैं, तो जब आप इसे एक्सेस करेंगे, तो सिद्धांत प्रत्येक को अलग से लोड करेगा। तो आप 5-6 प्रश्नों को चलाते हैं जब शायद केवल 1 की आवश्यकता होती है।

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

Whew! लंबी प्रतिक्रिया। असल में, हालांकि, आप "ओआरएम का उद्देश्य क्या है?" के दिल में प्राप्त हुए हैं और "हमें एक का उपयोग क्यों करना चाहिए?" ओआरएम हमें ऑब्जेक्ट मोड में ज्यादातर बार सोचने की इजाजत देता है, लेकिन अमूर्तता सही नहीं है और अबास्ट्रक्शन में रिसाव प्रदर्शन दंड के रूप में बाहर आती है।

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