2010-07-18 13 views
12

मैं PHP कोड के बहुत अजीब बिट पर ठोकर खाई। क्या कोई यह समझा सकता है कि यह क्यों हो रहा है? ***** बोनस अंक ***** यदि आप मुझे बता सकते हैं कि यह क्यों उपयोगी है।बहुत ही अजीब PHP मूल्य तुलना

<?php 
if(0=='a'){ 
    print ord(0)." should NEVER equal ".ord('a')."<br>"; 
} 
if(false==0){ 
     print "false==0<br>"; 
} 
if('a'==false){ 
     print "a==false<br>"; 
} 
?> 

और जिसके परिणामस्वरूप उत्पादन: तो पीएचपी '0' में 0 बदल जाता है

48 should NEVER equal 97 
false==0 
+1

बस जावास्क्रिप्ट की तरह, विभिन्न प्रकारों के बीच तुलना संक्रमणशील नहीं हो सकती है। वह प्रकार जबरदस्ती का डरावना है। – JAL

उत्तर

33

PHP में, 'ए' ASCII वर्ण नहीं है, लेकिन स्ट्रिंग ए है। एक संख्यात्मक संदर्भ में, यह 0 के बराबर है। उदाहरण के लिए intval('a')0 के मान में परिणाम देता है।

यह उपयोगी है क्योंकि PHP मुख्य रूप से पाठ संसाधित करने के लिए उपयोग किया जाता है, और कोई परीक्षण (123 == '123') का प्रयास करना चाहता है, जो सच है। और यह देखते हुए कि सिंगल (या डबल) उद्धरण चिह्नों में एक संख्या को संख्या के रूप में माना जाता है, यह किसी स्ट्रिंग के लिए समझ में नहीं आता है, जिसमें कोई संख्यात्मक मान 0 से अधिक नहीं है।

ओह हाँ, एक और चीज़। एक बूलियन संदर्भ में 'ए' सच है, झूठी नहीं। मेरा मानना ​​है कि इससे कुछ प्रकार की टेक्स्ट प्रसंस्करण अधिक प्राकृतिक हो जाती है, लेकिन मैं ईमानदारी से इस देर के समय में एक उदाहरण के बारे में नहीं सोच सकता।

+0

हां, यह 'ए' + 0' लेने जैसा है, क्योंकि 'ए' एक संख्या नहीं है, इसे आसानी से गिरा दिया गया है और 0 में जोड़ा गया है, जिसके परिणामस्वरूप 0 है, क्योंकि इंटीग्रर्स के स्ट्रिंग्स की तुलना में उच्च कास्टिंग प्राथमिकता है। – animuson

+0

***** बोनस अंक ***** से सम्मानित किया गया। जवाब के लिए धन्यवाद। – rook

3

ord(), वर्ण लेता है। और 0false के बराबर है, भले ही यह समान नहीं है (===)।

8

ठीक है, इसके लिए हमेशा PHP type cheat sheet है!

+0

+1 बहुत अच्छा !!! – rook

+0

वाह, मैंने कभी खाली महसूस नहीं किया() मतलब isfalse() और is_null() मतलब isnotset() है। – aib

7

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

Therearerulesforevery कि यह कैसे एक और प्रकार में डाला जाएगा या यह कैसे compares अन्य प्रकार के रूप में type'a' को किसी संख्या (केवल तार्किक पसंद, वास्तव में) पर डालने पर 0 में परिवर्तित किया जाता है। इस प्रकार कास्टिंग से बचने के लिए, समानता ऑपरेटर == के साथ परीक्षण न करें, लेकिन identity operator=== के साथ परीक्षण करें।

James pointed out के रूप में, यह उपयोगी है क्योंकि PHP वास्तव में तारों के साथ बहुत कुछ करता है। उदाहरण के लिए, एचटीएमएल फॉर्म केवल स्ट्रिंग सबमिट करते हैं, भले ही मान एक संख्या हो। यह भी तरह, कुछ वास्तव में संक्षिप्त कोड के लिए अनुमति देता है: जिसमें परिस्थितियों हालांकि

$result = someOperation(); 
if (!$result) { 
    // $result may be null, false, 0, '' or array(), 
    // all of which we're not interested in 
    error(); 
} 

इसका यह भी मतलब है कि तुम क्या जांच करने के लिए के बारे में वास्तव में सावधान रहना होगा, क्योंकि एक मूल्य के अप्रत्याशित रूप से कुछ और ही में डाला हो सकता है। और स्वीकार्य रूप से, 'a' == 0 अपने आप में वास्तव में मददगार के बजाय प्रकार की जॉगिंग का एक झगड़ा है। यह उन परिस्थितियों में से एक है जहां आपको सावधान रहना होगा और if (is_numeric($var) && $var == 0) जैसे परीक्षण करना होगा।

1

मैनुअल से PHP type comparison tables देखें। जब तक आप इसे आंतरिककृत नहीं कर लेते हैं, तब तक यह वास्तव में आसान काम है और यह समझने के लिए अमूल्य रहा है कि वास्तव में क्या मूल्यांकन किया जाएगा और कब।

अन्य लोगों ने पहले से ही प्रश्न के मूल का उत्तर दिया है, लेकिन मुझे लगता है कि यह कहना महत्वपूर्ण है कि PHP में, एकमात्र गैर-खाली स्ट्रिंग जो == ऑपरेटर के साथ "सत्य" का मूल्यांकन नहीं करती है, PHP के रूप में "0" है किसी भी स्ट्रिंग का इलाज केवल एक संख्या या पूर्णांक के रूप में होता है।

इसके लिए तर्क यह है कि PHP काफी कम टाइप किया गया है और पूर्णांक, स्ट्रिंग्स, फ्लोट्स और बूलियन मानों को अदला-बदली करने की अनुमति देता है। इसका एक असली दुनिया और बेहद आम उदाहरण यह है कि यदि आप MySQL या PDO फ़ंक्शंस का उपयोग कर रहे हैं, तो सब कुछ के लिए स्ट्रिंग लौटा दी जाती है, भले ही अंतर्निहित कॉलम एक पूर्णांक हो।

CREATE TABLE `test`.`pants` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , 
`some_other_int` INT NOT NULL 
) ENGINE = InnoDB; 

INSERT INTO `test`.`pants` (`id`, `some_other_int`) 
VALUES ('1', '1'), ('2', '0'); 

और निम्नलिखित कोड:

निम्नलिखित एसक्यूएल पर विचार करें! "क्षेत्र एक्स एक स्ट्रिंग नहीं था"

<?php 

$c = mysql_connect('127.0.0.1', 'user', 'password'); 
mysql_select_db('test', $c); 
$r = mysql_query('SELECT * FROM pants', $c); 

while ($row = mysql_fetch_assoc($r)) { 
    var_dump($row); 
    foreach($row as $k=>$v) { 
     if (!is_string($v)) 
      echo "field {$v} was not a string!\n"; 
    } 
} 

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

<?php 
$id = 2; 
$r = mysql_query(sprintf('SELECT * FROM pants WHERE id=%s', mysql_real_esacpe_string($id)), $c); 
$row = mysql_fetch_assoc($r); 

// this is the important bit 
if (0 == $row['some_other_int']) { 
    echo "It was zero!"; 
} 

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

प्रकार सहित सख्त समानता "वास्तव में, वास्तव में, ईमानदार ईश्वर के बराबर ईमानदार" ऑपरेटर का उपयोग करके परीक्षण किया जाता है, जिसे प्रतीक "===" द्वारा दर्शाया जाता है।

1

मैं नहीं दिख रहा है कि कैसे ('एक' == 0) सहायक

$var = '123abc'; 

if (123 == $var) 
{ 
    echo 'Whoda thunk it?'; 
} 

यह पीएचपी का अंतर्निहित रूपांतरण नियमों करने के लिए नीचे आता है।

मैं एक व्यावहारिक उदाहरण के बारे में सोचने में असफल रहा हूं, लेकिन यह मूल कारण है कि आप उस व्यवहार को क्यों देख रहे हैं।

विस्तार:

अपने उदाहरण में, 'एक' 0 (शून्य) को, तुलना के लिए बदल जाती है। कल्पना कीजिए कि तुलना के उद्देश्य के लिए, यह '0 ए' के ​​बराबर है। (यह अंक शून्य, नहीं पत्र है 'ओ।')

इसका और विस्तार:

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

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

http://bugs.php.net/bug.php?id=48012

यही सवाल का जवाब नहीं है, लेकिन यह सामान्य दिशा में इंगित करता है।

1

PHP एक कमजोर टाइप की गई भाषा है, और आपको त्रुटियों को फेंकने के बिना विभिन्न प्रकार के मानों की तुलना करने की अनुमति देता है, जो इसे उपयोग करना बहुत आसान बनाता है लेकिन जैसा कि आपने पाया है कुछ अजीब लेकिन तार्किक आउटपुट का कारण बन सकता है।

आपका पहला उदाहरण:

if(0=='a'){ 
    print ord(0)." should NEVER equal ".ord('a')."<br>"; 
} 

जब मूल्यों की दो अलग अलग प्रकार की तुलना की जाती है, एक मूल्य पहले ही प्रकार में एक और के रूप में एक डाली के माध्यम से दिया जाता है और उसके बाद की तुलना में। इंट और स्ट्रिंग के उदाहरण में स्ट्रिंग को Int में परिवर्तित किया जाता है। जब PHP एक स्ट्रिंग में एक पत्र बदलता है तो यह सभी पहले संख्यात्मक वर्णों और फिर बाकी की चॉप लेता है: यानी '123123afraa' 123123 बन जाता है, '9 ए 9' 9 हो जाता है। यदि स्ट्रिंग अंकों से शुरू नहीं होती है तो इसे 0 का मान दिया जाता है

वहां आपका उदाहरण वास्तव में है: 0 === (स्ट्रिंग) 'ए' जो वास्तव में 0 === 0 है क्योंकि 'ए' एक संख्यात्मक से शुरू नहीं होता है। मुझे लगता है कि आप एएससीआईआईआई में 'ए' के ​​मूल्य को वापस करने की उम्मीद कर रहे थे, जो यह नहीं करता! स्ट्रिंग को स्वच्छ करने के लिए यह वास्तव में उपयोगी है, PHP को शायद ही कभी एसीआई मानों से निपटने की ज़रूरत है, इसके लिए यह बहुत अधिक स्तर है। (वेबसाइट बनाने के लिए!)

जब एक स्ट्रिंग की तुलना एक बूलियन से की जाती है तो '' या '0' का मान गलत होता है, अन्य सभी मान सत्य होते हैं। यह उपयोगी है ताकि आप जाँच कर सकते हैं 'खाली' अगर एक मूल्य है:

यूआरएल http://domain.com/?foo=

अगर ($ _GET [ 'foo'])) { // कुछ करना }

जब एक पूर्णांक की तुलना एक बूलियन से की जाती है 0 के मान झूठे हैं अन्य मान सत्य हैं, यह बहुत मानक है।

तो, आपको यह समझने की ज़रूरत है कि क्या होता है जब विभिन्न प्रकार के चर == ऑपरेटर के साथ तुलना की जाती हैं। यह भी समझना बुद्धिमानी है कि == लगभग वही नहीं है जो आप चाहते हैं और === (जो आपके मानों को टाइप नहीं करेगा) का उपयोग करना बहुत सुरक्षित है।

0

असफलताओं को पकड़ने के उद्देश्य से कोड इकाई परीक्षण से उत्पन्न होता है, इसलिए प्रतीत होता है अजीब तुलना। उसी प्रकाश में, यह पुष्टि करने के लिए मुख्य इकाई परीक्षण के लिए प्रारंभिक हो सकता है कि == ऑपरेटर ठीक से काम कर रहा है - जैसा कि इसे करना चाहिए।

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