2009-05-06 17 views
26

मैं हाल ही में सबसे खराब PHP प्रथाओं पर this thread पढ़ रहा था। दूसरे उत्तर में extract() के उपयोग पर एक मिनी चर्चा है, और मैं बस सोच रहा हूं कि सभी हफ क्या है।निकालने के साथ इतना गलत क्या है()?

मैं व्यक्तिगत रूप से $_GET या $_POST जैसे किसी दिए गए सरणी को काटने के लिए इसका उपयोग करता हूं, जहां मैं बाद में चर को स्वच्छ करता हूं, क्योंकि उन्हें आसानी से मेरे लिए नामित किया गया है।

क्या यह बुरा अभ्यास है? यहां जोखिम क्या है? extract() के उपयोग पर आपके विचार क्या हैं?

+3

का उपयोग करने के लिए सुरक्षित है, बाद में नहीं। – GZipp

+0

$ _GET या $ _POST पर इसका उपयोग करने का आपका उदाहरण संभवतः क्यों लोग इसके खिलाफ हैं। PHP डेवलपर्स ने 'register_globals' को हटा दिया क्योंकि यह सुरक्षा समस्याओं का कारण बनता है और इन निकालने/हटाए गए व्यवहार को निकालने में उन्हें निकाला जाता है। (जानना अच्छा है कि क्या आपके पास कुछ पुराना कोडबेस है, आपको वास्तव में अपग्रेड करने के लिए परेशान नहीं किया जा सकता है।) – TecBrat

+0

आप इसे देख सकते हैं: http://stackoverflow.com/questions/5306498/php-is-there-a-safe-way -to-extract-post # answer-5306543 और यह जानने के लिए कि कौन से निकालने के नियम आपके लिए सबसे अच्छे हैं, यह जांचें: https://phptutors.wordpress.com/2013/04/17/php-extract-function-example/ –

उत्तर

56

मुझे लगता है कि यह केवल बुरी आदत है जिससे भविष्य में रखरखाव करने वाले कई चर हो सकते हैं (या स्वयं कुछ हफ्तों में) को पता नहीं है कि वे कहां से आ रहे हैं। इस परिदृश्य पर विचार करें:

extract($someArray); // could be $_POST or anything 

/* snip a dozen or more lines */ 

echo $someVariable; 

$someVariable कहां से आया? कोई कैसे बता सकता है?

मैं सरणी के चर तक पहुँचने में समस्या नहीं दिख रहा है वे में शुरू किया था, तो क्या तुम सच में के लिए एक अच्छा मामला पेश करने के लिए extract() का उपयोग करके मुझे यह इसके लायक है सोचने के लिए के लिए आवश्यकता होगी। आप कुछ अतिरिक्त वर्ण टाइप के बारे में वास्तव में चिंतित हैं, तो फिर बस ऐसा करते हैं:

$a = $someLongNameOfTheVariableArrayIDidntWantToType; 

$a['myVariable']; 

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

+4

आप मुझे नहीं बता रहे हैं कि आपको लगता है कि कोई भी वैश्विक दायरे में इसका उपयोग करने के लिए पर्याप्त गूंगा होगा? ... अरे, कुछ लोग शायद हैं। – Kris

+0

निकालें() बहुत उपयोगी है जब आप अनपैक() का उपयोग कर रहे हैं। – cleong

+0

'निकालने' भी एक सीएसवी या एक्सेल फ़ाइल को पार्स करते समय वास्तव में उपयोगी हो सकता है, जहां आप जानते हैं कि प्रत्येक कॉलम में क्या होना चाहिए और प्रत्येक पंक्ति/पंक्ति को मानों की सरणी के रूप में पढ़ा जाता है। हालांकि, मैं आम तौर पर पहले से वर्णित @nickf के कारणों के लिए इसका उपयोग करने से बचता हूं। संक्षेप में: महान शक्ति के साथ बड़ी ज़िम्मेदारी आती है। –

1

जोखिम register_globals के समान ही है। आप हमलावर को अनुरोध के साथ छेड़छाड़ करके, अपनी स्क्रिप्ट में चर सेट करने के लिए सक्षम करते हैं।

+1

superglobals निकालें और आप ठीक हो जाएगा। निकालें एक शक्तिशाली उपकरण है जो सही ढंग से उपयोग किया जाता है। – OIS

+0

"अपने आप को एक तेज छड़ी के साथ आंखों में न दबाएं और आप ठीक हो जाएंगे। एक तेज छड़ी एक शक्तिशाली उपकरण है जब सही ढंग से उपयोग किया जाता है।" - मैं स्क्रिप्ट स्तर पर निकालने ($ _ POST) के उपयोग का जिक्र कर रहा था, जो एक तेज छड़ी के साथ आंखों में खुद को पोक करने के स्पष्ट समकक्ष है। – Tomalak

+0

निकालने के लिए बेवकूफ पीपीएल बेवकूफ चीजों को करने की इजाजत देने के लिए एक बुरा प्रतिनिधि है, लेकिन यह स्मार्ट लोगों को कुछ अच्छी चीजें करने की अनुमति देता है। आप उत्तर में जानकारी की कमी है। आप register_globals के समान जोखिम नहीं लेते हैं या हमलावरों को निकालने का उपयोग करके चर सेट करने की इजाजत नहीं देते हैं। आप अनजाने और अनजाने में निकालने का उपयोग करके ऐसा करते हैं। – OIS

4

मैं कारण बहुत से लोगों को यह है कि निकालने $_GET और $_POST (यहां तक ​​कि $_REQUEST) superglobals उन सरणियों के भीतर प्रत्येक कुंजी है, जो मूल रूप से नकल है के रूप में एक ही नाम के साथ वैश्विक नाम स्थान में चर पंजीकृत करता है उपयोग करने की अनुशंसा नहीं है लगता है REGISTER_GLOBALS = 1.

16

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

<?php 
    $systemCall = 'ls -lh'; 
    $i = 0; 

    extract($_GET); 

    system($systemCall); 

    do { 
     print_r($data[$i]; 
     $i++; 
    } while ($i != 3); 

?> 

(एक अतर्कसंगत उदाहरण)

लेकिन अब एक दुर्भावनापूर्ण उपयोगकर्ता जो अनुमान लगा लेता है या कोड कहता है जानता है:

yourscript.php?i=10&systemCall=rm%20-rf 
बजाय

अब

, $ systemCall और $ i ओवरराइट किया गया है, जिसके परिणामस्वरूप आपकी स्क्रिप्ट पहले आपके डेटा को हटा रही है और फिर लटक रही है।

+4

हालांकि आप इस स्थिति से बचने के लिए EXTR_SKIP का उपयोग कर सकते हैं। – nickf

9

इसमें कुछ भी गलत नहीं है। अन्यथा इसे लागू नहीं किया जाएगा। कई (एमवीसी) फ्रेमवर्क इसका उपयोग करते हैं जब आप दृश्यों को चर (असाइन) चर भेजते हैं। आपको बस इसे सावधानीपूर्वक उपयोग करने की आवश्यकता है।निकालने के लिए इसे पार करने से पहले उन सरणी को स्वच्छ करें() और सुनिश्चित करें कि यह आपके चर को ओवरराइड नहीं करता है। यह न भूलें कि यह फ़ंक्शन कुछ और तर्क स्वीकार करता है! दूसरे और तीसरे तर्कों का उपयोग करके यदि टकराव होता है तो आप व्यवहार को नियंत्रित कर सकते हैं। आप उपसर्ग को ओवरराइड, छोड़ या जोड़ सकते हैं। http://www.php.net/extract

+12

"इसमें कुछ भी गलत नहीं है। अन्यथा इसे लागू नहीं किया जाएगा।" .......... ['goto'] (http://us1.php.net/goto), [जादू उद्धरण] (http://www.php.net/manual/en/security.magicquotes.php)। – Travesty3

31

अब चलो। लोग उपयोगकर्ता के बजाए उपकरण को दोष देते हैं।

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

+10

दुर्भाग्यवश, कभी-कभी बुद्धिमानी से कुछ उपयोग करने का एकमात्र तरीका इसका उपयोग नहीं करता है। – Dan

+0

@ डैनलॉग: एक उचित बिंदु :) यह परमाणु बम की तरह कुछ तरीकों से है .. –

+5

@ डैनलॉग, और कभी-कभी सलाह का उपयोग करने का एकमात्र तरीका * "कभी-कभी बुद्धिमानी से उपयोग करने का एकमात्र तरीका इसका उपयोग नहीं करता है" * बुद्धिमानी से इसका उपयोग नहीं करना है। – Pacerier

3

मैं PHP manual मेरे लिए बात कर दूंगा।

पृष्ठभूमि: extract($_REQUEST) php.ini

+1

superglobals निकालें और आप ठीक हो जाएगा। निकालें एक शक्तिशाली उपकरण है जो सही ढंग से उपयोग किया जाता है। – OIS

+1

@ ओआईएस: बशर्ते आप अपने वैकल्पिक पैरामीटर के लिए तर्क पारित करें, मैं सहमत हूं। यह अभी भी आप जो चाहते हैं उसे एक्सेस करने के लिए एक बेहतर विचार की तरह लगता है। – Powerlord

3

में register_globals = On सेटिंग आप एक समारोह में निकालने हैं, तो चर केवल कि दायरे में उपलब्ध हो जाएगा के समान है। यह अक्सर विचारों में प्रयोग किया जाता है। सरल उदाहरण:

//View.php 
class View { 
    function render($filename = null) { 
     if ($filename !== null) { 
      $this->filename = $filename; 
     } 
     unset($filename); 
     extract($this->variables); 
     ob_start(); 
     $this->returned = include($this->dir . $this->filename); 
     return ob_get_clean(); 
    } 
} 

//test.php 
$view = new View; 
$view->filename = 'test.phtml'; 
$view->dir = './'; 
$view->variables = array('test' => 'tset'); 
echo $view->render('test.phtml'); 
var_dump($view->returned); 

//test.phtml 
<p><?php echo $test; ?></p> 
कुछ वैकल्पिक निर्देशिका के साथ

, अगर फ़ाइल मौजूद है और निर्धारित वेरिएबल और तरीकों को देखने के लिए जाँच करता है - आप काफी दोहराया गया है Zend_View।

तुम भी $ this-> outVariables = get_defined_vars जोड़ सकते हैं(); विशिष्ट चर के साथ कोड चलाने के लिए और पुराने PHP कोड के साथ इनका उपयोग करने के परिणाम प्राप्त करें।

1

वैश्विक दायरे में कभी भी निकालें ($ _ GET)। इसके अलावा, इसका उपयोग होता है, जैसे कि एक फ़ंक्शन को कॉल करना (संभावित रूप से) बहुत सारे वैकल्पिक तर्क हो सकते हैं।

यह वर्डप्रेस डेवलपर्स के लिए थोड़ा परिचित दिखना चाहिए:

function widget (Array $args = NULL) 
{ 
    extract($args); 

    if($before_widget) echo $before_widget; 

    // do the widget stuff 

    if($after_widget) echo $after_widget; 
} 

widget(array(
    'before_widget' => '<div class="widget">', 
    'after_widget' => '</div>' 
)); 
5

तो ध्यान से इस्तेमाल नहीं किया यह दूसरों से बाहर बिल्ली के साथ आप काम भ्रमित कर सकते हैं पर विचार करें:

<?php 

    $array = array('huh' => 'var_dump', 'whatThe' => 'It\'s tricky!', 'iDontGetIt' => 'This Extract Function'); 
    extract($array); 
    $huh($whatThe, $iDontGetIt); 


?> 

पैदावार:

string(12) "It's tricky!" 
string(21) "This Extract Function" 

एक obfuscation में उपयोग करने के लिए उपयोगी होगा। लेकिन मैं उस पर नहीं जा सकता "वह var कहाँ से आया?" समस्या जो मैं दौड़ता हूं।

5

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

1

किसी के रूप में एक अलग धागा, here is a safer way to use extract में बताया गया है, केवल यह चर आपके द्वारा निर्दिष्ट निकालने के लिए अनुमति देकर, सब कुछ करने के बजाय सरणी शामिल हैं।

इस दस्तावेजीकरण का एक दोहरे उद्देश्य क्या चर इसे से बाहर आ रहे हैं तो एक चर वापस ट्रैकिंग अभ्यस्त इतना मुश्किल हो कार्य करता है।

-1

निकालने का उपयोग करने के लिए एक अतिरिक्त अच्छा कारण यह नहीं है कि PHP में HHVM का उपयोग करने के लिए PHP में एक गति है जो PHP को 10x तेज करने का दावा कर रहा है। फेसबुक (जिसने इसे बनाया है) इसका उपयोग कर रहा है, विकिपीडिया उस पर है, और वर्डप्रेस को देखने के लिए अफवाह है।

HHVM doesn't allow extract()

यह अभी भी अल्फा की तरह है, तो यह सबसे बड़ा चिंता का विषय

+0

गलत लिंक, यहां यह है और इसे लागू किया गया है: http://docs.hhvm.com/manual/en/function.extract.php –

1

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

यहां तक ​​कि कोडइग्निटर कोर कोड निकालने का भी उपयोग करता है, इसलिए यदि डेटा को स्वच्छ किया गया है और अच्छी तरह से संभाला जाता है तो विधि का उपयोग करने में कोई नुकसान नहीं होना चाहिए।

मैंने EXTR_IF_EXISTS स्विच के साथ कोडइग्निटर मॉडल में निकालने का उपयोग किया है और चर की संख्या को सीमित कर दिया है, यह बहुत अच्छी तरह से काम करता है।

1

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

#Extract only the specified keys. 
$extract=array_intersect_key(
    get_data() 
    ,$keys=array_flip(['key1','key2','key3','key4','key5']) 
); 

#Make sure all the keys exist. 
if ($missing=array_keys(array_diff_key($keys,$extract))) { 
    throw new Exception('Missing variables: '.implode(', ',$missing)); 
} 

#Everything is good to go, you may proceed. 
extract($extract); 

या

#If you don't care to check that all keys exist, you could just do this. 
extract(array_intersect_key(
    get_data() 
    ,array_flip(['key1','key2','key3','key4','key5']) 
)); 
0

पता है कि extract() सुरक्षित अगर आप (अनुरोध के परिणाम की तरह) उपयोगकर्ता डेटा के साथ काम कर रहे हैं नहीं है रहो, तो यह झंडे EXTR_IF_EXISTS और EXTR_PREFIX_ALL के साथ इस समारोह का उपयोग करने के लिए बेहतर है ।

यदि आप इसे सही उपयोग करते हैं, तो यह

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