標籤:not base 變數 title header 輸出 自己實現 window 中文
10、filesize緩衝的問題
PHP的filesize居然會緩衝(當然還有不少,這裡僅用filesize舉例,其它會緩衝的函數,以官方文檔為準)
線上代碼經常隨機出各種問題,排查了1個月,線上加各種日誌,最終發現是filesize緩衝的問題,如下代碼:
[php] view plain copy
- echo filesize("a.txt");
- exec("rm a.txt"); // 刪除檔案
- echo filesize("a.txt"); // 這裡會輸出大小,而不是報錯說檔案不存在
-
- echo filesize("b.txt");
- echo filesize("a.txt"); // 這裡會報錯檔案不存在,因為只緩衝最後一個檔案,緩衝裡只有b,沒有a的緩衝了
看到了吧,filesize不僅有緩衝,而且還只緩衝最後一個檔案,所以說PHP的開發人員也不知道怎麼考慮的,就不會加個filesize_withcache方法?
知道了原因,解決也就簡單了,在filesize調用前清除緩衝,加代碼: clearstatcache()
參考官方文檔:http://php.net/manual/zh/function.filesize.php
9、儲存源碼檔案時,注意要使用utf-8無bom簽名
之前用Windows的記事本編輯檔案,發布到Linux上線後,一直報錯:Cannot modify header information - headers already sent by (output started at xxx.php:1)
用Winmerge或BeyondCompare對比代碼也無法發現問題,後來用Netbeans才發現檔案最前面多了一個不可見字元,研究後才知道是Windows的Bom簽名
也就是說,在Windows上開發,在Linux上發布,注意要使用不支援Bom的編輯器,如果用VisualStudio要選擇進階儲存選項裡的不帶簽名
1、null和空、0、false等四個值的比較
在PHP中,== 會先進行類型轉換,再進行對比,而===會先比較類型,如果類型不同直接返回不相等,參考如下樣本
[php] view plain copy
- $a = null; $b = ‘‘; $c = 0; $d = false;
- echo ($a == $b)?1:0; // 輸出1
- echo ($a === $b)?1:0; // 輸出0
- echo ($a == $c)?1:0; // 輸出1
- echo ($a === $c)?1:0; // 輸出0
- echo ($b == $c)?1:0; // 輸出1
- echo ($b === $c)?1:0; // 輸出0
- echo ($a == $d)?1:0; // 輸出1
- echo ($a === $d)?1:0; // 輸出0
對於我這種以前唯寫js或C#代碼的碼農,被這幾個值忽悠過n次,n大於3
2、strrchr函數
在W3School網站上的注釋如下:
strrchr() 函數尋找字串在另一個字串中最後一次出現的位置,並返回從該位置到字串結尾的所有字元。
如果成失敗,否則返回 false。
實際上,這個函數是尋找某個字元,而不是尋找字串,應該參考官方文檔
程式碼範例:
[php] view plain copy
- $a = ‘abcdef.txt‘;
- $b = ‘.php‘;
- echo strrchr($a, $b);
上面的代碼輸出是:.txt
也就是說,如果$b是字串,只使用第一個字元,後面的其它字元會忽略
註:php提供了strstr函數,為什麼不提供strrstr函數呢,雖然自己實現也很簡單
3、foreach裡的引用賦值,參見官方文檔
這個引用賦值很好哇,對用C#的我,在C#裡要修改foreach的元素,是不可能的,是會出異常滴,php把這個變成了可能,但是:
在官方文檔裡有一句警告:Warning 數組最後一個元素的 $value 引用在 foreach 迴圈之後仍會保留。建議使用 unset() 來將其銷毀。
我們看一組代碼:
[php] view plain copy
- $a = [1,2,3];
- foreach($a as &$item){
- echo $item . ‘,‘;
- }
- //unset($item); // 引用賦值後不銷毀對象
- foreach($a as $item){
- echo $item . ‘,‘;
- }
上面的代碼的輸出如下:
1,2,3,1,2,2 看最後一個輸出的是2,而不是3,就是因為代碼裡沒有銷毀$item造成的,原因如下:
第一個迴圈,把3的引用賦給了$item,第二個迴圈,把1賦給了$item,因為$item是引用,導致數組的元素3變成了1,明白了嗎?
4、isset與empty的聯絡和區別,isset文檔 empty文檔
empty對如下8種情況返回true:
null、 空串""、字串0"0"、空array、布爾值false、數字0、浮點數0.0、類裡用var定義但是未賦值
isset 檢測變數是否設定,並且不是 NULL,但是對於empty的8種情況,只有null返回false,其它7種情況都返回true
綜上所述,除了empty描述的的非null的7種情況,在其它情況下, if(empty(變數)) 等效於 if(!isset(變數))
靈活用法一則:直接存取 $arr[‘aaa‘] 可能報錯,說aaa不存在,可以用:
if(isset($arr[‘aaa‘]){ 作業碼} 或 if(!empty($arr[‘aaa‘]){ 作業碼}
5、trim函數遇到中文空格時,會亂碼
[php] view plain copy
- $str = ‘ 《前後有全半形空格》 ‘;
- var_dump($str);
- $str2 = trim($str, ‘ ‘);
- var_dump($str2);
- $str3 = mb_ereg_replace(‘^(?:\s| )+|(?:\s| )+$‘, ‘‘, $str);
- var_dump($str3);
- $str4 = mb_ereg_replace(‘^[\s ]+|[\s ]+$‘, ‘‘, $str);
- var_dump($str4);
參考如上的代碼,輸出結果:
[plain] view plain copy
- string ‘ 《前後有全半形空格》 ‘ (length=38)
- string ‘?前後有全半形空格》‘ (length=28)
- string ‘《前後有全半形空格》‘ (length=30)
-
- A PHP Error was encountered
- Severity: Warning
- Message: mb_ereg_replace(): mbregex compile err: invalid code point value
可以看出:trim導致亂碼出現了,正則^(?:\s| )+|(?:\s| )+$ 可以正常工作,而正則^[\s ]+|[\s ]+$卻編譯異常,原因我還沒搜尋到
6、intval在Windows和Centos上,最大值範圍不同
在centos上,intval轉換的最大值是9223372036854775807,
而在我的Win7x64+64位的php上,轉換最大值卻是2147483647,非常奇怪,手冊明明說64位系統都是9223372036854775807,
這麼大一坑啊,官方解釋php6以下在win上僅是測試版,不支援64位
7、MySQL欄位類型為varchar時,不能用where xx=123來檢索,會無法利用索引
建議所有SQL的值都用單引號括起來,如:where xx=‘123‘,如果欄位類型為int,也能正確利用索引
8、執行SQL後不判斷傳回值,或判斷邏輯錯誤:
$sql = ‘insert into app_log(id) select 0 from dual where 1=2‘; $this->db->query($sql); return true; // 不加判斷,直接返回true |
$sql = ‘insert into app_log(id) select 0 from dual where 1=2‘; $result = $this->db->query($sql); if ($result) { // 有bug,插入不成功,result也是true return true; } return false; |
上面的2段代碼應該改成:
$sql = ‘insert into app_log(id) select 0 from dual where 1=2‘; $this->db->query($sql); // 如果sql有文法問題,affected_rows是-1 if ($this->db->affected_rows() > 0) { return true; } return false; |
注意:mysql中,update a set name=‘123‘ where id=1;
如果id為1的記錄,name已經是123,那麼這條update語句的affected_rows()=0
原文連結:http://blog.csdn.net/youbl/article/details/41014367
php常見的坑