PHP
टाइपिंग और नॉन-स्ट्रिक्ट कम्पेरिजन इश्यूज टाइप करें
खोज…
टाइप बाजीगरी क्या है?
PHP एक शिथिल टाइप की भाषा है। इसका मतलब यह है कि, डिफ़ॉल्ट रूप से, इसे उसी (या संगत) प्रकार के होने के लिए किसी अभिव्यक्ति में ऑपरेंड की आवश्यकता नहीं होती है। उदाहरण के लिए, आप एक संख्या को एक स्ट्रिंग में जोड़ सकते हैं और इसे काम करने की उम्मीद कर सकते हैं।
var_dump ("This is example number " . 1);
उत्पादन होगा:
स्ट्रिंग (24) "यह उदाहरण संख्या 1 है"
PHP स्वचालित रूप से असंगत चर प्रकारों को स्वचालित रूप से कास्टिंग करके इसे पूरा करती है जो अनुरोधित ऑपरेशन को करने की अनुमति देती है। उपरोक्त मामले में, यह पूर्णांक शाब्दिक 1 को एक स्ट्रिंग में डालेगा, जिसका अर्थ है कि इसे पूर्ववर्ती स्ट्रिंग शाब्दिक पर समेटा जा सकता है। इसे प्रकार की बाजीगरी कहा जाता है। यह PHP की एक बहुत ही शक्तिशाली विशेषता है, लेकिन यह एक ऐसी विशेषता भी है, जो आपको इसके बारे में जानकारी नहीं होने पर बहुत सारे बालों को खींच सकती है, और सुरक्षा समस्याओं को भी जन्म दे सकती है।
निम्नलिखित को धयान मे रखते हुए:
if (1 == $variable) {
// do something
}
आशय यह प्रतीत होता है कि प्रोग्रामर यह जाँच रहा है कि एक चर का मान 1 है। लेकिन अगर $ चर का मूल्य "1 और आधा" है तो क्या होगा? जवाब आपको चकित कर सकता है।
$variable = "1 and a half";
var_dump (1 == $variable);
परिणाम है:
bool (सही)
ऐसा क्यों हुआ है? यह इसलिए है क्योंकि PHP ने महसूस किया कि स्ट्रिंग "1 और डेढ़" पूर्णांक नहीं है, लेकिन इसे पूर्णांक की तुलना करने के लिए इसे 1 में होने की आवश्यकता है। असफल होने के बजाय, PHP टाइप करतब दिखाने की कोशिश करता है और, चर को एक में बदलने का प्रयास करता है। पूर्णांक। यह स्ट्रिंग की शुरुआत में सभी पात्रों को ले जाकर ऐसा करता है जो पूर्णांक तक डाली जा सकती हैं और उन्हें कास्टिंग कर सकते हैं। जैसे ही यह एक ऐसे चरित्र का सामना करता है जो एक नंबर के रूप में नहीं माना जा सकता है। इसलिए "1 और डेढ़" पूर्णांक 1 में ढल जाता है।
दी, यह एक बहुत ही विवादित उदाहरण है, लेकिन यह इस मुद्दे को प्रदर्शित करने का काम करता है। अगले कुछ उदाहरण कुछ मामलों को कवर करेंगे, जहां मैं टाइप सॉफ्टवेयर की गड़बड़ी की वजह से त्रुटियों में चला गया हूं जो वास्तविक सॉफ़्टवेयर में हुआ था।
एक फ़ाइल से पढ़ना
किसी फ़ाइल से पढ़ते समय, हम यह जानना चाहते हैं कि हम उस फ़ाइल के अंत में कब पहुँच सकते हैं। यह जानकर कि fgets()
फ़ाइल के अंत में गलत है, हम इसे लूप के लिए शर्त के रूप में उपयोग कर सकते हैं। हालांकि, डेटा पिछले पढ़ने से लौटे अगर कुछ बूलियन के रूप में मूल्यांकन करता है कि होने वाला false
, यह हमारी फ़ाइल पाश पढ़ समय से पहले ही समाप्त करने के लिए हो सकता है।
$handle = fopen ("/path/to/my/file", "r");
if ($handle === false) {
throw new Exception ("Failed to open file for reading");
}
while ($data = fgets($handle)) {
echo ("Current file line is $data\n");
}
fclose ($handle);
यदि पढ़ी जा रही फ़ाइल में एक रिक्त रेखा होती है, while
लूप उस बिंदु पर समाप्त हो जाएगा, क्योंकि खाली स्ट्रिंग बूलियन false
रूप में मूल्यांकन करती है।
इसके बजाय, हम बूलियन false
मूल्य के लिए जाँच कर सकते हैं स्पष्ट रूप से, सख्त समानता ऑपरेटरों का उपयोग करते हुए:
while (($data = fgets($handle)) !== false) {
echo ("Current file line is $data\n");
}
ध्यान दें कि यह एक आकस्मिक उदाहरण है; वास्तविक जीवन में हम निम्नलिखित लूप का उपयोग करेंगे:
while (!feof($handle)) {
$data = fgets($handle);
echo ("Current file line is $data\n");
}
या पूरी चीज़ को इसके साथ बदलें:
$filedata = file("/path/to/my/file");
foreach ($filedata as $data) {
echo ("Current file line is $data\n");
}
आश्चर्य को स्विच करें
स्विच स्टेटमेंट मैचों का निर्धारण करने के लिए गैर-सख्त तुलना का उपयोग करते हैं। इससे कुछ बुरा आश्चर्य हो सकता है । उदाहरण के लिए, निम्नलिखित कथन पर विचार करें:
switch ($name) {
case 'input 1':
$mode = 'output_1';
break;
case 'input 2':
$mode = 'output_2';
break;
default:
$mode = 'unknown';
break;
}
यह एक बहुत ही सरल कथन है, और जब $name
एक स्ट्रिंग है, तो उम्मीद के मुताबिक काम करता है, लेकिन अन्यथा समस्याएं पैदा कर सकता है। उदाहरण के लिए, यदि $name
पूर्णांक 0
, तो तुलना के दौरान टाइप-जॉगिंग होगी। हालाँकि, यह केस स्टेटमेंट में शाब्दिक मूल्य है जो कि जुगाड़ हो जाता है, स्विच स्टेटमेंट में स्थिति नहीं। स्ट्रिंग "input 1"
पूर्णांक में बदल जाती है 0
जो पूर्णांक के इनपुट मान से मेल खाता 0
। यदि आप पूर्णांक 0
का मान प्रदान करते हैं, तो इसका लाभ यह है कि पहला मामला हमेशा निष्पादित होता है।
इस समस्या के कुछ समाधान हैं:
स्पष्ट कास्टिंग
तुलना करने से पहले मान स्ट्रिंग के लिए टाइपकास्ट किया जा सकता है:
switch ((string)$name) {
...
}
या एक स्ट्रिंग लौटाने के लिए ज्ञात फ़ंक्शन का भी उपयोग किया जा सकता है:
switch (strval($name)) {
...
}
ये दोनों विधियाँ यह सुनिश्चित करती हैं कि मान उसी प्रकार का हो जैसा कि case
स्टेटमेंट्स में मान होता है।
switch
बचें
if
एक कथन का उपयोग हमें इस बात पर नियंत्रण प्रदान करेगा कि तुलना कैसे की जाती है, तो हमें सख्त तुलना ऑपरेटरों का उपयोग करने की अनुमति देता है:
if ($name === "input 1") {
$mode = "output_1";
} elseif ($name === "input 2") {
$mode = "output_2";
} else {
$mode = "unknown";
}
सख्त टाइपिंग
PHP 7.0 के बाद से, टाइपिंग के कुछ हानिकारक प्रभावों को सख्त टाइपिंग के साथ कम किया जा सकता है। फ़ाइल की पहली पंक्ति के रूप में इस declare
बयान को शामिल करके, PHP एक टाइप- TypeError
अपवाद को फेंककर पैरामीटर प्रकार की घोषणाओं और वापसी प्रकार की घोषणाओं को लागू करेगा।
declare(strict_types=1);
उदाहरण के लिए, यह कोड, पैरामीटर प्रकार की परिभाषाओं का उपयोग करते हुए, टाइप किए जाने वाले प्रकार TypeError
का एक बड़ा अपवाद छोड़ देगा:
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
echo sum("1", 2);
इसी तरह, यह कोड रिटर्न प्रकार की घोषणा का उपयोग करता है; यदि यह पूर्णांक के अलावा कुछ भी वापस करने की कोशिश करता है, तो यह एक अपवाद भी फेंक देगा:
<?php
declare(strict_types=1);
function returner($a): int {
return $a;
}
returner("this is a string");