假设我的字符串是:
$str = "abcdefg foo() hijklmopqrst";
如何让 PHP 调用函数
foo()
并将返回的字符串插入到该字符串的其余部分?
如果您正在调用某个类的方法,则可以使用普通的变量扩展。例如:
<?php
class thingie {
public function sayHello() {
return "hello";
}
}
$t = new thingie();
echo "thingie says: {$t->sayHello()}";
这将输出:
thingie 说:你好
请注意,调用周围的大括号是必需的。
$str = "abcdefg".foo()."hijklmnopqrstuvwxyz";
它将在字符串创建过程中调用函数。
function foo()
{
return 'Hi';
}
$my_foo = 'foo';
echo "{$my_foo()}";
$str="abcdefg foo() hijklmopqrst";
function foo() {return "bar";}
$replaced = preg_replace_callback("~([a-z]+)\(\)~",
function ($m){
return $m[1]();
}, $str);
输出:
$replaced == 'abcdefg bar hijklmopqrst';
这将允许任何小写字母作为函数名称。如果您需要任何其他符号,请将它们添加到图案中,即
[a-zA-Z_]
。要
非常小心您允许调用哪些函数。您至少应该检查 $m[1] 是否包含白名单函数,以不允许远程代码注入攻击。
$allowedFunctions = array("foo", "bar" /*, ...*/);
$replaced = preg_replace_callback("~([a-z]+)\(\)~",
function ($m) use ($allowedFunctions) {
if (!in_array($m[1], $allowedFunctions))
return $m[0]; // Don't replace and maybe add some errors.
return $m[1]();
}, $str);
在
"abcdefg foo() bat() hijklmopqrst"
上测试运行输出
"abcdefg bar bat() hijklmopqrst"
。白名单方法的优化(从允许的函数名称动态构建模式,即
(foo|bar)
。
$allowedFunctions = array("foo", "bar");
$replaced = preg_replace_callback("~(".implode("|",$allowedFunctions).")\(\)~",
function ($m) {
return $m[1]();
}, $str);
$foo = foo();
$str = "abcdefg {$foo} hijklmopqrst";
简单的串联可能会更好。也许更丑陋,但对于 PHP 解析器来说更有效。
长答案
如果您确实需要从双引号字符串计算任意表达式,您可以实现此解决方法,推测一个名为
variable-functions: 的功能
<?php
/**
* The hack
*
* @param $v mixed Value
* return mixed Value (untouched)
*/
$GLOBALS['_'] = function ( $v ) {
return $v;
};
// Happy hacking
echo "Today is {$_( date( 'Y-m-d' ) )} and the max function returns {$_( max( 1, 2, 3 ) )}...{$_( str_repeat( ' arrh', 3 ) )}!";
结果:
Today is 2018-02-07 and the max function returns 3... arrh arrh arrh!
示例不限于 date()
、
max()
和
str_repeat()
:您当然可以定义自己的函数,如
foo()
并调用它们,只要它们返回有效的字符串即可。简而言之,这个示例创建了一个简单的变量。它的名称很短:只有一个下划线。所以,这个变量实际上被称为
$_
。这个变量,老实说,它是一个函数,老实说,它只是返回你在第一个参数中表达的内容。这对您来说是语法糖,因为函数不容易在字符串内按原样扩展。相反,变量很容易扩展。就是这样。我想知道 PHP 是否会引入原生功能来做到这一点(注:我在 2018 年写了这篇文章)。
限制
请随意发表评论/建议其他方法来扩展函数
inside字符串,或者只是改进您的问题以分享有关您需求的更多背景信息。
参考资料:
<?
function foo($b)
{
return "Hi $b";
}
$bar = 'bario';
$my_foo = 'foo';
echo "<br>1 {$my_foo($bar)}";
$myfoo = foo; // my 'version'
echo "<br>2 {$myfoo($bar)}";
// the following is nogo; php error! $myfoo can not be called as function because it got the return value if foo() which is a string.
// means https://stackoverflow.com/users/517676/savinger answer above is wrong; this program doesn't print "<br>end":
$myfoo = foo();
echo "<br>3 {$myfoo($bar)}";
echo "<br>end";
?>
输出为:
1 Hi bario
2 Hi bario