本文是 http://tnx.nl/php - 如果你要複製他,請保持這個連結。
翻譯:ShiningRay @ Nirvana Studio 目錄
* 參數和傳回值極其矛盾 * PHP對大小寫不敏感的操作使用不同的函數 * PHP的函數命名方式的不一致 * PHP沒有詞法範圍 * PHP的主名空間中函數太多 * PHP缺少抽象令 TIMTOWTDI 走向糟糕的極端 * 更多資訊
參數和傳回值極其矛盾
要展示這個問題,下面有一個函數列表,裡面的函數用來匹配使用者定義的內容:(也許甚至那些用PHP的人才會使用這個文檔,只是用來查看該用哪個函數:P) 匹配 替換使用 大小寫不敏感 返回的數字 數組參數 返回匹配 s/m/x標誌 位移(-1=結尾) ereg ereg 否 所有 否 數組 無 0 ereg_replace ereg 字串 否 所有 否 無 無 0 eregi ereg 否 所有 否 數組 無 0 eregi_replace ereg 字串 否 所有 否 無 無 0 mb_ereg ereg[1] 否 所有 否 數組 無 0 mb_ereg_replace ereg[1] 字串/運算式 否 所有 否 無 有 0 mb_eregi ereg[1] 否 所有 否 數組 無 0 mb_eregi_replace ereg[1] 字串 否 所有 否 無 無 0 preg_match preg[2] 皆可 一個 否 數組 有 0 preg_match_all preg 皆可 所有 否 數組 有 0 preg_replace preg 字串/運算式 皆可 無/所有 是 無 有 0 str_replace str 字串 否 所有 是 數字 無 0 str_ireplace str 字串 是 所有 是 數字 無 0 strstr, strchr str 否 一個 否 子串 無 0 stristr str 是 一個 否 子串 無 0 strrchr str 否 一個 否 子串 無 -1 strpos str 否 一個 否 索引 無 n stripos str 是 一個 否 索引 無 n strrpos char[3] 否 一個 否 索引 無 n strripos str 是 一個 否 索引 無 -1 mb_strpos str[1] 否 一個 否 索引 無 n mb_strrpos str[1] 否 一個 否 索引 無 -1
這種問題還存在在其他的函數組裡,不僅僅是匹配的這部分而已。
(在Perl中,所有這些功能都可以通過四個簡單的操作符來完成。)
[1] 用於處理多位元組字元 [2] PCRE regex: 所謂的“Perl相容”的Regex。 [3] 在PHP5中也是字串str PHP對大小寫不敏感的操作使用不同的函數
(這個可能會有兩方面的爭論。有些人認為提供不同的函數更好,即使這意味著又要記很多名詞了)
在Perl中,你可以使用兩個lc() 或者是 /i 標誌,而PHP通常會提供一個大小寫敏感的變數。而且,大小寫不敏感的那些版本的函數名的命名方式也不一致。 Perl: $foo cmp $bar lc $foo cmp lc $bar PHP: strcmp($foo, $bar) strcasecmp($foo, $bar) Perl: index($foo, $bar) index(lc $foo, lc $bar) PHP: strpos($foo, $bar) stripos($foo, $bar) Perl: $foo =~ s/foo/bar/ $foo =~ s/foo/bar/i PHP: $foo = str_replace("foo", "bar", $foo) $foo = str_ireplace(...) PHP: $foo = ereg_replace("foo", "bar" ,$foo) $foo = eregi_replace(...) PHP的函數命名方式的不一致
* 大小寫不敏感的函數有一個"i"或者"case"在函數名的不同的位置。 * 毫無表現上的規律 有底線的 和 沒底線的:
底線 無底線:
stream_get_line readline disk_free_space diskfreespace is_object isset mcal_day_of_week jddayofweek set_error_handler setlocale snmp_get_quick_print snmpget get_browser getallheaders base64_encode urlencode image_type_to_mime_type imagetypes msql_num_fields mysql_numfields php_uname phpversion strip_tags stripslashes bind_textdomain_codeset bindtextdomain cal_to_jd gregoriantojd str_rot13 strpos
Perl的核心函數名則沒有含有底線的。 * PHP 有 unlink 、link 和 rename 和系統調用一致,但是 touch 的系統調用是 utime, 不是 touch。 * 同時你也無法確定單詞的順序: o 賓語 動詞:base64_decode, iptcparse, str_shuffle, var_dump o 動詞 賓語:create_function, recode_string
Perl的核心函數都是“動詞 賓語”結構的除了替代的 dbm* 函數。(注意裡面的 sys 是一個首碼,而不是一個賓語。同時 flock 和 lstat 是根據系統調用命名的。shm* 和 msg* 是庫函數調用) * "to" 還是 "2"?
ascii2ebcdic, bin2hex, deg2rad, ip2long, cal_to_jd (jdto*, *tojd), strtolower, strtotime,
PHP沒有詞法範圍
Perl 有詞法範圍和動態範圍。PHP則沒有。
對於為什麼詞法範圍很重要的解釋,可以參考 Coping with Scoping. PHP Perl 超全域(Superglobal) 有 有[1] 全域(global) 有 有 函數局部 有 有 詞法域(塊局部) 無 有 動態域 無 有
[1] Perl有一些變數總是在main:: 命名空間中。這些類似於PHP的超全域變數。 [2] 在子過程的塊中使用一個詞法變數,就可以作為一個函數的局部變數。 PHP的主名空間中函數太多
(使用編譯了所有核心分發包中的可用擴充的核心庫,我們使用了2003年11月發布的版本)
PHP 主要函數的數量:3079 [1] Perl主要函數的數量:206 [2]
中值PHP 函數名長度:13 平均PHP 函數名長度:13.67 中值Perl函數名長度:6 平均Perl函數名長度:6.22
注意,Perl的一些函數有簡短的等價文法:
readpipe("ls -l") ==> `ls -l` glob("*.txt") ==> <*.txt> readline($fh) ==> <$fh> quotemeta($foo) ==> "Q$foo" lcfirst($foo) ==> "l$foo" (lc is L) ucfirst($foo) ==> "u$foo" (uc is U)
[1] 來源:PHP Quick Reference [2] 來源:perldoc perlfunc PHP缺少抽象令 TIMTOWTDI* 走向糟糕的極端
*(There Is More Than One Way To Do It,有不止一種方式來完成它)
為什麼PHP有3079個函數但是Perl卻只有206個?在PHP中,常常有好幾個十分相似的函數。在Perl中,你要瞭解和記住的要少很多。
另外一個重要的因素是模組的使用,尤其是DBI模組??它用來提供資料庫支援,而不是把很多特性塞進核心,佔用了空間卻很少用到。
(不常用的模組不計算在內(所以這裡排除了PHP的PEAR和Perl的IO::File)). 如果核心沒有提供類似的功能,那麼這些模組也會算在裡面。為了簡便起見,內部的工作方式將會忽略。)
*
轉義:
o
PHP: (14) dbx_escape_string, escapeshellarg, escapeshellcmd, pg_escape_bytea, pg_escape_string, pg_unescape_bytea, addslashes, addcslashes, preg_quote, quotemeta, mysql_escape_string, mysql_real_escape_string, mysqli_real_escape_string, sqlite_escape_string
o
Perl: (2) [1] quotemeta, $dbh->quote
*
排序:
o
PHP: (16) sort, arsort, asort, krsort, ksort, natsort, natcasesort, rsort, usort, array_multisort, uasort, uksort, dbx_sort, imap_sort, ldap_sort, yaz_sort
o
Perl: (1) sort
*
遍曆列表:
o
PHP: (10) array_filter, preg_grep, array_search, array_unique, in_array, array_map, array_walk, array_count_values, array_change_key_case, array_sum
o
Perl: (2) map, grep
*
分割:
o
PHP: (8) split, explode, strtok, spliti, chunk_split, mb_split, preg_split, str_split
o
Perl: (1) split
*
匹配:
o
字串:
+
PHP: (11) strstr, strchr, stristr, strpos, strrchr, stripos, mb_strpos, mb_strrpos, strrpos, strripos, substr
+
Perl: (3) index, rindex, substr
o
Regex:
+
PHP: (6) ereg, eregi, mb_ereg, mb_eregi, preg_match, preg_match_all
+
Perl: (1) m//
*
替換匹配部分:
* PHP: (12) ereg_replace, eregi_replace, mb_ereg_replace, mb_eregi_replace, preg_replace, str_ireplace, str_replace, ltrim, rtrim, trim, nl2br
* Perl: (1) s///
*
串連到資料庫:
o
PHP: (17 或更多) dbx_connect, fbsql_connect, ibase_connect, msql_connect, msql_pconnect, mssql_connect, mysql_connect, odbc_connect, pg_connect, pg_pconnect, sesam_connect, ifx_pconnect, ifx_connect, sqlite_open, sqlite_popen, mysqli_connect, mysqli_pconnect
o
Perl: (2) DBI->connect, DBI->connect_cached
*
開啟(檔案、進程等):
o
PHP: (5) dio_open, fopen, proc_open, popen, gzopen[2]
o
Perl: (2) open, sysopen
*
讀取/接收:
o
PHP: (12) dio_read, fread, gzread[2], socket_read, socket_recv, socket_recvfrom, socket_recvmsg, readline, fgetc, fgets, stream_get_line, file
o
Perl: (5) read, readline, sysread, recv, getc
*
列印/輸出/寫入:
o
PHP: (14) print, echo, printf, fprintf, vprintf, dio_write, fwrite, fputs, gzwrite[2], socket_send, socket_sendmsg, socket_sendto, socket_write, socket_writev
o
Perl: (5) print, printf, syswrite, send, write
*
關閉:
o
PHP: (7) closelog, dio_close, fclose, gzclose[2], pclose, socket_close, proc_close
o
Perl: (1) close
*
常用/工具:
o
PHP: array_combine, array_fill, array_flip, array_merge, list, range, count, create_function, strtr, pow, putenv, getenv, getmygid, getmypid, getmyuid
o
Perl: 使用文法或者魔術變數
[1] 因為系統的LIST文法和DBI的預留位置,顯式轉義常常是不需要的。 [2] 在Perl中是由PerlIO層來處理的。 更多資訊
* Re^2: Is Perl a good career move? by Juerd, 2005 o 依然沒有命名空間 o 沒有閉包,甚至沒有匿名函數 o 沒有良好的HTML分析器 o 沒有簡單的MIME構建工具 o 沒有良好的WWW庫 o 沒有 CPAN o 沒有數組 o 沒什麼用的邏輯操作符 * Yaywoo! by Dave Brown, 2004 o 使用system()無法避免(不安全的)shell o XY-problem o 大量的不同程式,但是,很多隻是做了差不多的事情的變體 o 第二參數和傳回值毫無意義 o 函數名的差勁拼字方式 * Why PHP sucks by Edwin Martin, 2004 ,中文翻譯 為什麼PHP令人不爽(對於大型系統) By ShiningRay o 不良的遞迴支援 o PHP 不是安全執行緒的 o PHP 由於商業原因而不健全 o 沒有命名空間 o 非標準的日期格式化字元 o 混亂的許可證 o 不一致的函數命名規則 o 魔法引用地獄 * Perl vs. PHP - octo"s subjektiver Vergleich by Florian Forster, 2003 (German) o Perl 比 PHP 快很多 o Perl 比 PHP 更豐富 o Perl 比 PHP 有更好的文檔 o PHP 缺乏模組化支援 o PHP的here-docs對Windows使用者毫無用途 o PHP 缺少一致的資料庫API o PHP 快取資料庫查詢結果很危險 o 圖形上,PHP實際上被限制在了 GD 中 * I hate PHP by Keith Devens, 2003 o 白癡似的??調用時不推薦引用傳遞 * Experiences of Using PHP in Large Websites by Aaron Crane, 2002 o PHP 是推薦把表現和商務邏輯結合起來的 o 沒有命名空間造成很多問題 o php.ini 的全域配置 o 過分簡單化導致了額外的複雜度 * PHP Annoyances by Neil de Carteret, 2002 o 沒有真正的引用或者指標 o 毫無命名空間的概念 o 毫不組件化 o 想變成Perl,但事實上也沒想變成Perl o 沒有標準的DB介面 o 所有的PHP社區都是針對非程式員的 o 不支援鏈式方法調用 (現在已經不是了 --tnx.nl) o 沒有全域變數除非通過匯入 o register_globals 和 $_REQUEST 都讓人痛心 o 數組都是哈西表 o PEAR 並不是 CPAN o Arrays 不能插入值替換成字串(如$a=array();$b="$a";是錯誤的) o 沒有類似 "use strict" 用來檢驗變數名的功能 * PHP: A love and hate relationship by Ivan Ristic, 2002 o 社區令我不安 o 知識淵博的人少之又少 o Zend 發布的文章還建議不安全的實踐方式 * My list of PHP shortcomings by Nathan Torkington, 2001 o 沒有命名空間 o 所有的函數都是全域的 o 沒有真正的引用 o 沒有真實的資料結構 (現在已經不是了 --tnx.nl) o 沒有匿名函數
引用
EFnet #php: 19:45 <+Dragnslcr> Comparing PHP to Perl is like comparing pears to newspapers
Perl Monks: PHP - it"s "training wheels without the bike" -- Randal L. Schwartz
(::: |