目前 PHP 5 最後一個承載維護的版本:5.6,將於今年年底中止維護。也就是不會再有新功能,且就算有錯誤、安全漏洞也不會再繼續修補。
所以建議大家盡快升級手邊的 PHP 專案至 PHP 7。
個人的經驗,可以跳過 7.0 直接上 7.1,畢竟 7.1 主要是新增一些 7.0 還不支援的功能,沒有他太大的異動。7.2 主要是對效能調整,和新增一些語法,要直接跳 7.2 也不會花太多時間改程式。
軟體開發和生活瑣事
今天是測試 Memcache::connect() 踩到的問題。
先來看看文件上的說明:
所以我的程式就這樣寫:
$c = new Memcache();
$stat = $c->connect('localhost');
if (false === $stat) {
echo 'connection failed';
} else {
echo 'connected to cache server';
}
測試時把 Memcached shutdown 來看看是否會偵測到連線失敗。執行時卻噴了一堆錯誤訊息:
Warning: Memcache::connect(): Can't connect to localhost:11211, Connection refused (111) in /home/u/he5702/tmp/asd.php on line 4
Call Stack:
0.0001 355600 1. {main}() /home/u/he5702/tmp/asd.php:0
0.0001 355640 2. Memcache->connect() /home/u/he5702/tmp/asd.php:4
connection failed
文件上面並沒有提到 library 除了回傳 false 以外,還會噴一堆錯誤訊息。萬一這隻是 JSON API 就一定會導致 client parse error。
所以應變方法用「@」來隱藏錯誤訊息:
$stat = @$c->connect('localhost');
寫程式真的很怕遇到 undefine behavior,如果文件上都寫清楚的話,在 dev / staging 上都可以事先檢查、防範。但連文件都沒有寫,就只能等個被廣大的客戶客訴到死 ….。
我還以為 PHP SPL 的類別應該實作上應該有比較嚴謹,但 … 我錯了 QQ
先來看一下 SplPriorityQueue 的官方文件定義:
priority 和我預期的不一樣,原本以為只能放數字 (numbers) 但這邊的 priority type hint 卻標示為「mixed」,表示 priority 可以是任何資料型態 …?
先從最一般的 case 來測試吧:
$q = new SplPriorityQueue();
$q->insert(1, 'A');
$q->insert(2, 'B');
$q->insert(3, 'C');
$q->insert(4, 'D');
$q->insert(5, 'E');
while ($q->count() > 0) {
echo $q->extract() . PHP_EOL;
}
output:
5
4
3
2
1
看起來會用 ASCII 數值來比較,數值大的優先 dequeue。看起來沒問題。
再來看一下遇到相同 priority 中有多個數值時,到底會發生什麼事:
$q = new SplPriorityQueue();
$q->insert(1, 1);
$q->insert(2, 1);
$q->insert(3, 1);
$q->insert(4, 1);
$q->insert(5, 1);
while ($q->count() > 0) {
echo $q->extract() . PHP_EOL;
}
output:
1
5
4
3
2
「5, 4, 3, 2」還算正常,但是為什麼「1」會突然跑到最前面!?
最後,priority 真的可以放其他資料型態嗎?為了更清楚的看到執行結果,我這邊改使用 psysh 來操作:
Psy Shell v0.8.18 (PHP 7.1.18 — cli) by Justin Hileman
Unable to check for updates
>>> $q = new SplPriorityQueue();
=> SplPriorityQueue {#201
heap: [],
}
>>> $q->insert(1, [1, 2, 3]);
=> true
>>> $q->insert(2, []);
=> true
>>> $q->insert(3, new Exception())
=> true
靠北啊,Exception 也可以當作 priority 使用 ….
>>> while ($q->count() > 0) {
... echo $q->extract() . PHP_EOL;
... }
3
1
2
…. 我不想講了。
總之,若你要使用 SplPriorityQueue,請注意 undefined behavior。
Reference:
給定一個 array:
$list = [
'200' => 'OK',
'404' => 'not found',
'500' => 'internal server error',
];
使用 array_keys() 取得 keys 以後,key 的資料型態若可以被轉為 int 則會被自動轉換:
$keys = array_keys($list);
// array(3) {
// [0]=>
// int(200)
// [1]=>
// int(404)
// [2]=>
// int(500)
// }
由文件中可以看到,透過第三個參數「$strict」可以要求保留原始資料型態,但無法避開第二個參數「$search_value」。所以第三個參數基本上是放好看的 (WTF)
如果要處理的資料是比較敏感的,建議在 key 前面加個 prefix,或是取得 keys 以後再手動轉換資料型態。
剛接觸的應該會被命名搞的一頭誤水,畢竟名字相同、不然就是幾乎相同 XD
負責提供記憶體讀寫快取的服務叫做 Memcached,這個服務和 PHP 八竿子打不著關係,就算你不是寫 PHP 也這樣可以使用他。
再來要說的是 PHP 底下的二個函式庫:Memcache 和 Memcached。這二個函式庫,主要是提供一個方法讓 PHP 連接前面提到的 Memcached 讀寫資料。另外要注意的是 Memcache 和 Memcached 函式庫雖然名字很接近,但卻是二個完全不同的函式庫,無法同時使用,只能二選一。
以下透過 psysh 實際操作,來看一下同時使用會發什麼事情。
使用 Memcache 寫入一筆資料:
>>> $m = new Memcache
=> Memcache {#201}
>>> $m->connect('localhost')
=> true
>>> $m->set('test', ['Hello', 'World'])
=> true
>>> $m->get('test')
=> [
"Hello",
"World",
]
再來使用 Memcahed 函式庫,連到 localhost 的 Memcached server 看看會發生什麼事:
>>> $d = new Memcached
=> Memcached {#198}
>>> $d->addServer('localhost', 11211)
=> true
>>> $d->getAllKeys()
=> [
"test",
]
>>> $d->get('test')
=> 0
可以看出這二個函式庫提供的 methods 看起來很接近,但是底層處理資料的方式不一樣,只能挑其中一個來使用。