11

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

मैंने पहले भी मेरे अपने MVC बनाया और php के भीतर OOP का एक उचित समझ है लेकिन मैं जानता हूँ कि मेरी कार्यान्वयन कुछ गंभीर काम करने की जरूरत है।

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

इस मैं की स्थापना की है कि मैं मॉडल की सुविधा देता है के उदाहरण के लिए कहते हैं कि एक व्यक्ति एक इस व्यक्ति वस्तु कुछ बच्चे (मानव बच्चों) कि भी व्यक्ति वस्तुओं एक सरणी में आयोजित (addPerson और removePerson तरीकों के साथ कर रहे हैं हो सकता है बना सकते हैं से, एक व्यक्ति वस्तु स्वीकार करना)।

मैं तो एक PersonMapper है कि मैं एक व्यक्ति को बचाने के लिए एक विशिष्ट 'आईडी' के साथ एक व्यक्ति को पाने के लिए इस्तेमाल कर सकते हैं, या बना सकते हैं।

यह फिर लुकअप टेबल में रिलेशनशिप डेटा देख सकता है और उस व्यक्ति के लिए संबंधित बाल ऑब्जेक्ट्स बना सकता है, जिस पर अनुरोध किया गया है (यदि कोई है) और इसी तरह से सहेजें कमांड पर लुकअप टेबल में डेटा को सेव करें।

यह अब मेरी जानकारी के लिए सीमा धक्का है .....

क्या होगा यदि मैं उन स्तर के भीतर विभिन्न स्तरों और अलग कमरे के साथ एक इमारत मॉडल करने के लिए चाहते थे? अगर मैं उन कमरों में कुछ सामान रखना चाहता था तो क्या होगा?

मैं इमारत, स्तर, कमरे और आइटम

निम्नलिखित संरचना के साथ के लिए एक वर्ग पैदा करेगा।

इमारत 1 या कई स्तर वस्तुओं एक सरणी स्तर में आयोजित 1 या कई कमरे में हो सकता है एक सरणी कमरे में आयोजित वस्तुओं या कई आइटम वस्तुओं एक सरणी में आयोजित

प्रत्येक के लिए

और मानचित्रकारों 1 हो सकता है हो सकता है बच्चों के मैपर्स का उपयोग करके उच्च स्तर के मैपर्स के साथ कक्षा (या तो शीर्ष स्तर की वस्तु या अनुरोध पर आलसी लोड के अनुरोध पर)

यह एक दिशा में यद्यपि अलग-अलग वस्तुओं को कसकर जोड़ता है (यानी एक मंजिल करता है नहीं एक इमारत में होने की जरूरत है, लेकिन एक इमारत का स्तर हो सकता है)

क्या यह चीजों के बारे में जाने का सही तरीका है?

दृश्य के भीतर मैं एक स्तर का चयन करने के विकल्प के साथ एक इमारत दिखाना चाहता हूं और फिर कमरे का चयन करने के विकल्प के साथ स्तर दिखा सकता हूं .. लेकिन मैं वस्तुओं की संरचना जैसे पेड़ भी दिखाना चाहता हूं इमारत और वे किस स्तर और कमरे में हैं।

मुझे उम्मीद है कि यह समझ में आता है। मैं सिर्फ एक दूसरे के भीतर घोंसले की वस्तुओं की अवधारणा के साथ संघर्ष कर रहा हूं जब ओओपी की सामान्य अवधारणा चीजों को अलग करना प्रतीत होता है।

किसी की मदद कर सकते हैं यह वास्तव में उपयोगी होगा।

+0

नेस्टिंग सही लगता है। आप [प्रोग्रामर्स साइट] पर यह एक ही सवाल पूछने का प्रयास हो सकता है (http://programmers.stackexchange.com) – Malachi

+0

साइन नहीं है अपने पोस्ट – Malachi

+0

क्षमा करें कृपया पर हस्ताक्षर करने के पदों के बारे में, भविष्य में ऐसा नहीं होगा। –

उत्तर

0

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

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

+0

का उपयोग कर रहा है http://en.wikipedia.org/wiki/Composition_over_inheritance –

3

यह अब मेरी जानकारी के लिए सीमा धक्का है .....

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

यह कसकर यद्यपि एक ही दिशा में

जोड़ी विभिन्न वस्तुओं को लगता है कि के बारे में गलत कुछ भी नहीं है। असली दुनिया में इमारतों में फर्श, कमरे इत्यादि हैं और आप बस इस तथ्य को मॉडलिंग कर रहे हैं। बच्चे मानचित्रकारों

DDD शब्दावली में का उपयोग कर उच्च स्तर मानचित्रकारों से प्रत्येक वर्ग के लिए

और मानचित्रकारों, इन "मानचित्रकारों" "खजाने" कहा जाता है। इसके अलावा, आपके Building ऑब्जेक्ट को "कुल" माना जा सकता है यदि उसके भीतर सभी फर्श/कमरे/आइटम हैं और यदि इमारत के बिना Room लोड करना समझ में नहीं आता है। उस स्थिति में, आपको केवल एक BuildingRepository की आवश्यकता होगी जो पूरे भवन के पेड़ को लोड कर सके। यदि आप किसी भी आधुनिक ओआरएम लाइब्रेरी का उपयोग करते हैं, तो यह आपके लिए स्वचालित रूप से सभी मानचित्रण कार्य (बच्चे वस्तुओं को लोड करने सहित) करना चाहिए।

+0

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

9

के तुम इतनी तरह अपने वस्तुओं को व्यवस्थित मान लीजिए: enter image description here

आदेश (स्तर, कमरे, आइटम के साथ) पूरी इमारत वस्तु प्रारंभ करने में आप db परत वर्गों काम करने के लिए प्रदान करने के लिए है। सब कुछ आप इमारत के ट्री दृश्य के लिए की जरूरत प्राप्त करने में कठिनाई का एक तरीका यह है:

zoom for better view

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

class RoomMapper implements RoomMapperInterface { 

    public function fetchByLevelIds(array $levelIds) { 
     foreach ($levelIds as $levelId) { 
      $indexedRooms[$levelId] = array(); 
     } 

     //SELECT FROM room WHERE level_id IN (comma separated $levelIds) 
     // ... 
     //$roomsData = fetchAll(); 

     foreach ($roomsData as $roomData) { 
      $indexedRooms[$roomData['level_id']][] = $roomData; 
     } 

     return $indexedRooms; 
    } 

} 

अब मान लीजिए कि हम इस डाटाबेस स्कीमा डालते हैं

enter image description here

और अंत में कुछ कोड।

बिल्डिंग

class Building implements BuildingInterface { 

    /** 
    * @var int 
    */ 
    private $id; 

    /** 
    * @var string 
    */ 
    private $name; 

    /** 
    * @var LevelInterface[] 
    */ 
    private $levels = array(); 

    private function setData(array $data) { 
     $this->id = $data['id']; 
     $this->name = $data['name']; 
    } 

    public function __construct(array $data = NULL) { 
     if (NULL !== $data) { 
      $this->setData($data); 
     } 
    } 

    public function addLevel(LevelInterface $level) { 
     $this->levels[$level->getId()] = $level; 
    } 

    /** 
    * Initializes building data from the database. 
    * If all mappers are provided all data about levels, rooms and items 
    * will be initialized 
    * 
    * @param BuildingMapperInterface $buildingMapper 
    * @param LevelMapperInterface $levelMapper 
    * @param RoomMapperInterface $roomMapper 
    * @param ItemMapperInterface $itemMapper 
    */ 
    public function initializeById(BuildingMapperInterface $buildingMapper, 
      LevelMapperInterface $levelMapper = NULL, 
      RoomMapperInterface $roomMapper = NULL, 
      ItemMapperInterface $itemMapper = NULL) { 

     $buildingData = $buildingMapper->fetchById($this->id); 

     $this->setData($buildingData); 

     if (NULL !== $levelMapper) { 
      //level mapper provided, fetching bulding levels data 
      $levelsData = $levelMapper->fetchByBuildingId($this->id); 

      //indexing levels by id 
      foreach ($levelsData as $levelData) { 
       $levels[$levelData['id']] = new Level($levelData); 
      } 

      //fetching room data for each level in the building 
      if (NULL !== $roomMapper) { 
       $levelIds = array_keys($levels); 

       if (!empty($levelIds)) { 
        /** 
        * mapper will return an array level rooms 
        * indexed by levelId 
        * array($levelId => array($room1Data, $room2Data, ...)) 
        */ 
        $indexedRooms = $roomMapper->fetchByLevelIds($levelIds); 

        $rooms = array(); 

        foreach ($indexedRooms as $levelId => $levelRooms) { 
         //looping through rooms, key is level id 
         foreach ($levelRooms as $levelRoomData) { 
          $newRoom = new Room($levelRoomData); 

          //parent level easy to find 
          $levels[$levelId]->addRoom($newRoom); 

          //keeping track of all the rooms fetched 
          //for easier association if item mapper provided 
          $rooms[$newRoom->getId()] = $newRoom; 
         } 
        } 

        if (NULL !== $itemMapper) { 
         $roomIds = array_keys($rooms); 
         $indexedItems = $itemMapper->fetchByRoomIds($roomIds); 

         foreach ($indexedItems as $roomId => $roomItems) { 
          foreach ($roomItems as $roomItemData) { 
           $newItem = new Item($roomItemData); 
           $rooms[$roomId]->addItem($newItem); 
          } 
         } 
        } 
       } 
      } 

      $this->levels = $levels; 
     } 
    } 

} 

स्तर

class Level implements LevelInterface { 

    private $id; 
    private $buildingId; 
    private $number; 

    /** 
    * @var RoomInterface[] 
    */ 
    private $rooms; 

    private function setData(array $data) { 
     $this->id = $data['id']; 
     $this->buildingId = $data['building_id']; 
     $this->number = $data['number']; 
    } 

    public function __construct(array $data = NULL) { 
     if (NULL !== $data) { 
      $this->setData($data); 
     } 
    } 

    public function getId() { 
     return $this->id; 
    } 

    public function addRoom(RoomInterface $room) { 
     $this->rooms[$room->getId()] = $room; 
    } 

} 

कक्ष

class Room implements RoomInterface { 

    private $id; 
    private $levelId; 
    private $number; 

    /** 
    * Items in this room 
    * @var ItemInterface[] 
    */ 
    private $items; 

    private function setData(array $roomData) { 
     $this->id = $roomData['id']; 
     $this->levelId = $roomData['level_id']; 
     $this->number = $roomData['number']; 
    } 

    private function getData() { 
     return array(
      'level_id' => $this->levelId, 
      'number' => $this->number 
     ); 
    } 

    public function __construct(array $data = NULL) { 
     if (NULL !== $data) { 
      $this->setData($data); 
     } 
    } 

    public function getId() { 
     return $this->id; 
    } 

    public function addItem(ItemInterface $item) { 
     $this->items[$item->getId()] = $item; 
    } 

    /** 
    * Saves room in the databse, will do an update if room has an id 
    * @param RoomMapperInterface $roomMapper 
    */ 
    public function save(RoomMapperInterface $roomMapper) { 
     if (NULL === $this->id) { 
      //insert 
      $roomMapper->insert($this->getData()); 
     } else { 
      //update 
      $where['id'] = $this->id; 
      $roomMapper->update($this->getData(), $where); 
     } 
    } 

} 

आइटम

class Item implements ItemInterface { 

    private $id; 
    private $roomId; 
    private $name; 

    private function setData(array $data) { 
     $this->id = $data['id']; 
     $this->roomId = $data['room_id']; 
     $this->name = $data['name']; 
    } 

    public function __construct(array $data = NULL) { 
     if (NULL !== $data) { 
      $this->setData($data); 
     } 
    } 

    /** 
    * Returns room id (needed for indexing) 
    * @return int 
    */ 
    public function getId() { 
     return $this->id; 
    } 

}