2009-07-09 14 views
14

मुझे एहसास हुआ है, हालांकि मेरे अधिकांश अनुभवों में PHP अनुप्रयोगों को लिखने में शामिल है, लेकिन मुझे समय-समय पर "शुरुआती गलतियों" मिलते हैं। ऐसा इसलिए है क्योंकि PHP एक ऐसी भाषा है जो बहुत व्यवस्थित रूप से उगाई गई है और इस तरह के कुछ idiosyncrasies, quirks और pitfalls है जो मुझे नहीं पता है।PHP quirks और pitfalls

मैं यह प्रश्न उन सभी लोगों के लिए विकी बनना चाहता हूं जो PHP के नुकसान और अपवादों को जानना चाहते हैं जो हम मान सकते हैं नियम हैं। लेकिन कृपया, जैसे सामान्य प्रतिक्रियाएं नहीं लिखते:

कुछ काम करता है, $needle, $haystack के रूप में तर्क प्राप्त $haystack, $needle के रूप में कुछ है।

फ़ंक्शन नाम बताएं। उदाहरण के रूप में आपके पास मेरे कुछ जवाब हैं। ओह, और प्रति जवाब एक pitfall जोड़ें। इस तरह हम देखेंगे कि उनमें से सबसे ज्यादा तुच्छ कौन है (मतदान करके)।

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

उम्मीद है कि यह विकी हम सभी, शुरुआती और विशेषज्ञों के लिए मददगार होगा।

अद्यतन:

एंड्रयू मूर की टिप्पणी के बाद मैं सोच रहा हूँ कि इस सवाल का जवाब भी ख़तरा के लिए एक समाधान या वैकल्पिक हल शामिल करना चाहिए।

+0

php 5.3.3 के रूप में आप नामस्थान का उपयोग करते समय क्लास नाम को कन्स्ट्रक्टर नाम के रूप में उपयोग नहीं कर सकते हैं। आपको '__construct' का उपयोग करना होगा। कोई चेतावनी जारी नहीं की जाएगी, लेकिन 'नया MyClass' को कॉल करने से आपके कन्स्ट्रक्टर में कोड निष्पादित नहीं होगा। एक अच्छा pitfall के लिए Hurray। – nus

उत्तर

1

हालांकि स्ट्रिंग्स को for लूप और इंडेक्स का उपयोग करके पुनरावृत्त किया जा सकता है, उन्हें foreach लूप का उपयोग करके पुनरावृत्त नहीं किया जा सकता है। उदाहरण:

$str = 'foo'; 
$max = strlen($str); 

for ($i=0; $i<$max; $i++) { 
    echo $str[$i]; 
} 
// outputs: foo 

foreach ($str as $char) { 
    echo $char; 
} 
// Warning: Invalid argument supplied for foreach() ... 
+4

foreach (str_split ($ str) AS $ char) {echo $ char; } –

+3

ऐसा इसलिए है क्योंकि तार PHP में वर्णों के सरणी नहीं हैं। लूप के लिए केवल इसलिए काम करता है क्योंकि ब्रैकेट [] एक विशेष चरित्र तक पहुंचने के लिए वाक्य रचनात्मक चीनी हैं। दुर्भाग्यवश यह भी दिखाता है कि तारों को वर्णों के सरणी के रूप में छेड़छाड़ की जा सकती है, जैसा कि आप फोरच लूप में देखते हैं, असत्य है। जैसा कि एंड्रयू ने नोट किया है, str_split() का उपयोग करके इसे वास्तविक सरणी में तोड़ने का एक आसान तरीका है यदि आपको इसकी आवश्यकता है। –

+0

के पास मूल पोस्ट के साथ कुछ लेना देना नहीं है ... – eddy147

10

Serializing वस्तुओं है कि इस प्रक्रिया एक्सएमएल संरचनाओं और फिर unserializing उन्हें मूल XML संरचना को बहाल नहीं करता:

$dom = new DOMDocument; 
$dom->loadXML('<test/>'); 

$dom = serialize($dom); 
$dom = unserialize($dom); 

var_dump($dom->saveXML()); 
// $ Warning: DOMDocument::saveXML(): Couldn't fetch DOMDocument in ... 
// $ NULL 

SimpleXML वस्तुओं के लिए इसी तरह।

8

गैर-उद्योग-मानक ऑपरेटर प्राथमिकता।

$x = 1; 
echo 'foo: ' . $x+1 . ' bar'; 

विल उत्पादन: "1 bar", उम्मीद "foo: 2 bar" के बजाय। समाधान: ब्रांड्स का उपयोग करें।

+7

इको() की कई तर्क लेने की संभावना यहां भी उपयोग की जा सकती है: echo 'foo:', $ x + 1, 'bar'; –

+0

यह ध्यान देने योग्य है कि इसके बारे में * दो * फंकी चीजें हैं: न केवल वही प्राथमिकता है जो आप चाहते थे, बल्कि, ("foo: 1" + 1) संगत नहीं है; यह स्पष्ट रूप से 1 के बराबर है, नहीं "foo: 11"। – ojrac

+4

@ojrac, ऐसा इसलिए है क्योंकि PHP में concatenation ऑपरेटर है। (डॉट), + (प्लस) कई अन्य भाषाओं में नहीं है। + अंकगणितीय जोड़ के लिए प्रयोग किया जाता है और "foo: 1" का मूल्यांकन 1 में करने के लिए 0 को किया जाता है, इस प्रकार अंतिम परिणाम जो 1. –

7

इंटीजर आकार प्लेटफॉर्म पर निर्भर है। आप बिना किसी बाहरी मॉड्यूल के 32 बिट मशीन पर 64 बिट पूर्णांक का उपयोग नहीं कर सकते हैं। इसके अतिरिक्त, आप हस्ताक्षरित पूर्णांक घोषित नहीं कर सकते हैं।

+0

बीसी लाइब्रेरी के लिए है। –

1

मेरी पसंदीदा:

<?php 
$a = 0; 
$b = 'x'; 
var_dump(FALSE == $a); 
var_dump($a == $b); 
var_dump($b == TRUE); 

echo' <br />Conclusion: TRUE equals FALSE (at least in PHP)'; 
+2

यह अन्य स्क्रिप्टिंग भाषाओं में भी दिखाया जा सकता है, न केवल PHP। यह तुलना करने के लिए 'एक्स' को एक पूर्णांक में परिवर्तित करने के साथ क्या करना है। –

+2

== ऑपरेटर डेटा प्रकारों को सहारा देता है। आपको वैसे भी === का उपयोग करना चाहिए। – spoulson

+0

"== ऑपरेटर डेटा को सहकारित करता है ..." हमेशा नहीं, कभी-कभी मैं शून्य, 0, '' के रूप में गलत और अन्य सभी को सच मानना ​​चाहता हूं। –

2

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

मेरा सबसे बड़ी झुंझलाहट short_tags सेटिंग कि <? foobar(); ?> और <?=$var ?> टैग वाक्य रचना के लिए सक्षम बनाता है। मैं तर्क देता हूं कि PHP को ऑप्ट-इन की बजाय डिफ़ॉल्ट रूप से इस सुविधा को सक्षम करना चाहिए था।

== संपादित करें ==

PHP में> = 5.4 short_tags सेटिंग अब आशुलिपि गूंज बयान के लिए ध्यान में रखा जाता है, इस तरह के रूप में यह हर होस्टिंग वातावरण पीएचपी 5.4 का समर्थन करता है कि में उपलब्ध हो जाएगा और अप।

+0

मैं सहमत हूं कि लघु टैग डिफ़ॉल्ट होना चाहिए। – tj111

+7

लघु टैग बुराई हैं। वे एक्सएमएल घोषणा के साथ मिश्रण। आपको इसका उपयोग नहीं करना चाहिए ... –

+2

क्रांतिकारी। एक्सएमएल घोषणा एक बढ़त मामला है। और अगले आप मुझे बताएंगे कि छोटे टैग "पढ़ने के लिए मुश्किल" और कुछ अन्य बकवास हैं। सीधे शब्दों में कहें, " spoulson

8

मुझे नफरत है कि अगर आप ?> समापन टैग (जो ऐसा लगता है कि यह दूसरी तरफ होना चाहिए) के साथ php फ़ाइलों को बंद करते हैं तो आप कैसे समस्याएं प्राप्त कर सकते हैं। उदाहरण के लिए, कुछ सफेद जगहों के साथ एक फ़ाइल शामिल करें?> और उसके बाद हेडर बदलने की कोशिश करें (कोई आउटपुट बफरिंग नहीं मानते)। ऊ। ?>

1

== संपादित करें == यह नहीं रह गया पीएचपी> = 5.5 के लिए सच है के साथ कभी नहीं के करीब php फ़ाइलें जानने के लिए लंबे समय के लिए मुझे रास्ता ले लिया!

क्या मैं कभी कभी में चलाने Fatal error: Can't use function return value in write context त्रुटि empty() निर्माण का उपयोग कर रहा है। उदाहरण के लिए:

if (!empty(trim($_GET['s']))) { 
    // ... 
} 

empty() एक चर की जरूरत है, और कुछ भी त्रुटि का परिणाम देगा।

समाधान:

$s = trim($_GET['s']); 
if (!empty($s)) { 
    // ... 
} 
+1

सरल अभी भी: 'अगर (! ट्रिम करें ($ _ GET [' s ']) {... ' – troelskn

4

बिल्ट-इन कार्य का असंगत नामकरण सम्मेलनों। उदाहरण स्ट्रिंग प्रसंस्करण कार्यों के इस सेट के लिए:

str_shuffle() 
str_split() 
str_word_count() 
strcasecmp() 
strchr() 
strcmp() 

समाधान: हर समय मैनुअल खुला छोड़ दें।

+0

संयोग से, इसका कारण यह है कि वे शुरू में सी स्ट्रेट()' जैसे कार्यों के साथ अनुकरण करने की कोशिश कर रहे थे। और 'strcmp() '। –

0
$x = "a string"; 

if ($x == 142) 
{ 
    echo "lol, of course $x is a number"; 
} 
else 
{ 
    echo "$x is clearly not equal to 142"; 
} 

जब रन:

lol, of course a string is a number 

आप का उपयोग करना चाहिए ===

$x = "a string"; 

if ($x === 142) 
{ 
    echo "lol, of course $x is a number"; 
} 
else 
{ 
    echo "$x is clearly not equal to 142"; 
} 

जब चलाएँ: सत्य परीक्षण करने का

a string is clearly not equal to 142 
+0

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

+0

हाँ, मेरे कोड में इस समस्या को डीबग करने में मुझे कुछ समय लगा। मुझे पता था == coerced डेटा प्रकार लेकिन मुझे नहीं पता था ("एक स्ट्रिंग" == 234) सच का मूल्यांकन करेगा !! – Tyler

+3

क्षमा करें, लेकिन यह सच नहीं है। "एक स्ट्रिंग" == 142 गलत का मूल्यांकन करेगा। http://ch.php.net/manual/en/types.comparisons.php –

7

एकाधिक तरीके (0,123,, empty(), is_null(), isset()) + कमजोर टाइपिंग = this

कुछ अनुशासन के साथ आप ज्यादातर इस तालिका को संदर्भित करने के आवश्यकता से बचने कर सकते हैं:

  • सामान्य सच्चाई परीक्षण के लिए, आप बूलियन तुलना if ($) उपयोग कर सकते हैं {...} if (!$x) { ... }। यह अधिकांश भाषाओं में बुलियन ऑपरेटर के तरीके से व्यवहार करता है।

  • यदि आप गलत मूल्यों के लिए फॉर्म इनपुट का परीक्षण करना चाहते हैं तो यह हमेशा empty() का उपयोग करें (यह "0" को झूठा मानता है)।

  • हमेशा isset() उपयोग करें यदि आप या निर्धारित करने के लिए whethere एक चर सेट किया गया है चाहता हूँ नहीं

  • उपयोग is_null() या $x === NULL अगर आप केवल शून्य

6

मैं सभी प्रकार लिया है के लिए जांच करने की आवश्यकता संदर्भों के साथ foreach संयोजन परेशान

$testarray = array(1 => "one", 2 => "two"); 
$item = "three"; 
$testarray[3] =& $item; 
foreach ($testarray as $key => $item) { 
    // do nothing 
} 
echo $testarray[3]; // outputs "two" 

यह वास्तव में मुझे बंद कर दिया PHP4 युग, और यदि आप स्पष्ट संदर्भों का उपयोग नहीं करते हैं तो यह PHP5 में बेहतर हो गया है, फिर भी मैं अब और उसके बाद इसे पकड़ने का प्रबंधन करता हूं।

+0

क्या आप जानते हैं कि हुड के नीचे क्या चल रहा है? मैं उत्सुक हूं कि PHP यह क्यों देता है। – Harijoe

+1

= और असाइनमेंट सरणी में अंतिम प्रविष्टि $ आइटम चर के संदर्भ में बनाता है। फोरैच लूप के प्रत्येक पुनरावृत्ति पर इसका मतलब है कि $ testarray [3] $ आइटम का वर्तमान मूल्य होने के लिए परिवर्तन करता है। चूंकि $ testarray [2] "दो" है, यह मान $ testarray [3] से अधिक होने पर जारी रहता है, और यह $ testarray का अंतिम मान रहता है [3] –

2

कार्य करने के बाद विभिन्न ओएसई पर अलग-अलग व्यवहार होते हैं, और कुछ फ़ंक्शंस केवल विशिष्ट ओएस पर उपलब्ध होते हैं।

उदाहरण के लिए, mail() विंडोज पर फ़ंक्शन $to पैरामीटर में प्रेषक का नाम नहीं ले सकता है। इसमें केवल ईमेल पता हो सकता है। लिनक्स पर सभी ठीक काम करता है।

एक और उदाहरण, फ़ंक्शन strptime() केवल लिनक्स पर उपलब्ध है, न कि विंडोज़ (यह मुझे एक मौजूदा प्रोजेक्ट में मिला है जिसे मैं अपने विंडोज बॉक्स पर चलाने के लिए चाहता था)।

निश्चित रूप से, कुछ ऐसे कार्य हैं जो केवल कुछ ओएस (जैसे Win32API फ़ंक्शंस) पर समझ में आते हैं, लेकिन कई अन्य ऐसा लगता है कि उन्हें सभी ओएस पर समान व्यवहार करना चाहिए, वास्तव में जब वे नहीं करते हैं।

+0

'exec() 'परिवार इस श्रेणी में मेरा पसंदीदा है। –

2

कभी-कभी आप फ़ंक्शन-परिणाम को किसी अन्य फ़ंक्शन पर सीधे पास करना पसंद करते हैं, जो केवल इनपुट के रूप में चर स्वीकार करता है।

उदाहरण के लिए:

array_pop( explode('\\', get_class($this)) ) 

... एक E_STRICT-त्रुटि "केवल चर संदर्भ द्वारा पारित किया जाना चाहिए" का परिणाम देगा। फोन करने से

array_pop((explode('\\', get_class($this)))) 

(अपने नामस्थान और बढ़ाया वर्गों का उपयोग कर रहे हैं, इस लाइन केवल वर्ग के नाम (नाम स्थान के बिना रिटर्न): यह सिर्फ भीतरी आसपास कोष्ठक की एक और जोड़ी जोड़ने के काम कर रहे हो करने के लिए (लौटे) बयान ऑब्जेक्ट-पैरेंट-क्लास जो विस्तारित नहीं था और इस फ़ंक्शन को पकड़ सकता है।)

+0

बस इस त्रुटि का सामना करना पड़ा। समाधान के लिए धन्यवाद। वैसे, अतिरिक्त ब्रैकेट को PHPStorm द्वारा सही के रूप में पहचाना नहीं जाता है। पीएस: इस समस्या को '\ ReflectionObject' और' getName() 'विधि का उपयोग करके भी हल किया जा सकता है। – Kirzilla