2008-12-11 11 views
10

के लिए सबसे अच्छा समाधान हमारे PHP5 ओओ अनुप्रयोग (आकार और यातायात दोनों में) बढ़ने के बाद, हमने __autoload() रणनीति पर फिर से विचार करने का निर्णय लिया।__autoload

हम हमेशा उस श्रेणी की परिभाषा द्वारा फ़ाइल का नाम देते हैं, इसलिए ग्राहक ग्राहक ग्राहक.php के भीतर निहित होगा। हम उन निर्देशिकाओं को सूचीबद्ध करते थे जिनमें फ़ाइल संभवतः मौजूद हो सकती है, जब तक कि सही .php फ़ाइल नहीं मिली।

यह काफी अक्षम है, क्योंकि आप संभावित रूप से कई निर्देशिकाओं के माध्यम से जा रहे हैं जिनकी आपको आवश्यकता नहीं है, और हर अनुरोध पर ऐसा करना (इस प्रकार, स्टेटस (लोड कॉल) लोड करना)।

समाधान है कि मेरे मन के लिए आते हैं ...

एक नामकरण परंपरा है कि (नाशपाती के समान) निर्देशिका का नाम तय प्रयोग। नुकसान: बहुत बड़ा पैमाने पर नहीं होता है, जिसके परिणामस्वरूप भयानक वर्ग के नाम होते हैं।

- किसी भी प्रकार की पूर्व-निर्मित सरणी के साथ परिणाम (प्रोपेल इसके __autoload के लिए करता है)। नुकसान: नए कोड के किसी भी तैनाती से पहले पुनर्निर्माण की आवश्यकता है।

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

कोई अन्य समाधान?

उत्तर

0

कोडइग्निटर load_class फ़ंक्शन के साथ कुछ ऐसा करता है। अगर मैं सही ढंग से याद करता हूं, तो यह एक स्थिर कार्य है जिसमें वस्तुओं की एक सरणी होती है। समारोह के लिए कॉल है:


load_class($class_name, $instansiate); 
तो अपने मामले


load_class('Customer', TRUE); 

में

और इस वस्तुओं सरणी में ग्राहक वर्ग का एक उदाहरण लोड होगा।

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

-1

क्या आपने Zend_Loader (registerAutoload() के साथ) केवल मूल __autoload() के बजाय जांच की है? मैंने ज़ेंड_लोडर का उपयोग किया है और इसके साथ खुश हूं, लेकिन इसे प्रदर्शन परिप्रेक्ष्य से नहीं देखा है। हालांकि, this blog post ने कुछ प्रदर्शन विश्लेषण किया है; आप अपने परिणामों को अपने वर्तमान ऑटोलोडर पर अपने इन-हाउस प्रदर्शन परीक्षण में तुलना कर सकते हैं यह देखने के लिए कि क्या यह आपकी अपेक्षाओं को पूरा कर सकता है।

2

मैं कुछ समय के लिए ऑटोलोड के साथ भी खेल रहा हूं, और मैंने कुछ प्रकार के नामांकित ऑटोलोडर को लागू किया (हाँ, यह PHP5.2 के लिए भी काम करता है)।

रणनीति काफी सरल है: सबसे पहले मेरे पास सिंगलटन क्लास (लोडर) है जिसमें एक कॉल है जो import अनुकरण करता है। यह कॉल एक पैरामीटर (पूर्ण वर्ग नाम लोड करने के लिए) लेता है और आंतरिक रूप से उस फ़ाइल नाम की गणना करता है जिसे इसे से कॉल किया गया था (debug_backtrace() का उपयोग करके)।कॉल इस जानकारी को बाद में इसका उपयोग करने के लिए एक सहयोगी सरणी में संग्रहीत करता है (कुंजी के रूप में कॉलिंग फ़ाइल का उपयोग करके, और प्रत्येक कुंजी के लिए आयातित कक्षाओं की एक सूची)।

<?php 

    loader::import('foo::bar::SomeClass'); 
    loader::import('foo::bar::OtherClass'); 

    $sc = new SomeClass(); 

?> 

जब autoload निकाल दिया जाता है, पूर्ण वर्ग के नाम है कि सरणी में जमा हो गया था (डबल कोलन निर्देशिका विभाजक के साथ प्रतिस्थापित कर रहे हैं) एक वास्तविक फाइल सिस्टम स्थान में बदल जाता है, और:

विशिष्ट कोड इस तरह दिखता है परिणामी फ़ाइल नाम शामिल है।

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

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

+6

ऑटोलोड के दो बड़े फायदे हैं 1) उन्हें उपयोग करने से पहले कक्षाओं को मैन्युअल रूप से लोड नहीं करना है और 2) फाइल सिस्टम में अपने स्थानों को हार्ड कोडिंग नहीं करना है। आपने दोनों को पूर्ववत कर दिया है। – Preston

+0

यदि आपका प्रोजेक्ट कुछ कक्षाओं का उपयोग करता है तो आप सही हो सकते हैं, लेकिन बड़ी ओओ परियोजनाओं के लिए आपको दूसरे समाधान में जाना होगा। कल्पना करें कि एक विशाल ढांचे की सभी निर्देशिकाओं के माध्यम से एक वर्ग के लिए PHP खोज रहे हैं। बिना किसी प्रकार के आयात संकेतों के बहुत खराब। – azkotoki

0

यदि आप एपीसी का उपयोग कर रहे हैं, तो आपको ऑपोड कैशिंग सक्षम करना चाहिए। मेरा मानना ​​है कि प्रदर्शन के लिए इसका अधिक लाभ होगा, और आपके द्वारा नियोजित किसी भी वर्ग/फ़ाइल रणनीति की तुलना में अधिक पारदर्शी समाधान होगा।

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

अपने कक्षाओं के बढ़ते सेट के साथ कुछ प्रदर्शन प्रयोग करें। आपको शायद यह पता चलेगा कि फ़ाइल I/O को कम करने का लाभ इतना महत्वपूर्ण है कि सभी वर्गों को एक फ़ाइल में एक साथ भरना एक शुद्ध जीत है, भले ही आपको प्रत्येक अनुरोध के दौरान सभी कक्षाओं की आवश्यकता न हो।

+0

बेशक मैं ओपोड कैशिंग का उपयोग करता हूं। यह सिर्फ इतना है कि एपीसी आपको कई बार स्टेट() को कॉल करने से नहीं रोकता है, क्योंकि यह केवल आवश्यकता() पर हस्तक्षेप करता है। – tpk

+0

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

+0

क्या आपने प्रदर्शन को माप लिया है और परिणामों की तुलना की है, या आप सिर्फ एक शिक्षित अनुमान बना रहे हैं? –

1

2 सामान्य दृष्टिकोण हैं जो अच्छी तरह से काम करते हैं।
पहले पीयर मानक श्रेणी नामकरण संरचना का उपयोग कर रहा है, इसलिए आपको कक्षा को खोजने के लिए '_' को प्रतिस्थापित करने की आवश्यकता है।

http://pear.php.net/manual/en/pear2cs.rules.php

या आप php वर्गों और नक्शा वर्ग के नाम दर्ज करने के लिए के लिए निर्देशिका खोज सकते हैं। आप प्रत्येक पृष्ठ लोड खोज निर्देशिका को सहेजने के लिए कक्षा मानचित्र को कैश में सहेज सकते हैं।
सिम्फनी ढांचा उन दृष्टिकोणों का उपयोग करता है।

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

-3
function __autoload($class) 
{ 
    $patterns = array('%s.class.php', '%s.interface.php'); 

    foreach(explode(';', ini_get('include_path')) as $dir) 
    { 
     foreach($patterns as $pattern) 
     { 
      $file = sprintf($pattern, $class); 
      $command = sprintf('find -L %s -name "%s" -print', $dir, $file); 
      $output = array(); 
      $result = -1; 

      exec($command, $output, $result); 

      if (count($output) == 1) 
      { 
       require_once($output[ 0 ]); 
       return; 
      } 
     } 
    } 

    if (is_integer(strpos($class, 'Exception'))) 
    { 
     eval(sprintf('class %s extends Exception {}', $class)); 
     return; 
    } 

    if (! class_exists($class, false)) 
    { 
     // no exceptions in autoload :(
     die(sprintf('Failure to autoload class: "%s"', $class)); 
     // or perhaps: die ('<pre>'.var_export(debug_backtrace(), true).'</pre>');   
    } 
} 

आप निर्देशिकाओं को पुन: सक्रिय करने के लिए कुछ अन्य, कम पॉज़िक्स निर्भर तरीके भी पा सकते हैं, लेकिन यह वही है जो मैं उपयोग कर रहा हूं।

यह कक्षा या इंटरफ़ेस खोजने के लिए include_path (php.ini या .htaccess में सेट) में सभी निर्देशिकाओं को पार करता है।

+2

ओएमजी, यह भयानक है। प्रत्येक PHP अनुरोध पर, आप जो भी कक्षा लोड करते हैं, उसके लिए INCLUDE_PATH में प्रत्येक डीआईआर के लिए 'ढूंढें' कहें?! –

+0

और आपका पथ विभाजक ';' है (जिसका अर्थ है कि यह कोड केवल विंडोज़ पर चलता है) लेकिन आप 'find' जैसे पॉज़िक्स टूल पर भरोसा करते हैं? –

+0

मैं सहमत हूं ... यह बेहद अक्षम है। File_exists() क्यों नहीं? फिलहाल हमारे पास यही है। – tpk

1

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

1

मैंने अतीत में इस समाधान का उपयोग किया है, मैंने संदर्भ के लिए इसके बारे में ब्लॉग किया है और आप में से कुछ के लिए दिलचस्प हो सकता है ...

Here it is

0

मैं, प्रत्येक वर्ग की 'प्रकार' (नियंत्रक, मॉडल, पुस्तकालय फ़ाइलें, और इतने पर ...) के लिए विशिष्ट नामकरण सम्मेलनों है, इसलिए वर्तमान में मैं करने के लिए कुछ इसी तरह कार्य करें:

function __autoload($class){ 
    if($class matches pattern_1 and file_exists($class.pattern_1)){ 
     //include the file somehow 
    } elseif($class matches pattern_2 and file_exists($class.pattern_2)){ 
     //include the file somehow 
    } elseif(file_exists($class.pattern_3)){ 
     //include the file somehow 
    } else { 
     //throw an error because that class does not exist? 
    } 
} 
0

पुराना धागा लेकिन मैंने सोचा कि मैं अपनी विधि का खुलासा कर सकता हूं, शायद यह किसी की मदद कर सकता है। इस तरह से मैं उदाहरण के लिए मेरी वेबसाइट प्रवेश बिंदु /path/to/root/www/index.php में __autoload() परिभाषित है:

function __autoload($call) { 
    require('../php/'.implode('/', explode('___', $call)).'.php'); 
} 

सभी PHP फ़ाइलों एक पेड़ में आयोजित कर रहे हैं

 
/path/to/root/php 
    /Applications 
    /Website 
     Server.php 
    /Model 
    User.php 
    /Libraries 
    /HTTP 
     Client.php 
    Socket.php 

और कक्षाओं नाम हैं:

 
Applications___Website___Server 
Model___User 
Libraries___HTTP___Client 
Libraries___Socket 

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

एनबी: यह PHP 5 < 5.3 के लिए था, इसलिए पीएचपी 5.3 के लिए आप नामस्थान का उपयोग कर सकते, कारण है कि मैं 3 _ इस्तेमाल किया विभाजक के रूप में है कि यह एक आसान प्रतिस्थापन 5.3 नाम स्थान के लिए क्या करने का उपयोग है

0
function __autoload($class_name) { 
    $class_name = strtolower($class_name); 
    $path  = "../includes/{$class_name}.php"; 
    if (file_exists($path)) { 
     require_once($path); 
    } else { 
     die("The file {$class_name}.php could not be found!"); 
    } 
}