PHP Conference Japan 2024

变量函数

PHP 支持变量函数的概念。这意味着如果变量名后面附加了圆括号,PHP 将查找与变量计算结果名称相同的函数,并尝试执行它。除其他外,这可以用来实现回调、函数表等等。

变量函数不适用于echoprintunset()isset()empty()includerequire等语言结构。可以使用包装函数将这些结构用作变量函数。

示例 #1 变量函数示例

<?php
function foo() {
echo
"In foo()
\n"
;
}

function
bar($$arg = '')
{
echo
"In bar(); argument was '"$arg'.
\n"
;
}

// 这是 echo 的包装函数
function echoit($$string)
{
echo
$string;
}

$func = 'foo';
$func(); // 这调用了 foo()

$func = 'bar';
$func('test'); // 这调用了 bar()

$func = 'echoit';
$func('test'); // 这调用了 echoit()
?>

对象方法也可以使用变量函数语法调用。

示例 #2 变量方法示例

<?php
class Foo
{
function
Variable()
{
$name = 'Bar';
$this->$name(); // 这调用了 Bar() 方法
}

function
Bar()
{
echo
"This is Bar";
}
}

$foo = new Foo();
$funcname = "Variable";
$foo->$funcname(); // 这调用了 $foo->Variable()

?>

调用静态方法时,函数调用优先于静态属性运算符。

示例 #3 带静态属性的变量方法示例

<?php
class Foo
{
static
$variable = 'static property';
static function
Variable()
{
echo
'Method Variable called';
}
}

echo
Foo::$variable; // 这打印 'static property'。它不需要在这个作用域中使用 $variable。
$variable = "Variable";
Foo::$variable(); // 这调用了 $foo->Variable(),读取此作用域中的 $variable。

?>

示例 #4 复杂的回调

<?php
class Foo
{
static function
bar()
{
echo
"bar\n";
}
function
baz()
{
echo
"baz\n";
}
}

$func = array("Foo", "bar");
$func(); // 打印 "bar"
$func = array(new Foo, "baz");
$func(); // 打印 "baz"
$func = "Foo::bar";
$func(); // 打印 "bar"
?>

添加注释

用户贡献的注释 3 条注释

niemans at pbsolo dot nl
5年前
虽然文档建议常量的使用类似于变量的使用,但在变量函数方面存在例外。您不能使用常量作为函数名来调用变量函数。

const DEBUGME ='func';
function func($s) { echo $s. "\n"; }

DEBUGME('abc'); // 导致语法错误

$call = DEBUGME;
$call('abc'); // 可行

但是您可以将常量用作函数的参数。当您需要调用变量常量函数时,这是一个简单的解决方法

function dynamic($what, $with)
{
$what($with);
}
dynamic(DEBUGME, 'abc');

我认为这对于隐藏 API 和/或较长(复杂)的静态调用很有意义。
享受!
rnealxp at yahoo dot com
4年前
<?php
/*
您可能因为像我一样想要像在 JavaScript 中那样将函数作为对象传递给客户端对象而访问了这个 php 变量函数页面。我遇到的问题是,虽然我可以像这样使用变量调用函数“ $v(); ”……但我不能像这样调用“ $obj->p() ”,其中
'p' 是包含要调用的方法名称的属性。不想在调用之前将我的属性保存到变量中: " $v = $obj->p; $v(); ";即使找到了一种方法,以下内容仍然适用……

我将此扩展工作归功于这个人:tatarynowicz at gmail dot com;
没有他们,我将无法做到这一点。
*/
interface iface_dynamic_members{
//使用此接口可以为实现它的对象启用类型提示。
public function __call($name, $args);
public function
__set($name, $value);
public function
quietly_fail():bool;
}
trait
trait_has_dynamic_members{
//以 trait 的形式实现这些魔术方法,释放客户端对象
//以便它仍然可以从父类继承。
public function __call($name, $args) {
if (
is_callable($this->$name)) {
return
call_user_func($this->$name, $args);
}
else {
//您的动态成员对象可以声明自己是否愿意忽略不存在的方法调用。
if($this->quietly_fail()===true){
echo
'方法不存在,但我并不介意。';
}else{
echo
'方法不存在,我认为这是一个错误。';
}
}
}
public function
__set($name, $value) {
$this->$name = is_callable($value) ? $value->bindTo($this, $this): $value; //使用三元运算符赋值。
}
}
abstract class
MBR_ATTR{
//一个充满属性的类,对象可以采用;抽象的,因为不能被实例化(如果我也可以将其设置为“final”,我就会这样做)。
public static function is_a_walker(iface_dynamic_members $obj, ?string $walker_type='normal pace'){
$obj->walker_type = $walker_type;
$obj->walker_walk = function() {
return
"我正在以 {$this->walker_type} 的速度行走。";
};
}
public static function
is_a_runner(iface_dynamic_members $obj, string $runner_type){
$obj->runner_type = $runner_type;
$obj->runner_run = function() {
return
"我正在以 {$this->runner_type} 的速度奔跑。";
};
self::is_a_walker($obj); //如果能跑,也能走。
}
}
class
cls_partly_dynamic implements iface_dynamic_members{
use
trait_has_dynamic_members;
public function
quietly_fail():bool{
return
true;
}
}
// 报告所有错误,但 E_NOTICE 除外
error_reporting(E_ALL & ~E_NOTICE); //启用所有错误报告,但通知除外。
//----
//配置 runner 对象……
$obj_runner = new cls_partly_dynamic();
MBR_ATTR::is_a_runner($obj_runner, 'fast');
$obj_runner->runner_type = '有点慢';
//----
//配置 walker 对象……
$obj_walker = new cls_partly_dynamic();
MBR_ATTR::is_a_walker($obj_walker, 'slow');
$obj_walker->walker_type = '超快';
//----
//执行操作……
echo '步行者行动中…… '. '<br>';
echo
$obj_walker->walker_walk() . '<br>';
echo
'<br>';
echo
'跑步者行动中…… '. '<br>';
echo
$obj_runner->walker_walk() . '<br>';
echo
$obj_runner->runner_run() . '<br>';
echo
$obj_runner->xxx() . '<br>'; //尝试调用不存在的方法。
//我同意上述方法/技术并不总是理想的,特别是由于您选择的 IDE 中缺少代码补全;我倾向于在响应用户通过 UI 指示处理步骤时,使用这种方法进行动态编程。
?>
匿名用户
13年前
$ wget https://php.net/get/php_manual_en.tar.gz/from/a/mirror
$ grep -l "\$\.\.\." php-chunked-xhtml/function.*.html

接受可变参数的函数列表。
<?php
array_diff_assoc
()
array_diff_key()
array_diff_uassoc()
array()
array_intersect_ukey()
array_map()
array_merge()
array_merge_recursive()
array_multisort()
array_push()
array_replace()
array_replace_recursive()
array_unshift()
call_user_func()
call_user_method()
compact()
dba_open()
dba_popen()
echo()
forward_static_call()
fprintf()
fscanf()
httprequestpool_construct()
ibase_execute()
ibase_set_event_handler()
ibase_wait_event()
isset()
list()
maxdb_stmt_bind_param()
maxdb_stmt_bind_result()
mb_convert_variables()
newt_checkbox_tree_add_item()
newt_grid_h_close_stacked()
newt_grid_h_stacked()
newt_grid_v_close_stacked()
newt_grid_v_stacked()
newt_win_choice()
newt_win_entries()
newt_win_menu()
newt_win_message()
newt_win_ternary()
pack()
printf()
register_shutdown_function()
register_tick_function()
session_register()
setlocale()
sprintf()
sscanf()
unset()
var_dump()
w32api_deftype()
w32api_init_dtype()
w32api_invoke_function()
wddx_add_vars()
wddx_serialize_vars()
?>
To Top