php - एमवीसी में मॉडल को कैसे संरचित किया जाना चाहिए?




oop model-view-controller architecture model (5)

मैं सिर्फ एमवीसी ढांचे पर एक समझ प्राप्त कर रहा हूं और मुझे अक्सर आश्चर्य होता है कि मॉडल में कितना कोड जाना चाहिए। मेरे पास डेटा एक्सेस क्लास है जिसमें इस तरह के तरीके हैं:

public function CheckUsername($connection, $username)
{
    try
    {
        $data = array();
        $data['Username'] = $username;

        //// SQL
        $sql = "SELECT Username FROM" . $this->usersTableName . " WHERE Username = :Username";

        //// Execute statement
        return $this->ExecuteObject($connection, $sql, $data);
    }
    catch(Exception $e)
    {
        throw $e;
    }
}

मेरे मॉडल एक इकाई वर्ग होते हैं जो डेटाबेस तालिका में मैप किया जाता है।

क्या मॉडल ऑब्जेक्ट में सभी डेटाबेस मैप किए गए गुणों के साथ-साथ उपरोक्त कोड होना चाहिए या क्या यह कोड अलग करना ठीक है जो वास्तव में डेटाबेस का काम करता है?

क्या मैं चार परतों को समाप्त कर दूंगा?


Answers

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

पहली चीज़ जो मुझे साफ़ करनी है वह है: मॉडल एक परत है

दूसरा: शास्त्रीय एमवीसी और वेब विकास में हम जो भी उपयोग करते हैं, उसके बीच एक अंतर है। Here's लिखा गया एक पुराना उत्तर है, जो संक्षेप में वर्णन करता है कि वे अलग कैसे हैं।

क्या मॉडल नहीं है:

मॉडल एक वर्ग या कोई भी वस्तु नहीं है। यह करने के लिए एक बहुत ही आम गलती है (मैंने भी किया, हालांकि मूल उत्तर लिखा गया था जब मैंने अन्यथा सीखना शुरू किया) , क्योंकि अधिकांश ढांचे इस गलतफहमी को कायम रखते हैं।

न तो यह एक ऑब्जेक्ट-रिलेशनल मैपिंग तकनीक (ओआरएम) है और न ही डेटाबेस टेबल का एक अमूर्त है। कोई भी जो आपको अन्यथा बताता है, वह शायद किसी अन्य ब्रांड-नए ओआरएम या पूरे ढांचे को 'बेचने' की कोशिश कर रहा है।

क्या मॉडल है:

उचित एमवीसी अनुकूलन में, एम में सभी डोमेन व्यापार तर्क शामिल हैं और मॉडल लेयर ज्यादातर तीन प्रकार के संरचनाओं से बना है:

  • डोमेन ऑब्जेक्ट्स

    एक डोमेन ऑब्जेक्ट पूरी तरह से डोमेन जानकारी का तार्किक कंटेनर है; यह आमतौर पर समस्या डोमेन स्थान में एक तार्किक इकाई का प्रतिनिधित्व करता है। आम तौर पर व्यापार तर्क के रूप में जाना जाता है।

    यह वह जगह होगी जहां आप चालान भेजने से पहले डेटा को मान्य करने के लिए परिभाषित करते हैं, या ऑर्डर की कुल लागत की गणना करने के लिए। साथ ही, डोमेन ऑब्जेक्ट्स पूरी तरह से भंडारण से अनजान हैं - न तो जहां से (SQL डेटाबेस, REST API, टेक्स्ट फ़ाइल इत्यादि) और न ही वे सहेजे या पुनर्प्राप्त किए जाते हैं।

  • डेटा मैपर

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

  • Services

    आप उन्हें "उच्च स्तरीय डोमेन ऑब्जेक्ट्स" के रूप में सोच सकते हैं, लेकिन व्यावसायिक तर्क के बजाय, डोमेन ऑब्जेक्ट्स और मैपर के बीच बातचीत के लिए सेवाएं ज़िम्मेदार हैं। ये संरचनाएं डोमेन व्यापार तर्क के साथ बातचीत के लिए "सार्वजनिक" इंटरफ़ेस बनाने का अंत करती हैं। आप उनसे बच सकते हैं, लेकिन नियंत्रकों में कुछ डोमेन तर्क लीक करने के दंड पर।

    एसीएल कार्यान्वयन प्रश्न में इस विषय का एक संबंधित उत्तर है - यह उपयोगी हो सकता है।

मॉडल परत और एमवीसी ट्रायड के अन्य हिस्सों के बीच संचार केवल सेवाओं के माध्यम से होना चाहिए। स्पष्ट अलगाव के कुछ अतिरिक्त लाभ हैं:

  • यह एकल जिम्मेदारी सिद्धांत (एसआरपी) को लागू करने में मदद करता है
  • तर्क परिवर्तन के मामले में अतिरिक्त 'wiggle room' प्रदान करता है
  • जितना संभव हो सके नियंत्रक को सरल रखता है
  • यदि आपको कभी बाहरी एपीआई की आवश्यकता है, तो एक स्पष्ट ब्लूप्रिंट देता है

मॉडल के साथ कैसे बातचीत करें?

पूर्वापेक्षाएँ: व्याख्यान देखें "वैश्विक राज्य और सिंगलेट्स" और "चीजों के लिए देखो मत!" स्वच्छ कोड वार्ता से।

सेवा के उदाहरणों तक पहुंच प्राप्त करना

इन सेवाओं तक पहुंचने के लिए दोनों व्यू और कंट्रोलर इंस्टेंस (जिसे आप कॉल कर सकते हैं: "UI layer") दोनों के लिए, दो सामान्य दृष्टिकोण हैं:

  1. आप सीधे अपने विचारों और नियंत्रकों के रचनाकारों में आवश्यक सेवाओं को इंजेक्ट कर सकते हैं, अधिमानतः एक डी कंटेनर का उपयोग कर सकते हैं।
  2. अपने सभी विचारों और नियंत्रकों के लिए अनिवार्य निर्भरता के रूप में सेवाओं के लिए एक कारखाने का उपयोग करना।

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

फैक्ट्री और डीआई कंटेनर का उपयोग करने वाले दोनों समाधान आपको चयनित नियंत्रक के बीच साझा करने के लिए विभिन्न सर्वरों के उदाहरण साझा करने और किसी दिए गए अनुरोध-प्रतिक्रिया चक्र के लिए देखने की अनुमति देंगे।

मॉडल के राज्य में बदलाव

अब जब आप नियंत्रकों में मॉडल परत तक पहुंच सकते हैं, तो आपको वास्तव में उनका उपयोग शुरू करना होगा:

public function postLogin(Request $request)
{
    $email = $request->get('email');
    $identity = $this->identification->findIdentityByEmailAddress($email);
    $this->identification->loginWithPassword(
        $identity,
        $request->get('password')
    );
}

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

नियंत्रक उपयोगकर्ता के इनपुट को प्रमाणित करने के लिए ज़िम्मेदार नहीं है, क्योंकि यह व्यवसाय नियमों का हिस्सा है और नियंत्रक निश्चित रूप से SQL क्वेरी को कॉल नहीं कर रहा है, जैसा कि आप here या here देखेंगे (कृपया उन पर नफरत न करें, वे गुमराह हैं, बुरा नहीं हैं)।

उपयोगकर्ता को राज्य परिवर्तन दिखा रहा है।

ठीक है, उपयोगकर्ता ने लॉग इन किया है (या असफल)। अब क्या? कहा गया है कि उपयोगकर्ता अभी भी इसके बारे में अनजान है। तो आपको वास्तव में एक प्रतिक्रिया उत्पन्न करने की आवश्यकता है और यह एक दृष्टिकोण की ज़िम्मेदारी है।

public function postLogin()
{
    $path = '/login';
    if ($this->identification->isUserLoggedIn()) {
        $path = '/dashboard';
    }
    return new RedirectResponse($path); 
}

इस मामले में, दृश्य मॉडल की वर्तमान स्थिति के आधार पर, दृश्य ने दो संभावित प्रतिक्रियाओं में से एक का उत्पादन किया। एक अलग उपयोग-मामले के लिए, "दृश्य के वर्तमान चयनित" जैसे कुछ के आधार पर आपके पास प्रस्तुत करने के लिए अलग-अलग टेम्पलेट चुनने का विचार होगा।

प्रस्तुतिकरण परत वास्तव में काफी विस्तृत हो सकती है, जैसा कि यहां वर्णित है: PHP में एमवीसी दृश्यों को समझना ।

लेकिन मैं बस एक आरईएसटी एपीआई बना रहा हूँ!

बेशक, हालात हैं, जब यह एक overkill है।

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

इसका मतलब है कि, जब आपकी प्रस्तुति परत का तर्क किसी भी अस्तित्व के नजदीक नहीं है, तो व्यावहारिक दृष्टिकोण उन्हें एक परत के रूप में रखना है। यह मॉडल परत के कुछ पहलुओं को काफी सरल बना सकता है।

इस दृष्टिकोण का उपयोग लॉगिन उदाहरण (एपीआई के लिए) के रूप में लिखा जा सकता है:

public function postLogin(Request $request)
{
    $email = $request->get('email');
    $data = [
        'status' => 'ok',
    ];
    try {
        $identity = $this->identification->findIdentityByEmailAddress($email);
        $token = $this->identification->loginWithPassword(
            $identity,
            $request->get('password')
        );
    } catch (FailedIdentification $exception) {
        $data = [
            'status' => 'error',
            'message' => 'Login failed!',
        ]
    }

    return new JsonResponse($data);
}

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

मॉडल कैसे बनाया जाए?

चूंकि एक भी "मॉडल" वर्ग नहीं है (जैसा ऊपर बताया गया है), आप वास्तव में "मॉडल का निर्माण" नहीं करते हैं। इसके बजाय आप सेवाओं को बनाने से शुरू करते हैं, जो कुछ तरीकों को करने में सक्षम हैं। और फिर डोमेन ऑब्जेक्ट्स और मैपर लागू करें।

सेवा विधि का एक उदाहरण:

उपरोक्त दोनों दृष्टिकोणों में पहचान सेवा के लिए यह लॉगिन विधि थी। वास्तव में यह कैसा दिखता है। मैं लाइब्रेरी से एक ही कार्यक्षमता के थोड़ा संशोधित संस्करण का उपयोग कर रहा हूं, जिसे मैंने लिखा था .. क्योंकि मैं आलसी हूं:

public function loginWithPassword(Identity $identity, string $password): string
{
    if ($identity->matchPassword($password) === false) {
        $this->logWrongPasswordNotice($identity, [
            'email' => $identity->getEmailAddress(),
            'key' => $password, // this is the wrong password
        ]);

        throw new PasswordMismatch;
    }

    $identity->setPassword($password);
    $this->updateIdentityOnUse($identity);
    $cookie = $this->createCookieIdentity($identity);

    $this->logger->info('login successful', [
        'input' => [
            'email' => $identity->getEmailAddress(),
        ],
        'user' => [
            'account' => $identity->getAccountId(),
            'identity' => $identity->getId(),
        ],
    ]);

    return $cookie->getToken();
}

जैसा कि आप देख सकते हैं, अमूर्तता के इस स्तर पर, इस बात का कोई संकेत नहीं है कि डेटा कहां से लाया गया था। यह एक डेटाबेस हो सकता है, लेकिन परीक्षण उद्देश्यों के लिए यह सिर्फ एक नकली वस्तु हो सकती है। यहां तक ​​कि डेटा मैपर, जो वास्तव में इसके लिए उपयोग किए जाते हैं, इस सेवा के private तरीकों से छिपे हुए हैं।

private function changeIdentityStatus(Entity\Identity $identity, int $status)
{
    $identity->setStatus($status);
    $identity->setLastUsed(time());
    $mapper = $this->mapperFactory->create(Mapper\Identity::class);
    $mapper->store($identity);
}

मैपर बनाने के तरीके

दृढ़ता के एक अमूर्तता को लागू करने के लिए, सबसे लचीली दृष्टिकोण पर कस्टम डेटा मैपर बनाना है।

से: PoEAA पुस्तक

अभ्यास में वे विशिष्ट वर्गों या सुपरक्लास के साथ बातचीत के लिए लागू किए जाते हैं। मान लें कि आपके पास अपने कोड में Customer और Admin (दोनों User सुपरक्लास से विरासत में हैं)। दोनों अलग-अलग मिलान वाले मैपर होने का अंततः समाप्त हो जाएंगे, क्योंकि उनमें अलग-अलग फ़ील्ड होते हैं। लेकिन आप साझा और सामान्य रूप से प्रयुक्त संचालन के साथ भी समाप्त हो जाएंगे। उदाहरण के लिए: "अंतिम बार देखा गया ऑनलाइन" समय अपडेट करना। और मौजूदा मैपर को अधिक मजबूत बनाने के बजाय, अधिक व्यावहारिक दृष्टिकोण एक सामान्य "उपयोगकर्ता मैपर" होना है, जो केवल उस टाइमस्टैम्प को अपडेट करता है।

कुछ अतिरिक्त टिप्पणियां:

  1. डेटाबेस टेबल और मॉडल

    जबकि कभी-कभी डेटाबेस प्रोजेक्ट, डोमेन ऑब्जेक्ट और मैपर के बीच प्रत्यक्ष 1: 1: 1 संबंध होता है, बड़ी परियोजनाओं में यह अपेक्षाकृत कम आम हो सकता है:

    • एक डोमेन ऑब्जेक्ट द्वारा उपयोग की जाने वाली जानकारी को विभिन्न तालिकाओं से मैप किया जा सकता है, जबकि ऑब्जेक्ट में डेटाबेस में कोई दृढ़ता नहीं है।

      उदाहरण: यदि आप मासिक रिपोर्ट तैयार कर रहे हैं। यह विभिन्न तालिकाओं से जानकारी एकत्र करेगा, लेकिन डेटाबेस में कोई जादुई MonthlyReport तालिका नहीं है।

    • एक एकल मैपर एकाधिक तालिकाओं को प्रभावित कर सकता है।

      उदाहरण: जब आप User ऑब्जेक्ट से डेटा संग्रहीत कर रहे हैं, तो इस डोमेन ऑब्जेक्ट में अन्य डोमेन ऑब्जेक्ट्स का संग्रह हो सकता है - Group उदाहरण। यदि आप उन्हें बदलते हैं और User स्टोर करते हैं, तो डेटा मैपर को एकाधिक तालिकाओं में प्रविष्टियों को अद्यतन और / या सम्मिलित करना होगा।

    • एक डोमेन ऑब्जेक्ट से डेटा एक से अधिक टेबल में संग्रहीत किया जाता है।

      उदाहरण: बड़ी प्रणालियों में (सोचें: एक मध्यम आकार का सोशल नेटवर्क), यह उपयोगकर्ता प्रमाणीकरण डेटा को संग्रहीत करने के लिए व्यावहारिक हो सकता है और अक्सर सामग्री के बड़े हिस्से से अलग-अलग डेटा को एक्सेस किया जा सकता है, जिसे शायद ही कभी आवश्यक है। उस स्थिति में आपके पास अभी भी एक एकल User वर्ग हो सकती है, लेकिन इसमें मौजूद जानकारी इस बात पर निर्भर करेगी कि पूर्ण विवरण प्राप्त किए गए थे या नहीं।

    • प्रत्येक डोमेन ऑब्जेक्ट के लिए एक से अधिक मैपर हो सकते हैं

      उदाहरण: आपके पास सार्वजनिक-सामना और प्रबंधन सॉफ़्टवेयर दोनों के लिए साझा कोडबेस के साथ एक समाचार साइट है। लेकिन, जबकि दोनों इंटरफेस एक ही Article वर्ग का उपयोग करते हैं, प्रबंधन को इसमें बहुत अधिक जानकारी की आवश्यकता होती है। इस मामले में आपके पास दो अलग मैपर होंगे: "आंतरिक" और "बाहरी"। प्रत्येक प्रदर्शन अलग-अलग प्रश्न, या यहां तक ​​कि विभिन्न डेटाबेस (जैसे मास्टर या गुलाम) का उपयोग करते हैं।

  2. एक दृश्य टेम्पलेट नहीं है

    एमवीसी में उदाहरण देखें (यदि आप पैटर्न के एमवीपी भिन्नता का उपयोग नहीं कर रहे हैं) प्रस्तुतिकरण तर्क के लिए जिम्मेदार हैं। इसका मतलब है कि प्रत्येक दृश्य आमतौर पर कम से कम कुछ टेम्पलेट्स को जोड़ देगा। यह मॉडल लेयर से डेटा प्राप्त करता है और फिर प्राप्त जानकारी के आधार पर, एक टेम्पलेट चुनता है और मान सेट करता है।

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

    आप मूल PHP टेम्पलेट्स का उपयोग कर सकते हैं या कुछ थर्ड-पार्टी टेम्पलेटिंग इंजन का उपयोग कर सकते हैं। कुछ तीसरे पक्ष के पुस्तकालय भी हो सकते हैं, जो दृश्य उदाहरणों को पूरी तरह से बदलने में सक्षम हैं।

  3. उत्तर के पुराने संस्करण के बारे में क्या?

    एकमात्र बड़ा परिवर्तन यह है कि, पुराने संस्करण में मॉडल कहलाता है, वास्तव में एक सेवा है । बाकी "पुस्तकालय समानता" बहुत अच्छी तरह से रहता है।

    एकमात्र दोष जो मैं देखता हूं वह यह है कि यह वास्तव में एक अजीब पुस्तकालय होगा, क्योंकि यह आपको पुस्तक से जानकारी वापस कर देगा, लेकिन आपको पुस्तक को स्वयं छूने नहीं देगा, क्योंकि अन्यथा अमूर्तता "रिसाव" शुरू हो जाएगी। मुझे एक और अधिक उपयुक्त समानता के बारे में सोचना पड़ सकता है।

  4. दृश्य और नियंत्रक उदाहरणों के बीच संबंध क्या है?

    एमवीसी संरचना दो परतों से बना है: यूई और मॉडल। यूआई परत में मुख्य संरचनाएं दृश्य और नियंत्रक हैं।

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

    उदाहरण के लिए, एक खुले लेख का प्रतिनिधित्व करने के लिए, आपके पास \Application\Controller\Document और \Application\View\Document । इसमें यूआई परत के लिए सभी मुख्य कार्यक्षमताएं होंगी, जब लेखों से निपटने की बात आती है (बेशक आपके पास कुछ XHR घटक हो सकते हैं जो सीधे लेखों से संबंधित नहीं हैं)


व्यवसाय तर्क है कि सब कुछ एक मॉडल में है, चाहे वह एक डेटाबेस क्वेरी, गणना, एक आरईएसटी कॉल, आदि है।

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

एक अलग ऑब्जेक्ट रखना हमेशा आसान होता है जो वास्तव में मॉडल में निष्पादित किए जाने के बजाय डेटाबेस क्वेरीज़ निष्पादित करता है: यह विशेष रूप से आसान होगा जब यूनिट परीक्षण (आपके मॉडल में नकली डेटाबेस निर्भरता इंजेक्शन की आसानता के कारण):

class Database {
   protected $_conn;

   public function __construct($connection) {
       $this->_conn = $connection;
   }

   public function ExecuteObject($sql, $data) {
       // stuff
   }
}

abstract class Model {
   protected $_db;

   public function __construct(Database $db) {
       $this->_db = $db;
   }
}

class User extends Model {
   public function CheckUsername($username) {
       // ...
       $sql = "SELECT Username FROM" . $this->usersTableName . " WHERE ...";
       return $this->_db->ExecuteObject($sql, $data);
   }
}

$db = new Database($conn);
$model = new User($db);
$model->CheckUsername('foo');

इसके अलावा, PHP में, आपको शायद ही कभी अपवादों को पकड़ने / पुनर्स्थापित करने की आवश्यकता होती है क्योंकि बैकट्रैक संरक्षित है, खासकर आपके उदाहरण की तरह। बस अपवाद को फेंक दें और इसे इसके बजाय नियंत्रक में पकड़ें।


अधिकांशतः अधिकांश अनुप्रयोगों में डेटा, प्रदर्शन और प्रसंस्करण भाग होगा और हम उन सभी को M , V और C अक्षरों में डाल देंगे।

मॉडल ( M ) -> ऐसे गुण हैं जिनमें आवेदन की स्थिति है और यह V और C बारे में कुछ भी नहीं जानता C

देखें ( V ) -> एप्लिकेशन के लिए प्रारूप प्रदर्शित कर रहा है और केवल उस पर मॉडल को कैसे पचाने के बारे में जानता है और C बारे में परेशान नहीं करता C

नियंत्रक ( C ) ----> आवेदन के हिस्से को संसाधित कर रहा है और एम और वी के बीच तारों के रूप में कार्य करता है और यह एम और वी दोनों के विपरीत M , V दोनों पर निर्भर करता है।

कुल मिलाकर प्रत्येक के बीच चिंता का अलगाव होता है। भविष्य में किसी भी बदलाव या संवर्द्धन को बहुत आसानी से जोड़ा जा सकता है।


मेरे मामले में मेरे पास एक डेटाबेस क्लास है जो सभी प्रत्यक्ष डेटाबेस इंटरैक्शन को संभालती है जैसे कि क्वेरीिंग, लांचिंग, और ऐसे। तो अगर मुझे MySQL से PostgreSQL अपना डेटाबेस बदलना पड़ा तो कोई समस्या नहीं होगी। तो जोड़ना कि अतिरिक्त परत उपयोगी हो सकता है।

प्रत्येक तालिका में अपनी कक्षा हो सकती है और इसकी विशिष्ट विधियां हो सकती हैं, लेकिन वास्तव में डेटा प्राप्त करने के लिए, यह डेटाबेस क्लास को इसे संभालने देता है:

फ़ाइल Database.php

class Database {
    private static $connection;
    private static $current_query;
    ...

    public static function query($sql) {
        if (!self::$connection){
            self::open_connection();
        }
        self::$current_query = $sql;
        $result = mysql_query($sql,self::$connection);

        if (!$result){
            self::close_connection();
            // throw custom error
            // The query failed for some reason. here is query :: self::$current_query
            $error = new Error(2,"There is an Error in the query.\n<b>Query:</b>\n{$sql}\n");
            $error->handleError();
        }
        return $result;
    }
 ....

    public static function find_by_sql($sql){
        if (!is_string($sql))
            return false;

        $result_set = self::query($sql);
        $obj_arr = array();
        while ($row = self::fetch_array($result_set))
        {
            $obj_arr[] = self::instantiate($row);
        }
        return $obj_arr;
    }
}

टेबल ऑब्जेक्ट क्लास एल

class DomainPeer extends Database {

    public static function getDomainInfoList() {
        $sql = 'SELECT ';
        $sql .='d.`id`,';
        $sql .='d.`name`,';
        $sql .='d.`shortName`,';
        $sql .='d.`created_at`,';
        $sql .='d.`updated_at`,';
        $sql .='count(q.id) as queries ';
        $sql .='FROM `domains` d ';
        $sql .='LEFT JOIN queries q on q.domainId = d.id ';
        $sql .='GROUP BY d.id';
        return self::find_by_sql($sql);
    }

    ....
}

मुझे आशा है कि यह उदाहरण आपको अच्छी संरचना बनाने में मदद करेगा।


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

विचार करने के लायक एक और बात:

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





php oop model-view-controller architecture model