今天撞牆撞很大….由於手邊在碰的一個專案裡面需要產生類似驗證碼的圖片,他用了 imagecreate()
, imagettftext()
, imagesetpixel()
這些 PHP functions。聽說這支程式「曾經」是可以 work 的,不過在我手上就不 work,為了證明不是人品問題,一定要把這個 bug 修掉!
一開始我傻傻的在程式碼裡面翻找,但這樣實在太沒效率了,身為一個專業的….呃…雜工,一定要懂得善用工具!所以我用了….. command line php…..
$ php image.php > /dev/null
對啦,只不過是測試環境從 apache 換到 command line 底下了,這樣是有比較強嗎?有喔~因為我的測試環境有裝 xdebug,只要有 enable 就可以在 command line 底下看到 debugging messages,不用特別打開 stack trace。至於最後面把 standard output 導向 /dev/null
是為了不想看到他輸出的那張不完整的圖,那會干擾畫面。
首先第一步,我忘記詳細的訊息了,大意是說 imagecreate() is undefined
等等,這時候當然要去找找這函式有沒有需要什麼相依的 library 啊!找了一下發現,這些函式是由 PHP 的 GD module 所提供的,所以我迅速的安裝了 GD 模組…
$ sudo apt-get install php5-gd
接著,才是重頭戲的開始….
裝好 GD 模組之後,那些 function 都可以使用了,但是我卻一直收到這個錯誤訊息….
PHP Warning: imagettftext(): Could not read font .....(後略)
當然這訊息也是伴隨著 stack trace 的,看看傳進去的字型參數,用的是相對路徑 include/font/font.ttf
,當下懷疑是不是找不到檔案,用 realpath()
來幫忙看看…
echo realpath($font_path);
但是,咦,怎麼什麼都沒出現?大概花了 30 秒我才發現我做了蠢事….我已經把 standard output 丟掉了啊XD 上網找了一下「php stderr」立刻找到應該要這樣做
file_put_contents('php://stderr', realpath($font_path));
印出來之後,發現我給他的路徑是正確的,怎麼會這樣呢?苦惱許久,才想到要去查查 imagettftext() 的 manual,發現了驚人的事情!
原來,某些版本的 GD 會在你給他的路徑是相對路徑時,使用環境變數 GDFONTPATH
當作前綴,並且在最後補上 .ttf
。另外,版本低於 2.0.18 的 GD 還不允許路徑裡面有空白字元。檢查了一下…嗯,路徑沒有空白字元,那會不會是路徑問題?參考官方 manual 提供的 sample code:
<?php
// Set the enviroment variable for GD
putenv('GDFONTPATH=' . realpath('.'));
// Name the font to be used (note the lack of the .ttf extension)
$font = 'SomeFont';
?>
我自己設定好了正確的 GDFONTPATH
也把後面的 .ttf
拿掉,依然不 work….到這裡我已經快崩潰了….即使我發瘋似的交叉測試拿掉或加上 .ttf
、更改路徑、使用絕對路徑等等,都還是失敗。
接著我又開始想,會不會是別的原因?來看看檔案權限好了….
$ ls -l include/font/font.ttf
很好,檔案權限是 644 (rw-r--r--
),應該沒問題吧?算了,死馬當活馬醫,改成 777!!
$ chmod 777 include/font/font.ttf
可想而知,還是炸了…..
在網路上找來找去,碰到類似問題的人大多是這幾種狀況:
- 路徑錯誤 (前面提到的相對路徑問題)
- 檔案從 windows 傳到 unx 上就無法 work 了 (因為 unx 對檔名是 case-sensitive 的)
- 把
ttf
寫成tff
(這是他自己耍笨了…)
很多人問問題會列出自己的 GD 版本,那我也來看看有沒有什麼端倪
$ php -i
...
gd
GD Support => enabled
GD Version => 2.0
FreeType Support => enabled
FreeType Linkage => with freetype
FreeType Version => 2.4.8
T1Lib Support => enabled
GIF Read Support => enabled
GIF Create Support => enabled
JPEG Support => enabled
libJPEG Version => unknown
PNG Support => enabled
libPNG Version => 1.2.46
WBMP Support => enabled
Directive => Local Value => Master Value
gd.jpeg_ignore_warning => 0 => 0
...
就沒問題嘛 orz
我已經確定我的路徑是完全正確的,而且也是絕對路徑,檔案權限也確定是可以讀取的,GD module 看起來沒有什麼錯,那到底是什麼問題?心灰意冷之際,我想說不然拿現有的其他字型來試試看好了。事實上該專案裡本來有好幾個字型檔,我早就試過幾個都不 work,結果沒想到改成用自己系統本來有的字型,就成功了!太崩潰了!!! 可是還是很高興,立馬回到本來的程式上,加上剛剛使用的字型的絕對路徑,一切都搞定了!(超開心)
所以總結而言,我一開始的環境沒辦法正確執行這個程式,只有兩個原因
- 缺少 php-gd
- 字型檔有某種錯誤
我對字型不太有研究,所以就無法深究該字型檔究竟有什麼問題,畢竟用 file
去看他還是個正常的 True Type font 啊….
$ file font.ttf
font.ttf: TrueType font data
會不會跟編碼有關係呢?可是我用的只是一個 "1"
耶…..
好吧,雖然還是帶著懷疑,不過主要的問題算是解決了,結案!!!
Last modified on 2012-05-31