2009年8月22日 星期六

PHP 的__XXX

PHP有些是前面帶有兩個底線 '__'所組成的預設函式或變數
因為我比較不喜歡季這些有特別涵義的東西,簡單做個筆記把他記下來


__construct


這是個供類別使用的函式,就如同字面上意義,他可以代表類別建構式
一般沒寫這個函式的時候,PHP會去尋找同名的functoin當建構式
儘管大小寫不同,舉個例子

class People{

function people(){
echo 'people';
}
}
$p=new People();

//output:
people

但是如果有寫__construct的話,則會優先使用__construct,而原先同名的function則可以當member function使用

class People{
function __construct(){
echo 'construct';
}
function people(){
echo 'people';
}
}
$p=new People();// call __construct()
$p->people();//call member function people()

//output:
construct
people


__destruct


物件解構式,物件銷毀時要做的事情

class People{
function __destruct(){
//TODO
}
}


__get,__set


PHP的setter跟getter function,當object使用->去取值或用->=去設值的時候會呼叫的函式
儘管那個member從未定義一樣會去呼叫,__get須要一個參數,而__set則須要兩個參數
假設我用$p->Data,就像呼叫$p->__get("Data");
而如果我使用$p->Data="Tom"; 就像呼叫$p->__set("Data","Tom");

class People{
function __get($name){
echo "get function para: $name";
}

function __set($name,$value)
{
echo "set function para: name=$name,value=$value";
}
}

$p=new People();
$p->iget;//呼叫 __get($name) 並將iget當參數傳入
$p->iset=100;//呼叫 __set($name,$value) 並將iset跟100當參數傳入

//output:
get function para: iget
set function para: name=iset,value=100

這樣的好處是能夠把一些變數資訊隱藏起來
User不須要知道我變數是如何操作,昨天在透視 WebMVC看到的一個蠻妙的作法,跟關連陣列結合使用

class People{
var $arr=array();//一個空陣列
function __get($name){
echo "get function para: $name ";
return (isset($this->arr[$name]))?$this->arr[$name]:" no \$arr[$name]";
}

function __set($name,$value)
{
echo "set function para: name=$name,value=$value ";
$this->arr[$name]=$value;
}
}
$p=new People();
echo "get:".$p->iget;
$p->iset=100;
echo "get:".$p->iset;

//output
get function para: iget
get: no $arr[iget]
set function para: name=iset,value=100
get function para: iset
get:100


__toString


這個函式可以讓物件配合echo像一般變數一樣輸出,他必須有個return值

class People{
function __toString(){
return "I am a people";
}
}
$p=new People();
echo $p;

//output
I am a people

__call


作overloading時可以用到,雖然一般都選擇預設參數的方式,這個我就不常用了
__call會傳進兩個參數,一個function name一個參數陣列
我使用$p->fun(1,2,3)就好像在呼叫$p->__call("fun",array(1,2,3))
他的好處,是function名稱不再受到綁定,參數也可以隨意
而fun必須是一個class未定意的function,如果有定義會採用以定義的
下面舉兩個例子,使用預設參數跟使用__call

class People{
function operation($a="abc",$b=123){
echo "default:"."$a : $b";
}
function __call($name,$args)
{
echo "call function $name args:";
if(isset($args))
foreach ($args as $arg)
{
echo "$arg ,";
}
}
}

$p=new People();
//default
$p->operation();
$p->operation(99);
$p->operation(99,234);
//__call
$p->call();
$p->call(1);
$p->call(1,"Tom");
$p->bye(1,2,3,4);

//output
default:abc : 123
default:99 : 123
default:99 : 234
call function call args:
call function call args:1 ,
call function call args:1 ,Tom ,
call function bye args:1 ,2 ,3 ,4 ,


其他一些__clone、__iset、__unset也大概都差不多用法,不過使用機率不大就是了,有興趣在去查手冊

__autoload


上面的__XXX都必須在class裡面,而這個__autoload則是個獨立function,當呼叫一個不存在的class的時候
他會就會呼叫__autoload去試圖將他載入,他會傳入一個參數,也就是呼叫的class name
當我用$p=new People();,假設People不存在現有類別,他就會去呼叫__autoload("People");
假設我把上面範例拆開

//strFunctionClass.php
class People{
}


//strFunction.php

function __autoload($class){
if($class=="People")
{
include_once 'strFunctionClass.php';
}
echo "call Class :$class";
}
$p=new People();

//output
call Class :People

也有人會把一個class一個php檔並設成同樣的名稱,這樣就可以把load動作簡化,這個在客制Lib的時候很好用


//People.php
class People{...}

//index.php
function __autoload($class){
include_once "$class.php";
}
$p=new People();


其他還有一些是__開頭的變數

echo nl2br("\n").__METHOD__;/*Class的方法名稱*/
echo nl2br("\n").__FILE__;/*檔案所在絕對位置*/
echo nl2br("\n").__CLASS__;/*Class 名稱 在Class內才有用*/
echo nl2br("\n").__FUNCTION__;/*Function 名稱 在function內才有用*/
echo nl2br("\n").__LINE__;/*程式碼所在行數*/

我比較常用到的只有__FILE__,可以取得程式檔案的絕對位置
像是c:\appser\www\xxx.php,可以配合dirname取得檔案目前目錄
像是dirname(__FILE__)可以得到c:\appser\www\

-------------------------------------
題外話,在看透視 WebMVC(這篇文章很推薦)的時候,看到了一個很有趣的用法
就是把變數字串弄成函式或是另一個變數

function fun(){}

$temp=9999;
$var="temp";
echo $$var;//output 9999 就像 echo $temp

$temp="fun";
$temp();//最後會變成fun();

而這個應用也可以用在class上

class Action{
var $_action;
function setAction($action)
{
$this->_action=$action;
}
function run(){
if(method_exists($this,$this->_action))//確定是否是class method
$this->{$this->_action}();//用大括弧刮起來
else
echo "not member function:".$this->_action;
}
function sayHello(){
echo "Hello";
}
function sayHi(){
echo "Hi";
}
}

$act=new Action();
$act->setAction("sayHello");
$act->run();
$act->setAction("sayHi");
$act->run();
$act->setAction("say");
$act->run();
//output
Hello
Hi
not member function:say

沒有留言: