在程式設計中,特別是在框架 (Framework) 的設計中,因為框架的設計者預先並不知道框架的使用者 (Programmer) 在程序撰寫時所命名的 Function 名稱,框架的設計者可以用動態Function 的調用方式解決這個問題。簡單的說,function 的名稱是一個變數。
在本文中我們將會討論三種不同的動態調用的方式:
- 直接調用變數名稱,變數的值是一個 Function 名稱
- 使用 built-in Function call_user_func()
- 用 built-in Function eval()
Variable Function
在 MVC 模式中的 Model 中,假設是跟 Database 交互的,其中有 add/delete/update/query function,在實際調用時,因為不知道當前使用者(End-user) 要做的動作,這時就可以利用變量 Function 的方式來處理這樣的情景。當然也可以用 switch 的方式來處理。
Class User{
function __constuct()
{
// some code here
}
public function add()
{
// some code here
}// end add()
public function update()
{
// some code here
}// end update()
public function delete()
{
// some code here
}// end delete()
public function query()
{
// some code here
}// end query()
}// end class User
以下採用 switch 和動態 Function 調用代碼有何不同?
include_once('User.php');
$user = new User();
$action = isset($_GET['action']) && !empty($_GET['action']) ?
$_GET['action'] :
'query';
switch ($action)
{
case 'save':
$user->save();
break;
case 'update':
$user->update();
break;
case 'delete':
$user->delete();
break;
case 'query':
$user->query();
break;
default:break;
}
Dynamic Function Call
include_once('User.php');
$user = new User();
$action = isset($_GET['action']) && !empty($_GET['action']) ?
$_GET['action'] :
'query';
$user->$action();
可以看出使用動態 Function 調用非常簡潔。
call_user_func()
//Call a user defined function given by the function parameter.
// Take the following:
function hello($name)
{
echo 'Hello '.$name;
}
call_user_func('hello', 'dennis'); //output 'Hello dennis'
// Object methods may also be invoked statically using this function // by passing array($objectname, $methodname)
// to the function parameter.
class Hello {
function say_hello()
{
echo 'Hello!\n';
}
}
$classname = 'Hello';
call_user_func(array($classname, 'say_hello'));
// 多個 Parameter 時
class Hello{
function talk($who,$p)
{
echo $who .' talk with '.$p;
}// end talk()
}// end Hello()
$User = new Hello();
$func = 'talk';
call_user_func(array($User,$func),'dennis','allan');
eval()
eval 是把 string 轉變成 PHP 代碼來執行。這裡提到 eval 只是實現了動態調用的功能。使用 eval 會大大降低程式的執行效能,在實際產品環境中,盡量少用或不用 eval。
include_once 'User.php';
$User = new User();
$action = isset($_GET['action']) && !empty($_GET['action']) ?
$_GET['action'] :
'query';
eval("\$User->".$action."();");