最近在PHP4,PHP5上發現有些程式不相容的問題,在PHP4程式可以運行的程式,到了PHP5環境反而出現了
Cannot modify header information – headers already send by…..的錯誤訊息
以前遇到這種問題,就是在使用Header之前已經有output到瀏覽器,在找問題時,一般是include file或在<?PHP ?>前後有空白字元
但PHP4可以執行正常,怎麼到了PHP5會出問題呢?
去追查了一下,發現這似乎是UTF8檔案格式的問題,現行UTF-8格式的檔案,在檔頭會有一個BOM(Binary Order Mark)的字元,印象中在以前的經驗上,往往在處理UTF-8格式的XML,有時也會被這個BOM弄煩了
看來這次也是一樣,因為目前PHP似乎在針對UTF-8的php程式碼,沒有把這BOM碼處理的很好,導致如果有使用Header() 或是include file 時就會發生一些問題
小弟在此整理出一些解法:
1.如果你可以動到php的參數設定檔,那就簡單多了,請在php.ini之中調整output_buffering參數,這參數預設是沒有啟用的,要將此參數打開,就是把 分號(;)拿掉即可,如下:
output_buffering = 4096
這個參數是開了個buffer給output時用的,看php.ini上的註解提到這個是要讓程式允許可以在傳送header及cookies時可暫存的buffer,當使用時就不會直接傳到Client啦;不過這會有一些些影響整個PHP的執行效能,但影響不大啦,這算是最快可以排除的方式,所以列在第一點給大家參考!!
2.如果你有使用UltraEdit(至少是版本14以上才有這功能),可以於存檔時選擇檔案格式UTF-8並且無BOM版本的檔案,這樣就可以避掉BOM會帶來的問題了 (沒有BOM也不會造成UTF-8檔案格式的判斷錯誤)
或是可以下載NotePad++,這套 free的文字編輯器,可到此連結下載http://notepad-plus.sourceforge.net/tw/site.htm 台灣人寫的哦~要愛用國貨外!!
在開啟檔案時,上方選單編碼選項中的「轉換至UTF-8碼(檔首無BOM碼)即可(原文章相關錯誤已修正,感謝那位叫白目捷的友人提供指證),如下圖:
不過目前要一個一個檔案去做,小弟找了一下,似乎沒有找到可以批次去除BOM的,所以暫時加減用囉~!! 如果有大大知道有程式可以做到,請再告知小弟! 感恩喔!!
上述就是小弟整理的解法,不過要注意在不同的PHP版本上執行時,還要注意例如session_start()這個函式一定要在最前面執行,不然也有可能會於PHP5上顯示錯誤訊息
參考資料:
http://bbs.ecstart.com/thread-30347-1-4.html
PHP相關的函式真的是很多,而且都蠻簡單操作的
單單要讀CSV檔,只要透過fgetcsv 函式就可以處理,而且還可以把擾人的雙引號問題一併排除,不過在使用時,發現中文的處理上有一些瑕疵
上網找了一些資料,針對此問題有蠻多解法,不過還是要看一下問題發生原因
1.如果你的資料檔是big5,就要在讀入時進行iconv or mb_convert_encoding 轉成UFT-8才能使用
2.如果你都是utf-8還遇到問題,就是fgetcsv 的問題啦(我就是這個啦)
所以找到一篇有人重寫了fgetcsv ,試用後發現問題排除了,所以也分享一下解法
function __fgetcsv(&$handle, $length = null, $d = “,”, $e = '”') {
$d = preg_quote($d);
$e = preg_quote($e);
$_line = “”;
$eof=false;
while ($eof != true) {
$_line .= (empty ($length) ? fgets($handle) : fgets($handle, $length));
$itemcnt = preg_match_all('/' . $e . '/', $_line, $dummy);
if ($itemcnt % 2 == 0)
$eof = true;
}
$_csv_line = preg_replace('/(?: |[ ])?$/', $d, trim($_line));
$_csv_pattern = '/(' . $e . '[^' . $e . ']*(?:' . $e . $e . '[^' . $e . ']*)*' . $e . '|[^' . $d . ']*)' . $d . '/';
preg_match_all($_csv_pattern, $_csv_line, $_csv_matches);
$_csv_data = $_csv_matches[1];
for ($_csv_i = 0; $_csv_i < count($_csv_data); $_csv_i++) {
$_csv_data[$_csv_i] = preg_replace(“/^” . $e . “(.*)” . $e . “$/s”, “$1”, $_csv_data[$_csv_i]);
$_csv_data[$_csv_i] = str_replace($e . $e, $e, $_csv_data[$_csv_i]);
}
return empty ($_line) ? false : $_csv_data;
}
經過使用上面的函式,中文字解析出來,字首不會再是亂碼了,但有點要特別注意的,如果你後方有帶很多空值的欄位,他會一併清除,這和原本的fgetcsv 不太一樣,在轉換時要特別注意。
資料來源:
http://blog.csdn.net/shilian_h/archive/2009/07/22/4371051.aspx
在PHP要顯示貨幣金額,就是有加上逗號「,」的數字是很容易的
原本以為是要使用printf 函式,結果去查了一下,有個number_format 函式就可以達到
以下為他的語法
string number_format(float number, int [decimals], string [dec_point], string [thousands_sep]);
如想看更詳細的說明,請至 http://php.net/manual/en/function.number-format.php
所以我們可以用以下指令
$return=number_format(“1000000.1234″,4,”.”,”,”);
就可以得到1,000,000.1234,看起來還蠻容易的,結果再進一步的測試,發現怪怪的
當我的值為 10000000000000.4232326 應該可以得到
10,000,000,000,000.4232
沒想到結果不對了,竟然得到如下的資料,小數的數值不對了
10,000,000,000,000.4238
多測了幾組,都發現這狀況,看來在數值大於一定位數時,就會有錯亂,應該是PHP數值的變數接受的位數有限,所以大於的數值就可能會補數來補數去的吧..反正就是亂了
所以為了這種位數超大的值,小弟寫了一個小函式,改用字串的方式處理,就可以排除此問題
function money_format($data,$n=0) {
$data1=number_format(substr($data,0,strrpos($data,”.”)==0?strlen($data):strrpos($data,”.”)));
$data2=substr( strrchr( $data, “.” ), 1 );
if($data2==0) $data3=””;
else {
if(strlen($data2)>$n) $data3=substr($data2,0,$n);
else $data3=$data2;
$data3=”.”.$data3;
}
return $data1;
}
傳入值為$data 就是你要轉換的數值,$n就是小數點後面的位數
除了排除這個問題,在使用number_format時發現如果設定小數位數四位,如不足四數就會補零 。例如: 100000.12 會顯示 100,000.1200 ,所以小弟也順便調整,可以把後面的零給取消掉。在此提供給一樣遇到這問題的人一個方法(不一定是好方法,但一定是可行的方法)
最近在執行一項功能時,發現都會出現Maximum execution time of 30 seconds exceeded的錯誤訊息
查了一下,才知PHP預設執行時間超過了30秒的限制時,會丟出這個訊息,如果要執行一些複雜的動作
或是讀資料庫過久時,像產生報表時,可能30秒是不夠用的。
所以要調大這個限制時間,要去調整 php的參數設定檔才行
一般php.ini 於Linux平台是在 /etc/php.ini ,如果是windows平台就是在c:\windows之下
找到打開後,搜尋一下 max_execution_time就可以找到
max_execution_time =30
就是這個參數限制執行時間,所以可以調整為限兩分鐘就是120 (請斟酌調整)
這樣,再重開你的apache就行啦~~
近期留言