抱怨你的工具,並不會讓你的事情做得更好。
我前一篇的「PHP 開發迷思 (三) – PHP 很糟糕?」,有網友寫了一篇「 PHP 很爛」來回應。
我想說的是:對他來說, PHP 的確很糟,所以真的不適合他;因為他引用了別人停留在三四年前的 PHP 的觀念來證明他對 PHP 的看法。還有,他看到的都是爛 PHP 程序。
不可否認, PHP 的確在先天上有所不足,只因為它誕生的太早,很多包袱無法輕易擺脫。即便 PHP 6 將會擺脫這些束縛,但時間點似乎太晚?
所以呢?難道研究 PHP 的人都是傻瓜嗎?
當然不是。
我不想為 PHP 平反什麼,我也不認為我能改變多少人對 PHP 的看法。這裡我只想把這些人認為 PHP 爛的地方做個說明,剩下的就交給大家自行評斷。
版本問題
從 PHP 誕生以來有十五年了,真正被大家重視而開始運用的第 4 版則有十年了。
然而隨著 PHP 5 的誕生,以及 2008 年 PHP 4 不再被官方維護,大部份的主機商也已經部署了 PHP 5 作為主要執行環境;雖然現階段 PHP 5 還是會讓 PHP 4 的程序能夠執行,但是開發者的觀念如果沒有一起隨著更新,那才是災難的開始。
語言的設計本來就沒辦法一開始考慮周詳, Java 如此, Python 也是如此,它們在重大改版時,部份語法及相關的核心組件上本來就會有所改變。而開發者如果沒有適時去了解在新版本上的使用差異,那麼跟抱怨一把生銹的斧頭很難砍倒一棵大樹有什麼差別?
Unicode
Unicode 在最近這幾年才開始被台灣的開發者所重視,在那之前 BIG5 大概是他們的惡夢吧。
先不管 PHP ,我們來看一下別的語言怎麼處理 Unicode 。
Ruby: 就我粗淺的了解, Ruby 本身也不完整支援處理 Unicode ,但還是可以處理。
Python: 在 2.x 版也是透過 unicode 類別來處理,在 3.0 核心有直接支援。
那麼 PHP 呢?
的確 PHP 本身沒有很方便的方法來處理 Unicode ,但是不表示它不能用其他方法來處理:
mbstring: 多位元組的字串處理
iconv: 轉換編碼
PHP 6 以後則是直接把 unicode 放到核心函式裡。
當然 PHP 先天的限制,會讓它在處理 Unicode 字串上無法像 Ruby 和 Python 那麼直覺;但不表示我們不能透過其他方法將它封裝起來,方便後續的開發。
在資料庫上的 Unicode 問題也是如此, PHP 本身不處理這些,它只是透過 clIEnt 來取得資料庫回傳的資料,這在每個語言對資料庫的實作都是一樣的。
Magic Quotes
一開始 PHP 有 magic_quotes 只是為了方便處理要塞入資料庫的字串,因為當時 PHP 開發者對於程序與資料庫之溝通非常不熟悉。
然而,這只是資料分層處理的觀念。
事實上我們根本不該對接收下來的資料做假設,如果輸入的資料是「許功蓋 (BIG5) 」,就讓它保持「許功蓋 (BIG5) 」;等到要存入資料庫時,再讓真正的資料操作函數 (或物件) 去處理它 (像是 PDO::quote ) ,而不是再用 addslashes() 或 stripslashes() 這種別扭的方式來存取資料庫。
而從資料庫取得資料時也是一樣,因為我們用正確的方法塞入,所以它也會回傳我們正確的資料,這在所有語言都是一樣的!
所以後來的 PHP 5.3 版本就將 magic_quotes 廢棄, PHP 6 則直接不支援。
而在這之前的版本所開發出來的程序,也都是該以 magic_quotes 保持關閉的狀態來開發;遇到不確定 magic_quotes 是否開啟時,可以參考官方手冊的建議來取消它對程序的影響。
SQL Injection
某網友說:「填‘; shutdown — 就能打掛一票網站…,九成可能都是 PHP 寫的」,又說「我知道 SQL (Injection) 是跨語言的問題,但是 PHP 就是偏偏特別容易寫出有洞的程序 像這樣 “SELECT * FROM User WHERE id = $user_id” 然後就毀了。」
我個人倒認為,有九成以上會有 SQL Injection 問題的,可能是傳統的 ASP 網站。 (這邊 ASP 只是舉例,不表示真的九成以上都是這樣;事實上沒有引用一個正確的統計數字,這都只是嘴炮而已,請塬諒我用這麼粗俗的字眼)
從他寫的程序可以看得出來,如果他用的語言沒有一個正確的工具,那麼他還是有可能寫出有 SQL Injection 的網站。
其實上面提到的 magic_quotes 的目的之一,原來也是要解決 SQL Injection 的問題,但顯然我們有更好的方法來處理它。另外基本的輸入資料過濾也非常重要,設一道關卡來檢查輸入的正確與否本來就是程序設計師該做的;或許你可以用 Application Firewall 來完成,可是程序本身的防範措施才是最根本的解決之道。
語言本身幫我們做到一切當然是最好,但這不表示一位優秀工程師該把原本就有的技術與觀念全都依賴在工具上。
Web Framework
某網友說:「 PHP 一般要寫一周的網頁程序,可能我用 Python + TurboGears 一天就能寫完」,也有網友說:「 Xdite 用 RoR 一晚上就寫好莫拉克風災支援網」。
有趣的是,一個熱血又熟悉 CakePHP 或 CodeIgniter 的 PHP 開發者也可以做到同樣的事。
重點有三個:
PHP 也有 Web Framework 。
對這個 Framework 夠不夠熟悉。
有沒有熱血。
Web Framework 是在這三四年來 Web 開發方向趨於明顯時的產物,它可以說是一個語言想通往 Web 開發的鑰匙。所以像 Python 上的 Django 及 TurboGears 、 Ruby 上的 RoR 等,都是展現語言特色的優秀框架。
回頭來看看 PHP ,它在定義上也只是一個可以用來開發 Web 的 Script 語言;拿 TurboGears 來跟 PHP 比較,層級上實在是差太多了! PHP 在 Web 開發的門檻是很低,但不表示它就是沒有效率、不夠安全!因為這些都是開發者該去注意的!任何語言都一樣!任何號稱可以快速建置網站的開發者,只不過仰賴著 Web Framework 幫他們處理掉一些塬本是他該注意的事情而已。
換個角度來看,如果不依靠 Framework ,而有能力在一天之內用 Python 或 Ruby 語言本身硬刻出一個安全又快速網站的人,我想也是萬中無一吧。注:事實上只要能跟 Web Server 溝通,就連 VB 或批次檔都可以用來寫 CGI ,但真的是太麻煩了。
結論
語言本身沒有好壞之分,因為所謂的爛不爛都是決定於怎麼用它來開發的人。任何工具一定有用得順手和用得不順手的問題,看開發者用什麼樣的心態去面對而已。
依賴語言或框架本身的優勢的確很方便,但一旦脫離了它們,卻無法保證能開發出好的程序,這不是一個優秀的工程師。
我不否認 PHP 確實有缺陷,但我不傾向去抱怨它們。了解它的優缺點,正確的使用它才是身為 PHP 開發者所應該走的方向。
一切都是開發者本身的問題。