2009-04-27 18 views
36

सबसे वेब डेवलपर्स इन दिनों, मैं अच्छी तरह से वेब एप्लिकेशन और साइटों का ठोस MVC वास्तुकला के लाभों का आनंद ले रहा हूँ की तरह। PHP के साथ एमवीसी करते समय, ऑटोलोडिंग स्पष्ट रूप से बेहद आसान में आता है।कुशल पीएचपी ऑटो लोड हो रहा है और नामकरण रणनीति

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

उदाहरण के लिए, मान लीजिए कि मैं एक ऐप्स एक आधार पथ PATH_APP रूप में परिभाषित किया है, और models, views और controllers नामित निर्देशिका के साथ एक सरल संरचना है करते हैं। मैं अक्सर एक नामकरण संरचना को नियोजित करता हूं जिससे फाइलों को उपयुक्त निर्देशिका के अंदर IndexView.php और IndexController.php नाम दिया जाता है, और मॉडल में आमतौर पर डिफ़ॉल्ट रूप से कोई विशेष योजना नहीं होती है। मैं इस तरह इस संरचना है कि spl_autoload_register के साथ पंजीकृत हो जाता है के लिए एक लोडर समारोह हो सकता है:

public function MVCLoader($class) 
{ 
    if (file_exists(PATH_APP.'/models/'.$class.'.php')) { 
     require_once(PATH_APP.'/models/'.$class.'.php'); 
     return true; 
    } 
    else if (strpos($class,'View') !== false) { 
     if (file_exists(PATH_APP.'/views/'.$class.'.php')) { 
      require_once(PATH_APP.'/views/'.$class.'.php'); 
      return true; 
     } 
    } 
    else if (strpos($class,'Controller') !== false) { 
     if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) { 
      require_once(PATH_APP.'/controllers/'.$class.'.php'); 
      return true; 
     } 
    } 
    return false; 
} 

यह उस के बाद नहीं मिला है, मैं मॉडल निर्देशिका में उप-निर्देशिका स्कैन करने के लिए एक और समारोह हो सकता है। हालांकि, सभी if/else-ing, स्ट्रिंग जांच और निर्देशिका स्कैनिंग मेरे लिए अक्षम है, और मैं इसे बेहतर बनाना चाहता हूं।

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

उत्तर

28

यह वही मैं अपनी परियोजनाओं के सभी में उपयोग किया गया है (पिछले एक के स्रोत से सीधे उठा लिया) है:

public static function loadClass($class) 
{ 
    $files = array(
     $class . '.php', 
     str_replace('_', '/', $class) . '.php', 
    ); 
    foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path) 
    { 
     foreach ($files as $file) 
     { 
      $path = "$base_path/$file"; 
      if (file_exists($path) && is_readable($path)) 
      { 
       include_once $path; 
       return; 
      } 
     } 
    } 
} 

अगर मैं SomeClass_SeperatedWith_Underscores यह SomeClass के बाद SomeClass_SeperatedWith_Underscores.php के लिए दिखेगा देखने के लिए/SeperatedWith/Underscores.php वर्तमान में प्रत्येक निर्देशिका में रूट पथ शामिल हैं।

संपादित करें: मैं बस वहां बाहर रखना चाहता था कि मैं विकास में दक्षता के लिए इसका उपयोग करता हूं, और आवश्यक समय पर प्रसंस्करण नहीं करता हूं। यदि आपके पास अपने रास्ते पर पियर है तो इसके साथ आप कक्षाओं का उपयोग कर सकते हैं और उन्हें आवश्यकता होने पर उन्हें शामिल करने की आवश्यकता नहीं है।

मैं नामस्थान को तोड़ने को अंडरस्कोर से निर्देशिका के पदानुक्रम में मेरी कक्षाओं रखने के लिए, करते हैं ... इस कोड मुझे फ़ाइल संरचना अच्छा सुथरा रखने अगर मैं चाहता हूँ, या नेस्टेड निर्देशिका अगर बिना एक त्वरित वर्ग फ़ाइल सुई की सुविधा देता है मैं (एक पुस्तकालय उस पर प्रतिवादी, लेकिन परियोजना मैं वर्तमान पर काम कर रहा हूँ का हिस्सा नहीं है कि के लिए एक एकल वर्ग या दो जोड़ने के लिए।) चाहते

+3

ठंडाता के लिए पिंप +1 – Louis

+0

मुझे निश्चित रूप से अंडरस्कोर दृष्टिकोण पसंद है। यह कक्षा-से-फ़ाइल अनुवाद को और अधिक कुशल बनाता है। – zombat

+3

अपनी '$ files' सरणी के आस-पास 'array_unique()' लपेटें। यदि कक्षा के नाम में कोई अंडरस्कोर नहीं है, तो आप प्रत्येक फ़ाइल को दो बार कोशिश कर रहे हैं। – mpen

13

मैं इस समाधान पर उतरा:

मैं एक ही बनाया स्क्रिप्ट जो मेरी कक्षा लाइब्रेरी फ़ोल्डर (जिसमें अलग मॉड्यूल/सिस्टम के लिए उपफोल्डर्स शामिल हैं) को पार करता है, और फ़ाइल परिभाषाओं को कक्षा परिभाषाओं की तलाश में पार्स करता है।

class_name.php -> actual/source/file.php 

यह मैं का एक, आसान autoload समारोह है कि केवल वर्ग के नाम और करने के लिए पथ की जरूरत का उपयोग करने देता है: यह एक php फ़ाइल (बहुत सरल regex पैटर्न) में एक वर्ग परिभाषा मिलते हैं तो वह एक सिमलिंक बनाता है मुख्य सिम्लिंक फ़ोल्डर, और किसी भी पथ/स्ट्रिंग हेरफेर करने की ज़रूरत नहीं है।

सबसे अच्छा हिस्सा यह है कि मैं अपने स्रोत कोड को पूरी तरह से पुनर्व्यवस्थित कर सकता हूं या एक नया उपप्रणाली जोड़ सकता हूं और सबकुछ स्वतः लोड करने के लिए लिंक जनरेटिंग स्क्रिप्ट चला सकता हूं।

+0

शायद यह सबसे रचनात्मक समाधान है जिसे मैंने कभी पार किया है। अच्छी चीज़। जिज्ञासा से बाहर, यह दृष्टिकोण कैसे पार मंच होगा? – zombat

+4

जब से मैंने लिनक्स के साथ काम करना शुरू किया, तब से विंडोज़ के साथ मेरी प्रमुख पकड़ों में से एक सिम्लिंक की कमी रही है। जहां तक ​​मुझे पता है, यह समाधान केवल यूनिक्स के साथ काम करता है। – grossvogel

+5

एफवाईआई, आप विंडोज़ में सिम्लिंक बनाने के लिए 'mklink' का उपयोग कर सकते हैं: http://www.howtogeek.com/howto/windows-vista/using-symlinks-in-windows-vista/ –

7

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

include_once $this->views_path . $class . '.php'; 

आप एक से अधिक "दृश्य" रास्तों की जरूरत है, एक समारोह है कि विचारों को लोड करता है: बिंदु जहां को शामिल होता है पर,

public function load_view($class) { 
    // perhaps there's a mapping here instead.... 
    foreach ($this->views_paths as $path) { 
     $filename = $path . $class . '.php'; 
     if (file_exists($filename)) { 
      include_once $filename; 
     } 
    } 
    throw .... 
} 

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

+10

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

+1

मैं ज़ोंबैट से सहमत हूं। आलस्य एक अच्छी बात हो सकती है - इसे कुशलतापूर्वक काम करने के रूप में भी जाना जाता है। प्रदर्शन के लिए, हार्डवेयर सस्ता है। – rick

+2

यदि आपको उत्पादन को हिट करने के बाद कक्षा का नाम बदलना है, तो आप कोड लिखने से पहले पर्याप्त समय डिजाइन नहीं कर रहे हैं। यदि दक्षता महत्वपूर्ण है, तो अधिक समय व्यतीत करने से पहले आलसी की तुलना में रखरखाव में अनन्त रूप से अधिक समय बचाता है, इसके बारे में सोचने के बारे में सोचें। – jmucchiello

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