九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
細(xì)數(shù) PHP 中的那些坑(轉(zhuǎn))

變量類型

說(shuō)PHP入門門檻低,其中一個(gè)原因是我們不需要關(guān)心變量的類型,PHP為我們做了自動(dòng)的轉(zhuǎn)化。但事實(shí)上是這樣嗎?下面就是一個(gè)隱蔽的bug。

1234
<?phpvar_dump('string' == 0);?>==> true

很神奇吧,php在這里自動(dòng)將字符串作為整數(shù)0來(lái)比較了。由此引發(fā)了一系列問(wèn)題:

1234567891011
<?php$a = "1234567";var_dump($a['test']);==> 1  //坑爹的等同于$a[0], php5.4會(huì)給出一個(gè)非法索引warning,但是仍然返回1,php5.3則連warning都沒(méi)有。var_dump(isset($a['test']));==> true  //這是一個(gè)完全錯(cuò)誤的結(jié)果,在php5.4中得到修復(fù)var_dump(in_array(0, array('xxx')));==> true  //這也是一個(gè)令人費(fèi)解的bug,暫且還是理解為php將'xxx'轉(zhuǎn)化成0了吧var_dump(in_array(false, array('xxx')));==> false  //與之相對(duì)的,這個(gè)結(jié)果確是符合預(yù)料的。問(wèn)題是,在php中0==false呀。?>

所以當(dāng)一個(gè)表達(dá)式中同時(shí)包含0和字符串的時(shí)候就要特別留意了,以免被奇葩的bug坑了。

比較符號(hào)

等號(hào)==與不等!=

嚴(yán)格的來(lái)說(shuō),PHP中的==符號(hào)完全沒(méi)有作用,因?yàn)?code style="margin: 0px 3px; padding: 1px 3px; background: rgb(250, 250, 250); border: 1px solid rgb(238, 238, 238); font-family: Monaco, Menlo, "Andale Mono", "lucida console", "Courier New", monospace; font-size: 0.9em; border-radius: 5px;">'string' == true,而且'string' == 0但是true != 0。

然后是123 == "123foo",但是當(dāng)你用引號(hào)將123包起來(lái)以明確說(shuō)明這是一個(gè)字符串時(shí),'123' != "123foo",但是在現(xiàn)實(shí)中,誰(shuí)會(huì)用常量比較呢,這個(gè)123換成了一個(gè)變量,而根據(jù)php的哲學(xué),誰(shuí)會(huì)在意這個(gè)變量是什么類型。

在使用其他進(jìn)制的時(shí)候這種混淆尤其明顯,像下面的例子:

12345678
<?php"133" == "0133";133 == "0133";133 == 0133;    //因?yàn)?133是一個(gè)八進(jìn)制數(shù),轉(zhuǎn)成十進(jìn)制是91"0133" != 91;   //字符串中的數(shù)字始終是十進(jìn)制的,這個(gè)也可以理解"0x10" == 16;   //但是!,在十六進(jìn)制中上面的說(shuō)法又不成立了"1e3" == 1000;  //科學(xué)計(jì)數(shù)表示也一樣?>

大于>小于<

被搞糊涂的話,下面還有:

1234
<?phpnull == 0;  //這個(gè)可以理解null < -1;  //但是你會(huì)想到這個(gè)嗎?難道zend認(rèn)為0<-1??>

使用==時(shí),參照javascript中的做法,我們可以使用===讓比較更規(guī)范一些,但是>,<這些怎么辦?只能盡量避免。

三元運(yùn)算符

很多語(yǔ)言都提供了三元運(yùn)算符?:,因?yàn)樗銐蚝?jiǎn)潔,也夠geek。但是php中的表現(xiàn)與其他語(yǔ)言中又不同:

12345678910
<?php$arg = 'T';$vehicle = ( ( $arg == 'B' ) ? 'bus' :             ( $arg == 'A' ) ? 'airplane' :             ( $arg == 'T' ) ? 'train' :             ( $arg == 'C' ) ? 'car' :             ( $arg == 'H' ) ? 'horse' :             'feet' );echo $vehicle;?>

猜猜結(jié)果是什么?’horse’,而我們預(yù)料中的(在其他語(yǔ)言中)應(yīng)該是’train’。這種做法被稱為”left associative”(左結(jié)合),也即上面的表達(dá)式在php看來(lái)等同于$vehicle = (condition) ? 'horse' : 'feet',所以你永遠(yuǎn)不可能得到中間的結(jié)果,這有違人的第一感覺(jué),也與其他語(yǔ)言正好相反。

empty

empty是我在php中非常喜歡的一個(gè)方法,這里我說(shuō)錯(cuò)了,其實(shí)它是一個(gè)語(yǔ)言結(jié)構(gòu),而不是一個(gè)方法,但是它的使用方式又像一個(gè)方法。于是,empty()中包含運(yùn)算式的話是會(huì)報(bào)錯(cuò)的,這也造成了它的局限性。

數(shù)組

php中的數(shù)組應(yīng)該是一個(gè)’數(shù)組’,’hash表’,’集合’的結(jié)合體,這在使用上有它的方便之處,但是也造成了一些不易理解的地方,尤其體現(xiàn)在一些array相關(guān)的方法上。

1234
<?phparray("foo", "bar") != array("bar", "foo");  //這個(gè)時(shí)候,array就是數(shù)組array("foo" => 1, "bar" => 2) == array("bar" => 2, "foo" => 1);  //這個(gè)時(shí)候,array又變成了無(wú)序hash表?>

好吧,其實(shí)php中的array就是一個(gè)hash表,無(wú)論什么情況下。array('bar', 'foo')就是array('0'=>'bar', '1'=>'foo'),這樣對(duì)理解array的一些奇怪表現(xiàn)應(yīng)該會(huì)有幫助,但是下面的方法,有推翻了上面的論述,我將它算做一個(gè)bug:

123456
<?php$first  = array("foo" => 123, "bar" => 456);$second = array("foo" => 456, "bar" => 123);var_dump(array_diff($first, $second));==> array()?>

看到了吧,如果array是個(gè)hash表的話,$first和$second顯然是不一樣的。但是diff的結(jié)果卻認(rèn)為這是兩個(gè)一樣的數(shù)組。所以在愉快的使用array時(shí),別忘了停下來(lái),測(cè)試一下這些隱含的bug。

++--

123456
<?php$a = null;$a ++;  // $a == 1, 可以理解$a = null;$a --;  // $a == null, 凌亂了?>

解決這種++--中的不一致的辦法就是根本不用它們,用+=-=代替。

命名習(xí)慣

下面這些就與bug無(wú)關(guān)了,而是php中過(guò)于隨意的命名規(guī)則和變量順序,像htmlentitieshtml_entity_decode,你能想象這兩個(gè)方法是一張紙的兩面嗎?

其實(shí)方法的命名不規(guī)范問(wèn)題也不大,但是變量順序混亂就要人命了,比如array中的一大堆方法,看起來(lái)都以array打頭,相當(dāng)清晰。但是你能料到array_filter($input, $callback)array_map($callback, $input)兩個(gè)方法的回調(diào)方法位置正好相反嗎?我就經(jīng)常記錯(cuò)strpos中哪個(gè)參數(shù)才是該被搜索的字符串。

還有一個(gè)要命的地方就是很多參數(shù)的引用傳遞不明,比如上面的array_filter是對(duì)源對(duì)象的一個(gè)拷貝,但是array_walk卻是一個(gè)引用。這些在php.net上有“粗略”的說(shuō)明,我想誰(shuí)也不希望一邊翻文檔一邊寫(xiě)代碼吧。

錯(cuò)誤控制

關(guān)于php的錯(cuò)誤控制其實(shí)是一個(gè)關(guān)于“配置優(yōu)于約定”還是“約定優(yōu)于配置”的討論,而顯然php選擇了前者。在php中,有一個(gè)全局的配置文件“php.ini”,里面關(guān)于錯(cuò)誤控制的兩個(gè)選項(xiàng)error_reportingdisplay_errors分別代表錯(cuò)誤等級(jí)和是否顯示錯(cuò)誤。

這沒(méi)有問(wèn)題,問(wèn)題是這些配置在運(yùn)行時(shí)是可以修改的。有些框架或有些人為了掩蓋無(wú)處不在的notice,將error_reporting等級(jí)調(diào)高,或者索性將display_errors設(shè)置為off,這會(huì)讓其他開(kāi)發(fā)者困惑,讓錯(cuò)誤無(wú)跡可尋。

這也不是什么問(wèn)題,最大的問(wèn)題是php中還有set_error_handlerset_exception_handler,看字面意思,這兩個(gè)都是用來(lái)控制錯(cuò)誤的。但是在php中,errorexception卻是不一樣的。于是你要么在框架里寫(xiě)上兩套一樣的handler方法,要么就索性都不寫(xiě),由php去決定這些錯(cuò)誤該以什么形式表現(xiàn)。最糟糕的是只寫(xiě)一個(gè)或者寫(xiě)兩套不一樣的handler,這回讓人困惑為什么有些錯(cuò)誤以一種形式表現(xiàn),而一些錯(cuò)誤又以別的方式出現(xiàn),而且要找到這些handler也不是一件容易的事,他們可能出現(xiàn)在任何一個(gè)文件的任何一個(gè)角落,除非你用debug_backtrace將堆棧信息都打印出來(lái)。

后記

以上大部分內(nèi)容和例子來(lái)自PHP: a fractal of bad design,一個(gè)狂熱的python教徒。我不是python教徒,甚至連愛(ài)好者都說(shuō)不上,所以寫(xiě)這篇文章只是為了記錄php中存在的bug,以防一不小心被坑了。只有有了這些意識(shí),才能在這門語(yǔ)言中更好的發(fā)揮,物盡其用。

相關(guān)鏈接

PHP: a fractal of bad design

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
PHP 7.0 升級(jí)備注 |唐建鵬博客
isset-PHP手冊(cè)
在PHP語(yǔ)言中使用JSON
php數(shù)據(jù)類型
掌握這20個(gè)JS技巧,做一個(gè)不加班的前端人
十天學(xué)會(huì)PHP/第九天:錯(cuò)誤處理、異常處理、過(guò)濾器
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服