2012-08-27 6 views
5

मुझे थोड़ा परिचय शुरू करने दें। मैं PHP में ओओपी सीखने की प्रक्रिया में हूं। मैंने डिज़ाइन पैटर्न का भी शोध किया है लेकिन अभी तक विभिन्न प्रकार की अवधारणाओं को पूरी तरह से समझ नहीं लिया है। मैं मंच पर हूं जहां हर कुछ महीनों में मुझे एहसास होता है कि मैं चीजों को सही तरीके से नहीं कर रहा हूं और अपनी शैली बदलनी है। यह बहुत निराशाजनक है। इसलिए मैं एक बार और सभी के लिए चीजों को करने का सही तरीका खोजना चाहता हूं। मैं पूरी तरह से निम्नलिखित विषयों के बारे में Stackoverflow को पढ़ने की कोशिश की है:PHP में ओओपी प्रोग्रामिंग में अपनी कक्षाएं स्थापित करने का सही तरीका क्या है?

ORM
डाटा मैपर
सिंगलटन
वैश्विक बुराई कर रहे हैं
संबंधित

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

कृपया डुप्लीकेट के रूप में बंद न करें, मैंने ईमानदारी से विषय पर लगभग हर प्रश्न के माध्यम से खोज की है लेकिन मैं अभी भी कुछ चीजें जानना चाहता हूं जिन्हें मैं स्पष्ट करने में सक्षम नहीं हूं। क्षमा करें यह बहुत लंबा है लेकिन मैंने इसे व्यवस्थित करने की कोशिश की है ताकि इसे अच्छी तरह पढ़ा जाए!

मैं अपने डेटाबेस वर्ग के आवश्यक पोस्ट पोस्ट करके शुरू करूंगा।

database.php

<?php 


class DatabaseMySQL{ 

    private static $dbh; 

    public function __construct(){ 
     $this->open_connection(); 
    } 

    public function open_connection(){ 
     if(!self::$dbh){ 
      return (self::$dbh = new PDO(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER,DB_PASSWORD)) ? true : false; 
     } 
     return true; 
    } 

    public function query($sql, $params=array()){ 
     $this->last_query = $sql; 
     $stmt = self::$dbh->prepare($sql); 
     $result = $stmt->execute($params); 
     return $result ? $stmt : $stmt->errorInfo(); 
    } 

    public function fetch_all($results, $class_name=''){ 
     return $results->fetchAll(PDO::FETCH_CLASS, $class_name); 
    } 

} 

?> 

यह मेरा डाटाबेस वर्ग फ़ाइल है। यह वर्ग मुझे इस वर्ग की तरह कई उदाहरण बनाने की अनुमति देता है और यह कक्षा की स्थिर संपत्ति के रूप में संग्रहीत पहले से ही तत्काल पीडीओ ऑब्जेक्ट का पुन: उपयोग करेगा। यह किसी निर्दिष्ट वर्ग की वस्तुओं के रूप में डेटा प्राप्त करने के लिए पीडीओ का उपयोग करके परिणाम सेट से डेटा भी प्राप्त करता है।

मेरी अगली फ़ाइल मेरे पास मेरी कक्षा है जो मेरे सभी अन्य वर्गों से प्राप्त होती है। मैंने इसे मेनमोडेल कहा है। मुझे नहीं पता कि यह सम्मेलन का पालन करता है या नहीं।

MainModel.php

<?php 



abstract class MainModel{ 

    protected static $table; 

    public function __construct($array=array()){ 
     $this->assign_known_properties($array); 
    } 

    public function assign_known_properties($array){ 
     foreach($array as $key=>$value){ 
      $this->$key = $value; 
     } 
    } 

    public static function find_by_id($id){ 
     $db = new DatabaseMySQL(); 
     self::intialise_table_name(); 
     $id = (int) $id; 
     $sql = "SELECT * FROM ".static::$table." "; 
     $sql .= "WHERE id = {$id} ";  
     $result = self::find_by_sql($sql);  
     return array_shift($result); 
    } 

    public static function find_all(){ 
     $db = new DatabaseMySQL(); 
     self::intialise_table_name(); 
     $sql = "SELECT * FROM ".self::$table." "; 
     return self::find_by_sql($sql); 
    } 

    public static function fetch_as_objects($results){ 
     $db = new DatabaseMySQL(); 
     $called_class = get_called_class(); 
     $results = $db->fetch_all($results, $called_class); 
     return $results; 
    } 

    public static function find_by_sql($sql){ 
     $db = new DatabaseMySQL(); 
     $results = $db->query($sql); 
     return $results ? self::fetch_as_objects($results) : false; 
    } 

    public static function intialise_table_name(){ 
     $called_class = get_called_class(); 
     static::$table = strtolower($called_class).'s'; 
    } 

    public function get_table_fields(){ 
     self::intialise_table_name(); 
     $sql = "SHOW FIELDS FROM ".static::$table." "; 
     return self::find_by_sql($sql); 
    } 

    public function set_table_details(){ 
     $fields = $this->get_table_fields(); 
     $total = count($fields); 
     $array = array(); 
     foreach($fields as $object){ 
      $array [] = $object->Field; 
     } 
     $this->table_details = array('objects'=>$fields,'array'=>$array,'total'=>$total); 
     $this->set_placeholders_for_new_record(); 
     $this->set_properties_as_array(); 
     $this->set_properties_as_array(true); 
    } 

    public function set_properties_as_array($assoc=false){ 
     $array = array(); 
     if (!$assoc){ 
      foreach($this->table_details['array'] as $field){ 
       if(isset($this->$field)){ 
        $array [] = $this->$field; 
       }else{ 
        $array [] = NULL; 
       } 
      } 
      $this->table_details['values'] = $array; 
     }else{ 
      foreach($this->table_details['array'] as $field){ 
       if(isset($this->$field)){ 
        $array[$field] = $this->$field; 
       }else{ 
        $array [$field] = NULL; 
       } 
      } 
      $this->table_details['assoc_values'] = $array; 
     } 
    } 

    public function set_placeholders_for_new_record(){ 
     $string = ''; 
     for($i=0; $i<$this->table_details['total']; $i++){ 
      $string .= '? '; 
      if(($i+1) != $this->table_details['total']){ 
       $string .= ", "; 
      } 
     } 
     $this->table_details['placeholders'] = $string; 
    } 

    public function create(){ 
     $db = new DatabaseMySQL(); 
     $this->set_table_details(); 
     $sql = "INSERT INTO ".static::$table." "; 
     $sql .= " VALUES({$this->table_details['placeholders']}) "; 
     $result = $db->query($sql, $this->table_details['values']); 

     // If array is returned then there was an error. 
     return is_array($result) ? $result : $db->insert_id(); 
    } 

    public function update(){ 
     $db = new DatabaseMySQL(); 
     $this->set_table_details(); 
     $sql = "UPDATE ".static::$table." "; 
     $sql .= " SET "; 
      $count = 1; 
      foreach($this->table_details['array'] as $field){ 
       $sql .= "{$field} = :{$field} "; 
       if($count < $this->table_details['total']){ 
        $sql .= ", "; 
       } 
       $count++; 
      } 

     $sql .= " WHERE id = {$this->id} "; 
     $sql .= " LIMIT 1 "; 
     $result = $db->query($sql, $this->table_details['assoc_values']); 
     return $result; 
    } 

    public function save(){ 
     return isset($this->id) ? $this->update() : $this->create(); 
    } 
} 


?> 

इस फाइल को संक्षेप में प्रस्तुत करना। मैं find_by_id($int) जैसे स्थैतिक तरीकों का उपयोग करता हूं जो गतिशील वर्ग की वस्तुओं को गतिशील रूप से उत्पन्न करता है। मैं लेट स्टेटिक बाइंडिंग का उपयोग कर कक्षा के नाम तक पहुंच प्राप्त करने के लिए कर रहा हूं और मैं $stmt->fetchAll(PDO::FETCH_CLASS, $class_name) का उपयोग इन ऑब्जेक्ट्स को तुरंत डेटाबेस में डेटा के साथ स्वचालित रूप से परिवर्तित करने के साथ करने के लिए करता हूं।

प्रत्येक स्थिर विधि में मैं डेटाबेस MySQL क्लास का एक उदाहरण तत्काल करता हूं। प्रत्येक स्थैतिक विधि में मैंने कक्षा का नाम प्राप्त करके और s को जोड़कर SQL क्वेरी में dynmically सही स्टेटिक $table नाम सेट किया है। तो अगर मेरी कक्षा User थी, तो तालिका का नाम users बना देगा।

मेरे कन्स्ट्रक्टर में मैंने एक वैकल्पिक सरणी डाली है जिसे किसी ऑब्जेक्ट के गुणों के रूप में कुछ चर डालने के लिए उपयोग किया जा सकता है। इस तरह सबकुछ गतिशील रूप से किया जाता है जो मुझे मेरे प्रोजेक्ट के अंतिम चरण में छोड़ देता है। मेरी विरासत कक्षाएं।

User.php

class User extends MainModel{ 

} 

Question.php

class Question extends MainModel{ 

} 

क्या अब मैं क्या सरल है। मैं कह सकता हूं:

$user = new User(array('username'=>'John Doe')); 
echo $user->username; // prints *John Doe* 
$user->save(); // saves (or updates) the user into the database. 

मैं उपयोगकर्ता को स्थिर कॉल के साथ उपयोगकर्ता को पुनर्प्राप्त कर सकता हूं।

$user = User::find_by_id(1); 
echo $user->username; // prints users name 

तो अब मेरे सवालों के लिए:

  • 1) क्या नाम तो आप इस डिज़ाइन पैटर्न कहेंगे (अगर यह भी एक बिल्कुल) .Data मैपर है? निर्भरता अन्तःक्षेपण? डोमेन मॉडल (जो कुछ भी है)? डेटा एक्सेस लेयर?

  • 2) जैसा कि अब यह है कि इस कार्यान्वयन को अच्छी तरह से संरचित माना जाता है?

  • 3) यदि यह अच्छा है, तो क्या एक नामकरण सम्मेलन है, मुझे पता होना चाहिए कि मेरे कोड में यह गुम है?

  • 4) यदि यह अच्छा माना जाता है, तो क्या आप यह ध्यान में रखेंगे कि आपको विशेष रूप से क्या पसंद आया है, इसलिए मुझे पता चलेगा कि कौन सा हिस्सा निश्चित रूप से रखना है?

  • 5) यदि आपको नहीं लगता कि यह अच्छा है तो क्या आप एक विस्तृत स्पष्टीकरण देना चाहते हैं ऐसा क्यों है?

  • 6) चाहिए मेरी create, update, delete जो मेरे वस्तुओं के सभी तरीके हैं मेरी find_by_id, find_all जो केवल स्थिर कहा जाता है के रूप में एक ही कक्षा में हो सकता है और वास्तव में वस्तुओं लौट आते हैं। अगर वे दो अलग-अलग वर्गों में होना चाहिए, तो मैं इसके बारे में कैसे जा सकता हूं?

  • 7) $load->('UserClass') का उपयोग करने वाले सभी और क्यों मैपर्स और फैंसी शब्दों का उपयोग करते हैं और अभी तक उन्हें एक बार चाहिए?

+4

यह यहां अधिक फिट बैठता है: http://codereview.stackexchange.com/ –

+1

@IliaRostovtsev धन्यवाद मुझे यह नहीं पता था, लेकिन मैं अभी भी विशेषज्ञों से एक जवाब चाहते हैं और मुझे लगता है कि वे मुख्य रूप से यहां हैं! –

+3

सं।केवल विषयों पर न पढ़ें (और मैं SO को _primary_ संदर्भ के रूप में उपयोग करने से हतोत्साहित करता हूं)। अनुभव प्राप्त करें, अपने हाथ गंदे होने से डरो मत (यह प्रश्न एक अच्छी शुरुआत है, था)। पता है कि कोई काला और सफेद नहीं है। मुझे संदर्भ पता नहीं है लेकिन ग्लोबल्स जरूरी नहीं हैं, अगर दुरुपयोग किया जाता है तो केवल भयानक है। ओआरएम और सिंगलटन के लिए वही बात है, और, सबकुछ, सब कुछ --- कभी-कभी वे अच्छे प्रथाएं हैं लेकिन हमेशा सर्वश्रेष्ठ नहीं होते हैं। – skytreader

उत्तर

1

जिस समाधान के साथ आप आए हैं उसे "Active Record" कहा जाता है; लाभ और कमियों के लिए, आप मार्टिन फाउलर की पुस्तक पैटर्न ऑफ़ एंटरप्राइज़ आर्किटेक्चर के साथ-साथ इंटरनेट पर कई बातचीत देख सकते हैं।

Fwiw, मेरा व्यक्तिगत दृष्टिकोण यह है कि डेटाबेस-संचालित अनुप्रयोगों का निर्माण करने का यह एक बिल्कुल सही तरीका है जहां प्राथमिक व्यवसाय तर्क डेटाबेस को पढ़ रहा है और लिख रहा है; अधिक जटिल व्यापार तर्क बनाते समय यह थोड़ा बोझिल बन जाता है।

इसके अलावा, स्टैक ओवरफ़्लो "कृपया इस विषय पर चर्चा करें" शैली के प्रश्नों के लिए नहीं है - यह उन उत्तरों के लिए है जिनके लिए एक निष्पक्ष सही उत्तर है। तो, आपका प्रश्न 1 फिट बैठता है, लेकिन अन्य SO के लिए वास्तव में उपयुक्त नहीं हैं ...

+0

धन्यवाद लेने के लिए नेविल धन्यवाद, मैंने नहीं सोचा था कि मेरा प्रश्न इस विषय शैली पर चर्चा, सवाल 3 और प्रश्न 6 के बारे में क्या था? –

+0

@InGoditrust शायद आपको भगवान से पूछना चाहिए = पी। ठीक है, मैं 3 और 6 का जवाब दूंगा: नामकरण सम्मेलन और नेमस्पेसिंग के लिए [पीएसआर -0] (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) के बारे में पढ़ें , जो अभी मानक है। अपने तरीकों के बारे में, उन सभी को एक ही कक्षा में रखना ठीक है। आपको डीबीएएल को ओआरएम से अलग करने के बारे में भी सोचना चाहिए। आपको क्वेरी भाग भाग, और इकाई/संबंध भाग से कनेक्शन भाग को अलग करना चाहिए। यह सीखने के लिए सब अच्छा है, मैंने इसे भी किया है। लेकिन वास्तविक परियोजनाओं के लिए आपको डॉक्टरेट 2 या सिम्फनी 2 जैसी अच्छी तरह से परीक्षण की गई पुस्तकालयों का उपयोग करना चाहिए। – ChocoDeveloper

+0

@Choco डेवलपर मैंने उससे पूछा और अभी भी एक उत्तर का इंतजार कर रहा हूं। सुझावों के लिए धन्यवाद, आपके द्वारा दिया गया महान लिंक! –

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