欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

如何全面分析PHP的糟糕設計

如何全面分析PHP的糟糕設計,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

站在用戶的角度思考問題,與客戶深入溝通,找到豐林網站設計與豐林網站推廣的解決方案,憑借多年的經驗,讓設計與互聯(lián)網技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都做網站、網站制作、企業(yè)官網、英文網站、手機端網站、網站推廣、國際域名空間、網絡空間、企業(yè)郵箱。業(yè)務覆蓋豐林地區(qū)。

PHP不僅使用起來尷尬, 還有要嘛我想要的不適合, 要嘛不是最令人滿意, 要嘛違背我的信仰. 我可以告訴你關于一門語言, 所有我想避免的好方式, 所有我喜歡的壞方式. 來吧, 問吧! 談話會很有趣!

php是唯一的例外. 幾乎php抽象的所有東西都是支離破碎的. 包括語言, 框架, 整個生態(tài)系統(tǒng)都一塌糊涂. 我?guī)缀醪荒軉为毩谐鲋淞R的事情, 因為它全身都壞了. 每次我打算編輯一堆雜亂如麻的php抱怨清單的時候, 我都被一些瑣事打亂, 越深入就越會發(fā)現(xiàn)其它令人震驚的事情.

php讓人難堪. 它是如此的破碎, 但那些被培訓的業(yè)余愛好者, 卻對它稱贊不已. php在做一些徽不足道的挽回措施, 但我選擇忘記它.

不過我得讓我的系統(tǒng)擺脫這些東西, 也就這樣了, 這是最后一次嘗試.

打個比喻

我只是隨口和 Mel 抱怨下, 而她卻堅決讓我發(fā)表出來.

我甚至說不出來PHP到底怎么了, 因為 -- 還好. 想想你有一個, 嗯, 工具箱吧. 一堆工具. 看起來還好, 有標準的東西.

你拔除螺絲釘, 它怪異的有三個頭. OK, 好吧, 這對你不太有用, 但你猜遲早有天會有用.

你拿出榔頭, 被震住了, 兩邊都有是尖爪. 但它仍然能用, 我的意思是, 你可以用兩頭的中部斜著敲.

你拿出老虎鉗, 但它們沒有鋸齒面. 表面平而光滑. 這沒多大用, 但依然能用, 沒什么.

你可以繼續(xù). 工具箱的東西都是怪異和琢磨不定的, 但又不能說毫無價值. 整體看沒什么大問題; 它的工具都齊全.

現(xiàn)在, 想象有很多使用這些工具的木匠, 它們和你說:"這些工具有什么問題呢? 我們都用過, 它們工作都很好啊!". 工匠們給你展示他們建的房子,每個門都是五邊形的而屋頂是癲倒的. 你敲前門, 它向內倒榻了, 而他們卻抱怨你打破了他們的門.

這就是PHP的問題.

立場

我認為下面的特質對于一門語言的生產力和可用性是重要的, 而PHP在大范圍破壞它們. 如果你不同意這些, 好吧, 我無法想像, 我們永遠不會達成一致.

>> 一門語言必須是可預見的. 它是將人類的思想反映給計算機執(zhí)行的媒介, 因此它的關鍵是, 人類對程序的理解實際要正確.

>> 語言必須一致. 相似的東西就要看起來相似, 不同的就是不同. 學習了語言的部分知識, 就應能很容易理解剩下的部分.

>> 語言必須簡潔. 新語言應該減少繼承舊語言的不好的形式. (我們也可以寫機器碼.) 新語言當然應努力避免織入新的特有的形式.

>> 語言必須是可靠的. 語言是解決問題的工具; 應盡量避免引入新問題. 任何"陷阱"都會大量的分散注意力.

>> 語言必須是可調試的. 當出錯的時候, 程序員必須修正它, 我們需要獲得我們想要的幫助.

我的立場是:

>> PHP到處處充滿驚奇: MySQL_real_escape_string, E_ACTUALLY_ALL

>> PHP不一致: strpos, str_rot13

>> PHP需要特別形式: error-checking around C API calls, ===

>> PHP古怪: ==. for($foo as &$bar)

>> PHP晦澀: 默認無棧跟蹤或fatals, 復雜的錯誤報告

我不能就單個問題解釋為什么它歸為這些類, 否則將會沒完沒了. 我相信讀者自己會思考.

不要再和我扯這些東西了

我知道很多有利的論點. 我也聽到很多反駁的論點. 這些都只能讓談話立即停止. 不要再跟我扯這些東西了, 求你了. :(

>> 不要和我說"好的開發(fā)者能用任何語言寫出好的代碼", 或者壞開發(fā)者.. 吧啦吧啦. 這毫無意義. 好的工匠可以用石頭或錘子駕馭釘子, 但你見過有多少工匠用石頭的? 成為一個好開發(fā)者的標準之一就是善于選擇工具.

>> 不要和我說熟記上千個例外和古怪行為是開發(fā)者的職責. 是的, 這在任何系統(tǒng)中都是必要的, 因為電腦是傻的. 這不意味著, 系統(tǒng)能瘋狂的接受而沒有上限. PHP有的只是異常, 這是不行的, 一旦和語言摔角決斗, 你實際編寫程序就要花費更多的努力. 我的工具不能為我創(chuàng)建應用產生積極作用.

>> 不要和我說 "那就是C API 的工作方式". 這星球上高級語言存在的目的是什么, 它們能提供的一切僅僅是一些字符串助手函數(shù)和一堆C的包裝器? 如果是這樣, 那就用C! 這里, 甚至還有為它準備的CGI庫.

>> 不要和我扯 "搞出奇怪的事, 是你活該". 如果存在兩個特性, 總有一天, 某些人會找到一起使用它們的理由. 再次強調, 這不是C; 這里沒有規(guī)范, 這里不需要 "未定義行為".

>> 不要再和我扯 Facebook 和 Wikipedia 就用的PHP. 我早知道了! 它們也能用 Brainfuck 寫, 但只要他們足夠陪明, 不斷折騰這些事情, 他們總能克服平臺的問題. 眾所周知, 如果使用其它語言編寫, 開發(fā)時間可能會減少一半或加倍; 單獨拿出這些數(shù)據(jù)毫無意義.

上帝保佑, 不要再和我扯任何東西了! 如果列出的沒有傷害你的PHP的觀點, 無所謂, 因此請停止在網上做無意義的爭論, 繼續(xù)開發(fā)高帥富酷的站點來證明我是錯的 :).

偷偷告訴你: 我非常喜歡Python. 我也很樂意對它說些你不愛聽的話, 如果你真想的話. 我并不要求它完美; 我只是想揚長避短, 總結我想要的最佳東西.

PHP

語言核心

CPAN被稱為 "Perl的標準庫". 這并沒有對Perl的標準庫做過多說明, 但它蘊含了健壯的核心可以構建強大的東西的思想.

基本原則

PHP最初很明確的是為非程序員設計的(言外之意, 非專業(yè)程序); 根源已經很難脫離. 從PHP 2.0 文檔中挑選出來的對話:

一旦你開始為每個類型區(qū)分不同的操作符, 你就開始使用語言變得復雜了. 例如, 你不能為strings使用 '==', 你現(xiàn)在必須用 'eq'. 我沒看出這點來, 特別是那些類似PHP的腳本語言, 它們大多數(shù)相當簡單而多數(shù)情況下, 作為非程序員, 只想要一門包含少量基本邏輯語法的語言, 而不想付出過多學習曲線.

>> PHP 為保持前進不惜代價. 什么都有比沒有好.

>> 這不是個正確的設計原則. 早期的PHP受Perl影響; 大量的標準庫參考C使用 "out" 參數(shù); OO部分的設計像C++和Java.

>> PHP從其它語言中引入大量的靈感, 但對那些熟知其它語言的人, 仍然難以理解. (int)看起來像 C, 但是 int 并不存在. 命名空間使用 \. 新的數(shù)組語法使用 [key => value], 不同于任何其它語言定義hash字面量的形式.

>> 弱類型(例如, 默默的自動在 strings/mumbers/等間轉換)是如此的復雜.

>> 少量的新特性以新語法實現(xiàn); 大多數(shù)工作通過函數(shù)或者看起來像函數(shù)的東西完成. 除了類的支持, 這理所當然的需要新的操作符和關鍵字.

>> 本頁列出的問題都有官方解決方案 -- 如果你想資助 Zend 修復它們的開源編程語言的話.

>> 路漫漫, 其修遠. 思考下面的代碼, 從PHP文檔的某地方挑出來的.

@fopen('http://example.com/not-existing-file', 'r');

它將做什么?

>> 如果PHP使用 --disable-url-fopen-wrapper編譯, 它將不工作. (文檔沒有說, "不工作"是什么意思; 返回 null, 拋出異常?)

>> 注意這點已在 PHP 5.2.5 中移除.

>> 如果 allow_url_fopen 在 php.ini 中禁用, 也將不工作. (為什么? 無從得知.)

>> 由于 @ , non-existent file 的警告將不打印.

>> 但如果在php.ini中設置了scream.enabled, 它又將打印.

>> 或者如果用 ini_set 手動設置 scream.enabled.

>> 但, 如果 error_reporting 級別沒設置, 又不同.

>> 如果打印出來了, 精確去向依賴于 display_errors , 再一次還是在 php.ini. 或者 ini_set中.

我無法告訴你這個函數(shù)調用的行為, 如果沒有查看編譯時標志 , 服務器端配置, 和我的程序中的配置的話. 這些都是內建行為.

>> 該語言充滿了全局和隱似狀態(tài). mbstring 使用全局字符編碼. func_get_arg 之類的看起來像正常的函數(shù), 但是只對當前正在執(zhí)行的函數(shù)操作. Error/exception 處理默認是全局的. register_tick_function 設置了一個全局函數(shù)去運行每個 tick(鉤子?) ---- 什么?!

>> 沒有任何線程支持. (不奇怪, 因為上面已給出.) 加之缺乏內建的 fork (下面提到), 使得并行編程極其困難.

>> PHP的某些部分在實踐中會產生錯誤代碼.

>> json_decode 對不正確的輸入返回 null, 盡管 null 也是一個 JSON 解碼的合法對象 -- 該函數(shù)極不可靠, 除非你每次使用后都調用 json_last_error.

>> 如果在位置0處找到, array_search , strpos, 和其它類似的函數(shù)返回0, 但如果都沒有找到的話. 會返回 false

讓我們稍稍展開最后一部分.

在C中, 函數(shù)如 strpos 返回 -1, 如果未找到. 如果你沒檢查這種情況, 卻試著以下標使用它, 那將可能命中垃圾內存, 程序會崩潰. (也許吧, 這是C. 誰泥馬知道. 我確定至少有工具處理它)

話說, Python中, 等效的 .index 方法將拋出一個異常, 如果元素沒找到的話. 如果你不檢查該情形, 程序將崩潰.

在PHP中, 該函數(shù)返回 false. 如果你把 FALSE 作為下標使用, 或者用它做其他事情, PHP會默默的將它轉成0, 但除了用于 === 比較. 程序是不會崩潰的; 它將執(zhí)行錯誤的邏輯, 且無任何警告, 除非你記得在每個使用 strpos 和其它類似函數(shù)的地方包含正確的樣版處理代碼.

這真是糟透了! 編程語言只是工具; 它們是為我服務的. 這里, PHP給我布下了陷阱, 等著我跳進去, 而我不得不時刻警惕這些無聊的字符串操作和相等比較. PHP是個雷區(qū).

我已經聽過很多關于PHP解析器的故事, 它的開發(fā)者來自世界各地. 有從事PHP核心開發(fā)工作的人, 有調試PHP核心的人, 也有和核心開發(fā)者交流過的人. 沒有一個故事是贊賞的.

因此不得不在這里插入一句, 因為它值得重復: PHP是個業(yè)余愛好者的社區(qū). 極少數(shù)人設計, 為它工作, 或極少有人知道他們在做什么. (哦, 親愛的讀者, 你當然是個極品例外!) 那些成長了, 想轉投其它平臺的人, 使整個社區(qū)的平均水平下降. 這個, 就是這里, 是PHP的最大問題: 絕對的盲目領導盲目.

好了, 回來面對現(xiàn)實吧.

操作符

== 不中用.

>> "foo" == TRUE , 和 "foo" == 0... 但, 當然 TRUE != 0.

>> == 會將兩邊轉成數(shù)字, 如果可能的話, 這意味著它將轉成 floats 如果可能. 所以大的16進制字符串(如, password hashes) 可能偶然會比較成 true , 盡管它們不一樣. 就連 JavaScript 都不會這樣做.

>> 由于某些原因, "6" == "6", "4.2" == "4.20", 和 "133" == "0133". 但注意 133 != 0133, 因為 0133 是八進制的.

>> === 比較值和類型... 除了對象, 只有兩邊實際上是同一對象才為 true ! 對于對象, == 比較值(或每個屬性)和類型, 這又是 === 比較任何非對象類型的行為. 好玩嗎?

比較大小也好不到哪去.

>> 甚至行為都不一致: NULL < -1, 而 NULL == 0. 排序也因此不確定; 它依賴于在排序中比較元素的算法的順序.

>> 比較操作符嘗試排序數(shù)組, 以兩種不同的方式: 首先按長度, 然后按元素. 如果它們有相同數(shù)量的元素但不同的keys, 它們是不可比的.

>> 對象比較比其它比較做得更多... 除了那些即不小于也不大于的對象.

>> 為了類型更安全的 == 比較, 我們有 ===. 為了類型更安全的 < 比較, 我們有... 什么也沒有. "123" < "0124", 通常, 不管你怎么做. 類型轉換也無濟于事.

>> 盡管上面的舉動很瘋狂, 但卻明確拒絕Perl's的字符串 paris 和算術運行符, PHP沒有重載 +. + 就是通常的 +, 而 . 是通常的連接符.

>> [] 下標操作符也可以拼寫成 {}.

>> [] 可以用于任何變量, 不光是字符串和數(shù)組. 它返回 null , 無錯誤警告.

>> [] 僅能獲取單個元素.

>> foo()[0] 是個語法錯誤. (已在 PHP 5.4 中修復)

>> 不像(從字面上看)任何其它語言都有的類似的操作符, ?: 是左結合的. 因此:

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

打印 horse.

變量

>> 無法聲明變量. 當?shù)谝淮问褂脮r, 不存在的變量會被創(chuàng)建為 null 值.

>> 全局變量在使用前, 需要 global 聲明. 這是根據(jù)上面得出的自然結果, 因此這是個完美的理由, 但, 如果沒有顯示的聲明, 全局變量甚至無法讀取 -- PHP 將悄悄的創(chuàng)建一個局部同名變量取代它. 我還沒見過其它語言使用類似的方法處理范圍問題.

>> 沒有引用. PHP所謂的引用是個真正的別名; 這無疑是一種倒退, 不像 Perl 的引用, 也沒有像 Python 那樣的對象標識傳遞.

>> 沒有明顯的方式檢測和取消引用.

>> "引用" 使變量在語言中與眾不同. PHP 是動態(tài)類型的, 因此變量通常無類型... 除了引用, 它修飾函數(shù)定義, 變量語法, 和賦值. 一旦變量被引用(可在任何地方發(fā)生), 它就一直是個引用. 沒有明顯的方法探測和解引用需要的變量值.

>> 好吧, 我說謊了. 有些"SPL types" 也作用于變量: $x = new SplBool(true); $x = "foo"; 將失敗. 這有點像靜態(tài)類型, 自己看看.

>> A reference can be taken to a key that doesn&rsquo;t exist within an undefined variable (which becomes an array). Using a non-existent array normally issues a notice, but this does not.

>> 通過函數(shù)定義的常量稱為 taking a string; 這之前, 它們不存在. (這可能實際上是復制 Perl 使用常量的行為.)

>> 變量名是大小寫敏感的. 函數(shù)和類名不是. 使得方法使用駝峰式命名會很奇怪.

結構

>> array() 和幾個類似的結構不是函數(shù). $func = "array"; $func(); 不工作.

>> 數(shù)組拆包可以使用 list($a,$b) = .... 操作完成. list() 是類函數(shù)語法, 就像數(shù)組那樣. 我不知道為什么不給一個真正的專用語法, 也不知道為什么名字如些的讓人迷惑.

>> (int) 很顯然的被設計成類似C, 但它不是單獨的標記; 在語言中, 沒有東西被稱為 int. 試試看: var_dump(int)不工作, 它會拋出一個解析錯誤, 因為參數(shù)看起來像是強制轉操作符.

>> (integer) 是 (int) 的別名. 也有 (bool)/(boolean)和(float)/(double)/(real).

>> 有個(array)操作符用來轉成數(shù)組和 (object) 用來轉成對象. 這聽起來很貼心, 但常常有個用例: 你可以用 (array) 使得某個函數(shù)參數(shù), 既可以是單個元素,也可以是列表, 相同對待. 但這樣做不可靠, 因為如果某人傳遞了單個對象,把它轉換成數(shù)組將實際上生成了一個包含對象屬性的數(shù)組. (轉換成對象執(zhí)行了反轉操作.)

>> include()這類的函數(shù)基本上就是C的#include: 他們將其它的文件源碼轉存到你的文件中. 沒有模塊系統(tǒng), 甚至對 PHP 代碼也一樣.

>> 沒有類似嵌套或者局部范圍的函數(shù)或類. 它們都是全局的. include 某文件, 它的變量導入到當前函數(shù)范圍中(給了文件訪問你的變量的能力), 但是函數(shù)和類存入全局范圍中.

>> 追加數(shù)組使用 $foo[] = $bar.

>> echo 不是函數(shù).

>> empty($var) 是如此極端, 對于任何其它東西不表現(xiàn)為函數(shù), 除了變量, e.g. empty($var || $var2), 是個解析錯誤. 為什么地球上有這種東西, 解析器為什么需要了解 empty ?

>> 還有些冗余的語法塊: if (...): ... endif;, 等等.

錯誤處理

>> PHP 的一個獨特操作符是 @ (實際上從DOS借用過來的), 它隱藏錯誤.

>> PHP 錯誤不提供棧軌跡. 你不得不安裝一個處理器生成它們. (但 fatal errors不行 -- 見下文.)

>> PHP 的解析錯誤通常只拋出解析的狀態(tài), 沒其它東西了, 使得調試很糟糕.

>> PHP 的解析器所指的例如. :: 內部作為 T_PAAMAYIM_NEKUDOTAYIM, 而 << 操作符作為 T_SL. 我說 "內部的", 但像上面說的, 給程序員顯示的 :: 或 << 出現(xiàn)在了錯誤的位置.

>> 大多數(shù)錯誤處理打印給服務器日志打印一行錯誤日志, 沒人看到而一直進行.

>> E_STRICT看起來像那么回事, 但它實際上沒多少保護, 沒有文檔顯示它實際上是做什么的.

>> E_ALL包含了所有的錯誤類別 -- 除了 E_STRICT.

>> 關于什么允許而什么不允許是古怪而不一致的. 我不知道 E_STRICT 是怎樣適用于這里的, 但這些卻是正確的:

>> 試圖訪問不存在的對象屬性, 如, $foo->x. (warning)

>> 使用變量做為函數(shù)名, 或者變量名, 或者類名. (silent)

>> 試圖使用未定義常量. (notice)

>> 試圖訪問非對象類型的屬性.(notice)

>> 試圖使用不存在的變量名.(notice)

>> 2 < "foo" (隱藏)

>> foreach (2 as $foo); (warning)

而下面這些不行:

>> 試圖訪問不存在的類常量, 如 $foo::x. (fatal error)

>> 使用字符串常量作為函數(shù)名, 或變量名, 或類名. (parse error)

>> 試圖調用一個示定義函數(shù). (fatal error)

>> Leaving off a semicolon on the last statement in a block or file. (parse error)

>> 使用 list 和其它準內建宏作為方法名. (parse error)

>> 用下標訪問函數(shù)的返回值, 如: foo()[0]. (parse error; 已在 5.4 中修復)

在列表的其他地方也有幾個關于其它怪異解析錯誤的好例子

>> __toString 方法不能拋出異常. 如果你嘗試, PHP 將 ... 呃, 拋出一個異常. (實際上是個 fatal error, 可以被通過的, 除了...)

>> PHP 錯誤和 PHP 異常是完全不同的物種. 它們不能相互作用.

>> PHP 錯誤 (內部, 稱為 trigger_error)不能被 try/catch 捕獲.

>> 同樣, 異常不能通過 set_error_handler 安裝的錯誤處理器觸發(fā)錯誤.

>> 作為替代, 有一個單獨的 set_exception_handler 可以處理未捕獲的異常, 因為用 try 塊包裝你程序入口在 mod_pho 模塊中是不可能的.

>> Fatal 錯誤 (例如, new ClassDoesntExist()) 不能被任何東西捕獲. 大量的完全無害的操作會拋出 fatal 錯誤, 由 于一些有爭議的原因被迫終結你的程序. 關閉函數(shù)仍然運行, 但它們無法獲取棧軌跡(它們運行在上層), 它們很難告知該程序是由一個錯誤還是程序的正常運行結束.

>> 沒有 finally 結構, 使得包裝代碼 (注冊處理器, 運行代碼, 注銷處理器; monkeypatch, 運行測試, unmonkeypatch) 很難看, 很難寫. 盡管 OO 和異常大量的復制了Java的模式, 這是故意的, 因為 finally "在PHP上下文中, 只得其形不得其神".Huh ?

函數(shù)

>> 函數(shù)調用似乎相當昂貴.

>> 一些內建函數(shù)與 reference-returning 函數(shù)交互, 呃, 一種奇怪的方式.

>> 正如在別處提到的, 很多看起來像函數(shù)或者看起來它們應該是函數(shù)的東西實際上是語言的構成部分, 因此無法像正常函數(shù)一樣的工作.

>> 函數(shù)參數(shù)可以具有 "類型提示", 基本上只是靜態(tài)類型. 你不能要求某個參數(shù)是 int 或是 string 或是 對象 或其它 "核心" 類型, 即使每個內建函數(shù)使用這種類型, 可能因為 int 在PHP中不是個東西吧. (查看上面關于 (int) 的討論). 你也不能使用特殊的被大量內建函數(shù)使用的偽類型裝飾: mixed, number, or callback.

>> 因此, 下面:

function foo(string $s) {}  foo("hello world");

產生錯誤 the error:

PHP Catchable fatal error: Argument 1 passed to foo() must be an instance of string, string given, called in...

>> 你可能會注意到 "類型提示" 實際上并不存在; 在程序中沒有 string 類. 如果你試圖使用 ReflectionParameter::getClass() 動態(tài)測試類型提示, 將會得到類型不存在, 使得實際上不可能取得該類型名.

>> 函數(shù)的返回值不能被推斷

>> 將當前函數(shù)的參數(shù)傳給另一個函數(shù) (分派, 不罕見) 通過 call_user_func_array('other_function', func_get_args())完成. 但 func_get_args 在運行時拋出一個 fatal 錯誤, 抱怨它不能作為函數(shù)參數(shù). 為什么為什么這是個類型錯誤? ( 已在 PHP 5.3 中修復)

>> 閉包需要顯示的命名每個變量為 closed-over. 為什么解析器不想辦法解決? (Okay, it&rsquo;s because using a variable ever, at all, creates it unless explicitly told otherwise.)

>> Closed-over 變量, 通過和其它函數(shù)參數(shù)相同的語義"傳遞". 這樣的話, 數(shù)組和字符串等等, 將以傳值方式傳給閉包. 除非使用 &.

>> 因為閉包變量會自動傳遞參數(shù), 沒有嵌套范圍, 閉包不能指向私有方法, 不管是否定義在類中. ( 可能在 5.4 中修復? 不清楚.)

>> 函數(shù)沒有命名參數(shù). 實際上被 devs 顯示拒絕, 因為它 "會導致代碼臭味".

>> Function arguments with defaults can appear before function arguments without, even though the documentation points out that this is both weird and useless. (So why allow it?)

>> 向函數(shù)傳遞額外的參數(shù)會被忽略 (除了內建函數(shù), 會拋出異常). 丟失的參數(shù)被假定為 null.

>> "可變" 函數(shù)需要 func_num_args, func_get_arg, 和 func_get_args. 這類事情沒有語法.

OO

>> PHP的函數(shù)部分被設計成類似C, 但面向對象 (ho ho) 被設計成類似 Java. 我不想過分強調這有多不合諧. 我還沒有發(fā)現(xiàn)一個有大寫字母的全局函數(shù), 重要的內建類使用駝峰式方法命名, 并有getFoo的Java風格的屬性訪問器. 這是門動態(tài)語言, 對嗎? Perl, Python, 和 Ruby 都有一些 通過代碼訪問"屬性"的概念; PHP 僅僅有笨重的 __get 之類的東西. 類型系統(tǒng)圍繞著低層的 Java語言設計, Java 和PHP's處一時代, Java 有意的做了更多限制, 照搬Java, 我百思不得其解.

>> 類不是對象. 元編程不得不通過字符串名指向它們, 就像函數(shù)一樣.

>> 內建的類型不是對象, (不像Perl) 也無法使得看起來像對象.

>> instanceof 是個操作符, 盡管很晚才增加進來, 而大多數(shù)語言都建有專門的函數(shù)和語法. 受Java影響嗎? 類不是第一類? (我不知道它們是不是.)

>> 但有一個 is_a 函數(shù). 它有個可選參數(shù)指定是否允許對象實際是一個字符串命名的類.

>> get_class 是函數(shù); 沒有 typeof 操作符. 同樣有 is_subclass_of.

>> 然而, 這對于內建類型無法工作, (再一次, int 不是個東西). 這樣, 你需要 is_int 等等.

>> 右值必須是變量或字面量; 不能是表達式. 不然會導致... 一個解析錯誤.

>> clone 是一個操作符?!

>> OO 的設計是一只混合 Perl 和 Java 的怪物.

>> 對象屬性通過 $obj->foo, 但類屬性是 $obj::foo. 我沒見過任何其它語言這樣做, 或者這樣做有什么用.

>> 而, 實例方法仍然能通過靜態(tài)的(Class::method)調用. 如果從其它方法中這么調用, 會在當前 $this 上被看成常規(guī)的方法調用. 我認為吧.

>> new, private, public, protected, static ,等等. 試圖虜獲 Java 開發(fā)者的芳心? 我知道這更多是個人的品位, 但我不知道為什么這些東西在一門動態(tài)語言中是必要的 -- 在 C++ 中, 它們中的大多數(shù)是有關匯編和編譯時的命名決議.

>> 子類不能覆蓋 private 方法. 子類覆蓋的公共方法也不可見, 單獨調用, 超類的私有方法. 會有問題, 如在測試mocks對象時.

>> 方法無法命名為, 例如 "list" , 因為 list() 是特殊的語法 (不是個函數(shù)) , 而解析器會被搞暈. 如此曖昧的原因無從得知, 而類工作得就很好. ($foo->list() 不是語法錯誤.)

>> 如果當解析構造函數(shù)參數(shù)時拋出異常(如, new Foo(bar()) 而 bar() 拋出), 構造函數(shù)不會被調用, 但析構函數(shù)會. (已在PHP 5.3 中修復)

>> 在 __autoload 和解析函數(shù)中的異常會導致 fatal 錯誤.

>> 沒有構造器或析構器. __construct 是個初始化函數(shù), 像 Python 的 __init__. 無法通過調用類申請內存和創(chuàng)建對象.

>> 沒有默認的初始化函數(shù). 調用 parent::__construct()的時候, 如果父類沒定義它自己的 __construct 方法會導致 fatal 錯誤.

>> OO 帶來了個迭代器接口, 是語言規(guī)范的部分(如 ... as ...), 但該接口實際上沒有內建實現(xiàn)(如數(shù)組) . 如果你想要個數(shù)組迭代器,你必須用 ArrayIterator 包裝它. 沒有內建方式能夠讓迭代器將其作為第一類對像工作.

>> 類可以重載它們轉化成字符串的方式, 但不能重載怎樣轉換成數(shù)字或任何其它內建類型的方式.

>> 字符串, 數(shù)字, 和數(shù)組都有字符串轉換方式; 語言很依賴于此. 函數(shù)和類都是字符串. 然而,如果沒定義 __toString , 試圖將換內建或自定義對像(甚至于一個閉包) 轉換成字符串會導致錯誤, 甚至連 echo 都可能出錯.

>> 無法重載相等或比較操作.

>> 實例方法中的靜態(tài)變量是全局的; 它們的值跨越該類的多個實例共享.

標準庫

Perl "某些需要匯編". Python 是 "batteries included". PHP 是 "廚房水槽, 它來自加拿大, 但所有的水龍頭用C貼牌".

概括

>> 沒有類型系統(tǒng). 你可以編譯PHP, 但必須通過 php.ini 指定要加載什么, 選項因擴展部分存在(將它們的內容注入到全局名稱空間中)或不存在.

>> 因為名稱空間是最近才有的特性, 標準庫一點沒被打亂. 在全局名稱空間中有上千個函數(shù).

>> 庫的某些部分很不一致.

>> 下劃線 對 無下劃線: strpos/str_rot13, php_uname/phpversion, base64_encode/urlencode, gettype/get_class

>> “to” 對 2: ascii2ebcdic, bin2hex, deg2rad, strtolower, strtotime

>> Object+verb 對 verb+object: base64_decode, str_shuffle, var_dump versus create_function, recode_string

>> 參數(shù)順序: array_filter($input, $callback) versus array_map($callback, $input), strpos($haystack, $needle) versus array_search($needle, $haystack)

>> 前綴混亂: usleep vs microtime

>> Case insensitive functions vary on where the i goes in the name.

>> 大概一半的數(shù)組函數(shù)以 array_ 開頭. 剩下的不是.

>> 廚房水槽. 庫包括:

>> 綁定 ImageMagick, 綁定 GraphicsMagick (ImageMagick的派生), 少量的幾個函數(shù)能檢測 EXIF 數(shù)據(jù) (其中ImageMagick已經可以做到)

>> 解析 bbcode 的函數(shù), 一些非常特殊的標記, 被幾個少量的論壇包使用.

>> 太多 XML 包. DOM (OO), DOM XML (not), libxml, SimpleXML, “XML Parser”, XMLReader/XMLWriter, 和一大砣我不能認出的東西就省略了. 當然會有些不同, 你可以自由的弄清晰它們的區(qū)別.

>> 綁定了兩個特別的信用卡處理器, SPPLUS 和 MCVE. 什么?

>> 三種訪問 MySQL 數(shù)據(jù)庫的方式: mysql, mysqli, 和 PDO 抽象的一些東西.

C 影響

它需要擁有的自己的符號. PHP 是個高層的, 動態(tài)類型的語言. 然后大量的標準庫的部分仍然只是圍繞 C APIS 的薄層封裝, 伴隨著下面的東西:

>> "Out" 參數(shù), 盡管 PHP 可以返回 ad-hoc 哈?;蚝敛毁M力的返回多參數(shù).

>> 至少一打的函數(shù)是為了獲取某子系統(tǒng)的最近一次錯誤(見下文), 盡管 PHP 已存存異常處理功能8年了.

>> 有個 mysql_real_escape_string, 盡管已有個具有相同參數(shù)的 mysql_escape_string, 僅僅因為它是 MySQL C API 的一部分.

>> 全局行為卻是非全局功能的(如 MySQL). 使用多個 MySQL 連接需要顯示的對每個函數(shù)調用傳遞連接句柄.

>> 包裝器真的, 真的, 真的很薄. 例如, 調用了 dba_nextkey 而沒調用 dba_firstkey 將出現(xiàn)段錯誤.

>> 有一堆的 ctype_* 函數(shù) (如 ctype_alnum) 映射類似名稱的 C 字符函數(shù), 而不是如, isupper.

Genericism

如果函數(shù)相做兩件略有不同的事, PHP 就搞出兩個函數(shù).

你怎樣反向排序? 在 Perl 中, 你可以用 { $b <=> $a}. 在 Python 中, 你可能用 .sort(reverse = True). 在 PHP 中, 有個特別的函數(shù)叫 rsort().

>> 那些看起來像 C error 的函數(shù): curl_error, json_last_error, openssl_error_string, imap_errors, mysql_error, xml_get_error_code, bzerror, date_get_last_errors, 還有其它的嗎?

>> 排序函數(shù): array_multisort, arsort, asort, ksort, krsort, natsort, natcasesort, sort, rsort, uasort, uksort, usort

>> 文本檢索函數(shù): ereg, eregi, mb_ereg, mb_eregi, preg_match, strstr, strchr, stristr, strrchr, strpos, stripos, strrpos, strripos, mb_strpos, mb_strrpos, plus the variations that do replacements

>> 有大量的別名: strstr/strchr, is_int/is_integer/is_long, is_float/is_double, pos/current, sizeof/count, chop/rtrim, implode/join, die/exit, trigger_error/user_error&hellip;

>> scandir 返回一個當前給出目錄的文件列表. 而不是(可能有益)按返回目錄順序返回, 函數(shù)返回一個已排序的文件列表. 有個可選的參數(shù)可以按字母逆順返回. 這些用于排序很顯然很不夠.

>> str_split 將字符串拆成等長的塊. chunk_split 將字符串拆成等長的塊, 然后用個分隔符連接.

>> 讀取壓縮文件需要一套單獨的函數(shù), 取決于格式. 有六套函數(shù), 它們的 API 都不同, 如 bzip2, LZF, phar, rar, zip, 和gzip/zlib

>> 因為使用參數(shù)數(shù)組調用函數(shù)是如此的別扭(call_user_func_array), 所以有些配套的像 printf/vprintf 和 sprintf/vsprintf. 它們做相同的事, 但一個帶多個參數(shù), 另一個帶參數(shù)數(shù)組.

文本

>> preg_replace 帶 /e (eval) 標志的將用待替換的字符串替換匹配的部分, 然后 eval 它.

>> strtok 的設計顯然是和 C 函數(shù)等效的, 由于很多原因, 已被認為是個壞注意. PHP 可以輕易的返回一個數(shù)組(而這在C中別扭), 很多的hack strtok(3) 用法 (修改字符串某處), 在這里不能使用.

>> parse_str 解析查詢字符串, 從函數(shù)名看不出任何跡象. 而它會 register_globals 并轉存查詢字符串到本地范圍變量中, 除非你傳遞一個數(shù)組來填充. (當然, 什么也不返回)

>> 碰到空分隔符, explode 會拒絕分割. 每個其它的字符串拆分實現(xiàn)采取這種作法的意思應該是把字符串應拆分成字符; PHP有一個拆分函數(shù), 令人迷惑的稱為 str_split 而卻描述為 "將字符串轉成數(shù)組".

>> 格式化日期, 有 strftime, 像 C API 處理本地語言環(huán)境一樣. 當然也有 date, 完全不同的語法而僅用于 English.

>> "gzgetss -- 獲取 gz 文件的行指針并去除 HTML 標記." 知道了這一系列函數(shù)的概念, 讓我去死吧.

>> mbstring

>> 都是關于 "multi-byte", 解決字符集的問題.

>> 仍然處理的是普通字符串. 有個單一的全局"默認"的字符集. 一些函數(shù)允許指定字符集, 但它依賴于所有的參數(shù)和返回值.

>> 提供了 ereg_* 函數(shù), 但這些都被廢棄了. preg_* 很幸運, 用一些 PCRE-specific 標記, 它們能理解 UTF-8.

系統(tǒng)和反射

>> 有一大堆的函數(shù), 聚焦于文本和變量. 壓縮和提取僅是冰山一角.

>> 有幾種方式讓PHP動態(tài), 咋一看沒有什么明顯的不同或相對好處. 類工具不能修改自定義類; 運行時工具取代了它并能修改自定義的任何東西; Reflection* 類能反射語言的大部分東西; 有很多獨特的函數(shù)是為了報告函數(shù)和類的屬性的. 這些子系統(tǒng)是獨立, 相關, 多余的嗎?

>> get_class($obj) 返回對象的類名稱. get_class()返回被調用函數(shù)中的類的名稱. 撇開這些不說, 同一個函數(shù)會做完全不同的事情: get_class(null)... 行為象后者. 因此面對一個隨機的變量, 你不能信任它. 驚訝吧!

>> stream_* 類允許實現(xiàn)自定義的流對象給fopen和其它的內建的類似文件處理的東西使用. 由于幾個內部原因, "通知" 不能被實現(xiàn).

>> register_tick_function 能接受閉包對象. unregister_tick_function 不行; 相反, 它會拋出錯誤, 抱怨閉包不能轉換成字符串.

>> php_uname 告知你當前操作系統(tǒng)相關東西.

>> fork 和 exec 不是內建的. 它們來自 pcntl 擴展, 但默認不包含. popen 不提供 pid 文件.

>> session_decode 用于讀取任意的 PHP session 字符串, 但僅當有個活躍的 session 時才工作. 它轉存結果到 $_SESSION 中, 而不是返回它的值.

雜項

>> curl_multi_exec 不改變 curl_error 當出錯的時候, 但它改變 curl_error.

>> mktime 的參數(shù)是有順序的: hour, minute, second, month, day, year

數(shù)據(jù)操縱

程序什么都不是, 除了咀嚼和吐出數(shù)據(jù)以外. 大量的語言圍繞著數(shù)據(jù)操縱設計, 從 awk 到 Prolog 到 C. 如果語言無法操縱數(shù)據(jù), 它就無法做任何事.

數(shù)字

>> Integers 在32位平臺是是有符號32位數(shù). 不像PHP的同時代者, 沒有自動 bigint 提升. 因此你的數(shù)學運算可能會由于CPU體系結構結果不一樣. 你唯一選擇大整數(shù)的方式是使用 GMP 或 BC 包裝函數(shù). (開發(fā)者可能已經建義加入新的, 單獨的,64位類型. 這真是瘋了.)

>> PHP支持八進制數(shù)語法, 以0開頭, 因此如 012 是10. 然而, 08變成了0. 8(或9)和任何接下來的數(shù)字消失了. 01c是個語法錯誤.

>> pi 是個函數(shù). 或者有個常量, M_PI.

>> 沒有冪操作符, 只有 pow 函數(shù).

文本

>> 無Unicode支持. 只有ASCII工作是可靠的, 真的. 有個 mbstring 擴展, 上面提過的, 但會稍被打擊.

>> 這意味著使用內建的string函數(shù)處理UTF-8文本會有風險.

>> 相似的, 在ASCII外, 也沒有什么大小寫比較概念. 盡管有擴展版本的大小寫敏感的函數(shù), 但它們不會認為 &eacute; 等于 &Eacute;.

>> 你不能在變量中內插keys , 如, "$foo['key']"是個語法錯誤. 你也不能 unquote it (這樣會產生警告, 無論什么地方!), 或使用 ${...}/{$...}

>> "${foo[0]}"是對的. "${foo[0][0]}"是個語法錯誤. 糟糕的拷貝類似 Perl 的語法 (兩個根本不同的語議)?

數(shù)組

嘔, 騷年.

>> 這家伙扮演list數(shù)據(jù)類型, 操作hash, 和排序set, 解析 list, 偶爾會有些奇怪的組合. 它是怎樣執(zhí)行的? 以何種方式使用內存? 誰知道? 不喜歡, 反正我還有其它的選擇.

>> => 不是操作符. 它是個特別的結構, 僅僅存在于 array(...) 和 foreach 結構中.

>> 負值索引不工作, 盡管 -1 也是個和0一樣的合法鍵值.

>> 盡管這是語言級的數(shù)據(jù)結構, 但沒有簡短語法; array(...)是簡短語法. (PHP 5.4 帶來了"literals", [...].)

>> => 結構是基于 Perl , Perl允許 foo => 1 而不用引號. 在PHP中, 你這么做會得到警告; 沒有無需引號創(chuàng)建 hash 字符串鍵值的方式.

>> 數(shù)組處理函數(shù)常常讓人迷惑或有不確定行為, 因為它們不得不對 lists, hashes, 或可能兩者的結合體做運算. 考慮 array 分組, "計算arrays的不同部分".

$first  = array("foo" => 123, "bar" => 456);  $second = array("foo" => 456, "bar" => 123);  echo var_dump(array_diff($first, $second));

這段代碼將做什么? 如果 array_diff 將參數(shù)以 hashes 看待, 它們明顯是不同的; 相同的keys有不同的值. 如果以list看待, 它們仍然是不同的; 值的順序不同.

事實上 array_diff 認為它們相等, 因為它以 sets 對待: 僅僅比較值, 忽略順序.

>> 同樣, array_rand 隨機選擇keys時, 也有奇怪的行為, 這對大多數(shù)需要從列表中挑出東西的用例沒什么幫助.

盡管大量PHP代碼依賴key的順序:

array("foo", "bar") != array("bar", "foo")   array("foo" => 1, "bar" => 2) == array("bar" => 2, "foo" => 1)

>> 如果兩個數(shù)組混合的話, 會發(fā)生什么? 我留給讀者自己弄清楚. (我不知道)

>> array_fill 不能創(chuàng)建0長度的數(shù)組; 相反它會發(fā)出警告并返回 false.

>> 所有的(很多的...) 排序函數(shù)就地操作而什么都不返回. 想新建一個已排序數(shù)組的拷貝, 沒門; 你不得不自己拷貝數(shù)組, 然后排序, 然后再使用數(shù)組.

>> 但 array_reverse 返回一個新數(shù)組.

>> 一堆被排序的東西和一些鍵值對聽起來像是個某種強大的處理函數(shù)參數(shù)的方式, 但, 沒門.

非數(shù)組

>> 標準庫包含 "快速哈希", "特定的強類型"的hash結構OO實現(xiàn). 然, 深入它, 有4類, 每種處理不同的鍵值對類型組合. 不清楚為什么內建的數(shù)組實現(xiàn)不能優(yōu)化這些極其普通情況, 也不清楚它相對的性能怎樣.

>> 有個 ArrayObject 類 (實現(xiàn)了4個不同的接口) , 它包裝數(shù)組讓它看起來像對象. 自定義類可以實現(xiàn)同樣的接口. 但只有限的幾個方法, 其中有一半不像內建的數(shù)組函數(shù), 而內建的數(shù)組函數(shù)不知道怎樣對ArrayObject或其它的類數(shù)組的類型操作.

函數(shù)

>> 函數(shù)不是數(shù)據(jù). 閉包實際上是對象, 但普通的函數(shù)不是. 你甚至不能通過它們裸名稱引用它們; var_dump(strstr) 會發(fā)出警告并猜測你的意思是字符串字面量, "strstr". 想辨別出字符串還是"函數(shù)"引用, 沒門.

>> create_function 基本上是個 eval 的包裝者. 它用普通的名字創(chuàng)建函數(shù)并在全局范圍安裝它(因此永遠不會被垃圾回收---不要在循環(huán)中使用!). 它實際上對當前上下文一無所知, 因為它不是閉包. 名字包含一個 NUL 字節(jié), 因此永遠不會與普通函數(shù)沖突 (因為如果在文件的任何地方有 NUL的話, PHP 的解析器會失敗).

>> Declaring a function named __lambda_func will break create_function&mdash;the actual implementation is to eval-create the function named __lambda_func, then internally rename it to the broken name. If __lambda_func already exists, the first part will throw a fatal error.

其它

>> 對 NULL 使用 (++) 生成 1. 對 NULL 用 (--) 生成 NULL.

>> 沒有生成器.

Web 框架

執(zhí)行環(huán)境

>> 一個單一共享文件 php.ini, 控制了 PHP 的大部分功能并織入了復雜的針對覆蓋什么與何時覆蓋的規(guī)則. PHP軟件能部署在任意的機器上, 因此必須覆蓋一些設置使環(huán)境正常, 這在很大程序上會違背像 php.ini 這樣的機制的使用.

>> PHP基本上以CGI運行. 每次頁面被點擊, PHP 在執(zhí)行前, 重編譯整個環(huán)境. 就連 Python 的玩具框架的開發(fā)環(huán)境都不會這樣.

>> 這就導致了整個 "PHP 加速器" 市場的形成, 僅僅編譯一次, 就能加速PHP, 就像其它的語言一樣. Zend, PHP的幕后公司, 將這個做為它們的商業(yè)模式.

>> 很長時間以來, PHP的錯誤默認輸出給客戶端 -- 我猜是為開發(fā)環(huán)境提供幫助. 我不認為這是真相, 但我仍然看到偶爾會有mysql 錯誤出現(xiàn)在頁面的頂部.

>> 在 <?php ... ?>標簽外的空白, 甚至在庫中, PHP以文本對待并解析給響應 (或者導致 "headers already sent" 錯誤). 一個流行的做法是忽略 ?>關閉標簽.

部署

部署方式常常被引述為PHP的最高級部分: 直接部署文件就可以了. 是的, 這比需要啟動整個進程的 Python 或 Rury 或 Perl 要容易. 但 PHP 留下了許多待改進的地方.

我很樂意以應用服務器的方式運行Web應用程序并反向代理它們. 這樣的代價最小, 而好處多多: 你可以單獨管理服務器和應用程序, 你可以按機器的多或少運行運行多個或少量應用進程, 而不需要多個web服務器,你可以用不同的用戶運行應用, 你可以選擇web服務器, 你可以拆下應用而無需驚動web服務器, 你可以無縫部署應用等等. 將應用與web服務器直接焊接是荒謬的, 沒有什么好的理由支持你這么做.

>> 每個 PHP 應用程序都使用 php.ini . 但只有一個 php.ini 文件, 它是全局的; 如果你在一個共享的服務器上, 需要修改它, 或者如果你運行兩個應用需要不同的設置, 你就不走運了; 你不得不向組織申請所有必須的設置并放在應用程序, 如使用 ini_set 或在 Apache 的配置文件或在 .htaccess設置. 如果你能做的話. 可能 wow , 你有大量的地方需要檢查以找出怎樣獲取已設置的值.

>> 類似的, "隔離"PHP應用的方法也不容易, 它依賴于系統(tǒng)的其它部分. 想運行兩個應用程序,想要不同的庫版本, 或不同的PHP版本本身? 開始構建另一人Apache的拷貝吧.

>> "一堆文件"方案, 除了使路由像只病重的笨驢外, 還意味著你不得不小心處理白名單或黑名單, 以控制什么東西可訪問, 這是因為你的 URL 層次也就是你的代碼樹的層次. 配置文件和其它的"局部模塊"需要C之類的東西守護以避免直接加載. 版本控制系統(tǒng)的文件(如 .svn) 需要保護. 使用 mod_php , 使得文件系統(tǒng)的所有東西都是潛在的入口; 使用應用服務器, 僅有一個入口, 并且僅通過 URL 控制調用與否.

>> 你不能無縫的升級那堆以 CGI-style 運行的文件, 除非你想要應用崩潰和出現(xiàn)未定義行為, 當用戶在升級的間歇期點擊你的站點時.

>> 盡管配置 Apache 運行 PHP 很"簡單", 仍然會有一些陷阱. 而 PHP 文檔建議使用 SetHandler 使得 .php 文件以 PHP方式運行, AddHandler 看起來運行良好, 然而事實上會有問題.

當你使用 AddHandler, 你在告知 Apache "以 php 執(zhí)行它" , 這是一個可能的處理 .php 文件的方式. 但! Apache 對文件的擴展名不這樣認為. 它被設計為能支持如, index.html.en 這樣的文件. 對于 Apache , 文件可以同時具有任意數(shù)量的擴展名.

猜想, 你有個文件上傳的表單, 存儲一些文件到公共目錄中. 確保沒人能上傳 PHP 文件, 你僅僅檢查文件不能有.php 擴展名. 所有的攻擊需要做的只是上傳以 foo.php.txt 命名的文件; 你的上傳工具不會看出問題, Apache 會認為它是個 PHP, 它會很高興的執(zhí)行.

這里不是 "使用原始文件名" 或 "沒有更好的驗證"導致的問題; 問題是你的web服務器要被配置用來運行任何舊代碼, 使得PHP "容易部署". 這不是理論上的問題; 我已發(fā)現(xiàn)很多實際的站點有類似的問題了.

缺失的特性

我認為所有這些都是以構建一個Web應用為中心的. 對PHP看起來很合理, 是它的銷售賣點之一, 它是 "Web語言", 理應有它們.

>> 無模塊系統(tǒng). PHP就是模版.

>> 無 XSS 過濾器. htmlspecialchars 不是 XSS 過濾器.

>> 無 CSRF 保護. 你必須自己做.

>> 無通用標準的數(shù)據(jù)庫API. 像PDO這類東西不得不包裝每個特定數(shù)據(jù)庫的API, 分別抽象不同部分.

>> 無路由系統(tǒng). 你的站點結構就是你的文件系統(tǒng)結構.

>> 無認證或授權.

>> 無開發(fā)服務器.

>> 無交互調試模式.

>> 無一致的部署機制; 僅僅"拷貝所有文件到服務器中".

安全

語言邊界

PHP的蹩腳安全機制可能會放大, 因為它利用某語言拿出數(shù)據(jù), 又把它轉存到另一個中. 這是個壞注意. "<script>" 可能在SQL中意味著什么都不是, 但在HTML中就很是了.

讓情況更糟糕的是通常有人哇哇喊到 "你的輸入要消毒". 那完全錯誤; 你不可能有什么魔法使塊數(shù)據(jù)完全"干靜". 你需要做的就是對語言說: SQL使用占位符, 進程孵化使用參數(shù)列表, 等等.

>> PHP公然鼓勵 "消毒": 有個數(shù)據(jù)過濾擴展可以做到.

>> 所有的 addslashes, scripslashes, 和其它的 slashes相關的東西都是廢物, 毫無用處.

>> 我只能告訴你這么多, 無法安全的孵化進程. 你僅能通過shell執(zhí)行字符串. 你的選擇是瘋狂的轉義, 并希望默認的shell使用正確的轉義, 或手動的 pcntl_fork_exec 和 pcntl_exec.

>> 所有的轉義命令和轉義參數(shù)存在大致相同的描述. 注意在Windows中, 轉義參數(shù)不工作 (因為它假設成 Bourne shell 語議), 轉義命令僅僅用空格替換一堆標點符號, 因為沒人能搞清楚 Windows 命令轉義行為 (它可能默默的破壞你試圖做的任何事情).

>> 原始的內建 MySQL 綁定, 仍然廣泛使用, 它無法創(chuàng)建 prepared statements.

直到今天, PHP 文檔關于SQL注入的建議還是讓人抓狂的做如類型檢查, 使用sprintf 和 is_numeric, 在每個地方手動的使用mysql_real_escape_string , 或在每處手動使用 addslashes (這個"可能更有用"!) 這樣的實踐. 并沒有提到 PDO 或 參數(shù)化, 除了在用戶評論中有點線索. 至少在兩年以前, 我就有具體的向 PHP dev 抱怨過了 , 他被驚動了, 而頁面卻從未變過.
Insecure-by-default

>> register_globals. 它被默認關閉的,而在5.4中去除了. 我不在乎.

>> include 接受 HTTL URLS. 和上面一樣.

>> Magic quotes. So close to secure-by-default, and yet so far from understanding the concept at all.

核心

PHP解釋器本身就有一些惱人的安全問題.

>> 2007年的時候, 解析器有個整數(shù)溢出漏洞. 修復始于 if(size > INT_MAX) return NULL; 從那以后就走下坡路了. (對于那些不需要使用C的人: 曾經, INT_MAX 是適合變量最大整數(shù). 我希望你能從這里搞清楚其余的東西.)

>> 最近, PHP 5.3.7 包括了個 crypt() 函數(shù), 有個漏洞讓任何人可以用任何密碼登錄.

>> PHP5.4是容易遭受拒絕服務攻擊,因為它需要Content-Length頭(任何人都可以設置),并試圖分配更多內存。這是一個壞主意。

我可以挖掘更多, 但重點不是這有很多X漏洞 -- 是軟件就有bugs, 無論如何都有. 這些自然是令人咋舌. 我并沒有特意尋找這些; 但在過去的幾個月里, 它們自己送上門來了.

總結

一些評論會理所當然的指出我沒得出任何結論. 好吧, 我是沒有結論. 如果你一路看到了這里, 我假設一開始你就同意我了 :)

如果你僅了解PHP而對學習其它東西感興趣, 可以看看 Python 教程, 嘗試 Flask 這個為web準備的家伙. (我不是它的模版語言的鐵桿粉絲, 但它確實很好的完成了這些工作.) 它將你的應用分成多個部分, 但它們看起來仍然是一致的. 我可能稍后會寫個關于這個的貼子; 旋風般的介紹整個語言和不同于這里所說的web堆棧.

之后或對于更大的項目, 你可能需要 Pyramid, 一個中等規(guī)模的框架, 或者是 Django, 一個構建站點的復雜的框架, 如 Django站點.

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。

網站題目:如何全面分析PHP的糟糕設計
標題鏈接:http://aaarwkj.com/article0/jejeio.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供企業(yè)網站制作、網站內鏈自適應網站、網站制作、網站改版虛擬主機

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

外貿網站制作
日韩毛片中文字幕在线观看| 亚洲欧美熟妇欲乱又伦| 丁香婷婷深情五月亚洲天堂| 欧美日韩一级一区二区三区| 九九热99这里有精品| 风间由美亚洲一区二区三区| 日韩无遮挡免费在线观看| 国产一区在线视频无卡顿| 免费av不卡一区二区| 高清国产国产精品三级国产av| 国产一区在线免费在线观看| 91欧美精品在线视频| 中文字幕日韩av综合在线| 久久国产亚洲欧美日韩精品| 精品国产品国语在线不卡| 日本岛国大片一区二区在线观看| 热门精品一区二区三区| 日本 一区二区在线| 日本精品视频免费网| 久久99精品久久久子伦| 国产做a爰片久久91| 搡老女人老91妇女老熟女| 日韩新片一区二区三区| 久久国产精品久久国产精品| 亚洲男人堂色偷偷一区| 国产农村妇女一区二区三区| av在线中文字幕乱码| 日韩av毛片在线观看| 黄色录像免费看中文字幕| 成年人正常性生活频率| 极品美女粉嫩啪啪高潮| 日韩一二区不卡在线视频| 人妻勾引中文字幕在线视频| 欧美福利在线观看视频| 亚洲天堂av在线有码| 日本欧美国产一区二区| 久久99国产精品成人免费| 日韩视频在线不卡观看| 人妻少妇麻豆中文字幕久久精品| 麻豆视频传媒入口在线播放 | 日韩国产传媒在线精品|