2009年12月30日 星期三

php 物件的static method最好要以static keyword清楚標示

因為一時心血來潮  想知道呼叫php物件的 static method 跟 non-static method 在效率上有沒有差別
就寫了簡單的程式測試一下  一開始我的物件的method只有一個 並沒有以 static 關鍵字宣告:
class T
{
    public f()
    {
    }
}

而只是以兩種不同的方式呼叫:
1.
$o = new T();
$o->f();

2.
T::f();

結果以第二種方式 花的時間大概是 第一種方式的兩倍 讓我非常驚訝
後來我在php官網發現了造成效率差距這麼巨大的原因
Calling non-static methods statically generates an E_STRICT level warning.

即使在 php.ini 中的 error_reporting 設為 E_ALL 用第二種方式呼叫 method也不會出現 warning
因為 E_ALL 是不包含 E_STRICT 的  所以我便以為這樣寫的 code 是合法的 真是大錯特錯

我後來把 class 改寫:
class T
{
    public function f()
    {
    }

    public static function sf()
    {
    }
}

再以 T::sf() 呼叫 static method
結果是呼叫 static method 或是 non-static method 時間都差不多 感覺這樣才是合理的狀態

然後 我把 error_reporting 改成 E_ALL | E_STRICT 了
寫 code 還是要嚴謹一點才好

2009年9月12日 星期六

windows的handle

這裡有說明了 windows 系統中的 handle 代表的意義
windows kernel 幫每個 process  維護一份 handle table
table 中的 entry 指向該 handle 所代表的 object
因為是每個 process 一份 handle table 所以一個 handle value 只對使用該 handle 的 process 有意義

2009年8月15日 星期六

PHP的物件

最近練習用PHP寫聊天室來當做練習  參考網路上的文章用MVC與物件來寫程式 這是第一次用物件寫程式
之前一直很想知道程序導向與物件導向的優異在哪  但是我程式寫的不夠多  即使查了很多資料但始終無法體會
這次用物件來寫程式 對於物件的優點還是沒有什麼體會 不過倒是學到了許多以前不知道的知識
以下做一些筆記:


magic method
PHP物件有許多 magic method 可以用 例如 __call method
例如 假設有個情況是我要把client傳來的字串直接當作method name去呼叫某物件的method
但是 client 輸入的資料是一定要檢查的 我可以用 method_exists 去檢查此 method 存不存在
但是如果用 __call 的話 直接將呼叫不存在的method時該做的動作寫在 __call 裡就可以了

此外 __get __set 也是很好用的 method
看到這兩個 method 我才知道 PHP 物件也可以像 javascript 一樣動態創建屬性
不過我一直很想知道 如果物件沒有覆寫這兩個method的話 動態創建屬性時的行為會是怎樣
PHP官網似乎沒有提到這個 自己實驗的結果 只知道物件會自動創造一個 public 屬性
這樣當然很方便 但是依賴這種寫法 感覺以後維護或是 debug 會很有問題
(因為動態創建的屬性與 class 中 define 的屬性的存取都是一樣寫法 會分不清楚)
在網路上也看到其他人自訂 setvar getvar 之類的method來動態存取屬性


XML的處理
我的資料有些是使用 xml 檔案來儲存 PHP 可以用 simplexml 系列的函式去處理 xml 檔案
一開始其實我是想用 DOMDocument 來處理的 因為這個物件對 xml 的存取與處理很完善
但是在試用的時候發現找不到 DOMDocument 物件 雖然官網說這個物件是 PHP5 core 的一部份(我server是PHP5)
查了資料才發現 這是 linux distribution dependent 的 有些 linux 版本PHP5就是沒有 DOMDocument
必須要多裝 php-xml 才行
所以我只好什麼事情都用 simplexml 來做 這個物件真的是夠 simple 連 removeChild 這種 method 都沒有
後來我發現可以用 unset 來直接刪掉節點 上網搜尋的結果也是通通都用 unset 去刪掉節點
因為 xml 是普通文字檔案 需要做同步的機制 我又用了 semaphore 去做存取控制
雖然有 flock 可以鎖住檔案 但是官網有人回報有問題 所以不太敢用


物件的使用
對於 PHP 物件的使用熟悉了一點 像是 $this 變數 static 關鍵字 還有 :: 運算子的用途都稍有瞭解
還發現 PHP5 支援 type hinting 這個機制
可以在 function prototype 指定接收參數是哪種物件或是陣列 例如:

function foo_arr(array $arr) {};

function foo_obj(some_class $obj) {};

則之後呼叫到這樣定義的函式時 只能傳物件(而且必須是 "some_class" 的物件) 或是陣列過去
這個機制感覺蠻好玩的 不過現在只支援物件與陣列

2009年8月7日 星期五

apache mod rewrite

要使用 apache 的 mod rewrite 功能 在設定檔中必須要設定 Options FollowSymLinks
apache官方文件中就有描述
如果不是網站管理員的話  只要在http.conf有設定AllowOverride All
則可以將 Options FollowSymLinks 放到網頁資料夾底下的.htaccess檔案中
這樣也可以使用 mod rewrite 的功能

此外 修改.htaccess的設定後 不需要重新啟動apache即可立即生效
因為apache會在每次http request發生時去掃瞄資料夾下的.htaccess檔案
這提供了相當方便的功能 (修改完立即見效)
但也犧牲了一些效能 (每次都要掃瞄.htaccess檔案)

2009年8月6日 星期四

linux linker and dynamic linker

在linux下面的linker是ld
這是在編譯時 將各個object file連結成一個executable的程式

而linux下面的dynamic linker是ld.so/ld-linux.so
這是在一個程式要執行時 將程式與它所用到的dynamic share libraries連結起來並載入記憶體的程式
ld.so是用來處理a.out格式的二進位檔 ld-linux.so是用來處理ELF格式的二進位檔

從檔名可以看出來 dynamic linker是以share object的形式存在
當一個executable要開始執行時 dynamic linker 連結完executable與它用到的dynamic share libraries後 還會被map到該executable的address space中
因為ELF程式的PLT GOT機制 在程式執行中 還必須要用到dynamic linker

在Windows中的dynamic linker與linux不同 是以kernel的一部分存在
這樣做的好處是速度會快一點(不需要每個程式執行時都要將dynamic linker map到process address space中) 但是會缺少一點彈性

2009年7月24日 星期五

PHP裡的 & 運算子

在PHP中 下面這段寫法並不會出現警告訊息
< ?php
$a=&$b;
? >

這也許會讓人覺得 $b 變數未宣告即使用 應該會出現警告才對
但是在PHP官網裡的 What References Do有這一段說明:
Note: If you assign, pass, or return an undefined variable by reference, it will get created.

所以 當 &$b 出現時 $b 就會被創造 並且設為NULL 然後將 $a 設為 $b的 alias
因此上面的寫法在PHP裡 其實是合法的

不過PHP裡還有我較有疑問的地方是 只要一個變數設為NULL 則使用不存在的index也不會有事 例如:
< ?php
$a=NULL;
$b=$a['aaa']['bbb'];
? >
以上的寫法 在PHP中是不會出現警告訊息的 這是蠻讓人奇怪的一點

2009年7月23日 星期四

當網頁裡event發生時 阻擋default action的執行

在網頁裡 一個event發生時 通常會有default action
例如在一個text element中打字 則會發生 onkeydown onkeypress onkeyup這三個事件
default action就是在輸入框裡顯示打入的字串

想要阻止瀏覽器的default action執行時 如果是用inline的方式註冊event handler 直接return false就可以了
例如 < input type="text" onkeypress="return false;" >

但如果使用addEventListener註冊 event handler 就需採用別的方法 而且IE和firefox必須用不同的方法
例如:
< input type="text" id="text_element" >

< script type="text/javascript" >
function foo(e)
{
if (e.preventDefault)
e.preventDefault(); //firefox
else
e.returnValue=false; //IE
}
document.getElementById('text_element').addEventListener('keypress', foo, false);
< /script >

W3C的標準是用event object的preventDefault method去阻擋掉default action的發生
但是IE並沒有實作這個method 不過IE的event object有returnValue這個property
將這個屬性設為false一樣可以阻擋掉default action的發生
因此可以用上面的寫法去支援IE與firefox