假设我的字符串是:
$str = "abcdefg foo() hijklmopqrst";
如何让PHP调用函数foo()并将返回的字符串插入到该字符串的其余部分?
foo()
1u4esq0p1#
如果你正在调用某个类的方法,你可以使用普通的变量扩展,例如:
<?php class thingie { public function sayHello() { return "hello"; } } $t = new thingie(); echo "thingie says: {$t->sayHello()}";
这将输出:东西说:你好注意,调用 * 两边的大括号是必需的。
nzkunb0c2#
就用这个:
$str = "abcdefg".foo()."hijklmnopqrstuvwxyz";
它将在字符串创建期间调用函数。
yhived7q3#
function foo() { return 'Hi'; } $my_foo = 'foo'; echo "{$my_foo()}";
xmq68pz94#
$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_]。
[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)。
"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);
dy1byipe5#
$foo = foo(); $str = "abcdefg {$foo} hijklmopqrst";
ulydmbyx6#
不。没有本地构造可以完全做到这一点。一个简单的连接可能更好,可能更难看,但对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年写了这张纸条)。
date()
max()
str_repeat()
$_
注意,即使这样,函数在你定义字符串的时候也会被扩展。我真的猜不出你的需求,但是如果你以后需要扩展函数,而不是在字符串定义的时候,你可能需要采用一些更高级的东西,比如解析器。有很多,特别适合文本模板。但是我猜这超出了这个答案的范围。您可以随意评论/建议其他方法来扩展字符串 * 内部 * 的函数,或者只是改进您的问题以分享更多关于您需求的上下文。参考文献:
uoifb46i7#
它仍然是不可能的,有黑客可用,但不是我会建议,而是建议坚持与老学校点运算符iidoee. $str="abcdefg ". foo() ." hijklmopqrst";根据复杂( curl )语法文档注:函数、方法调用、静态类变量和类常量在{$}中从PHP 5开始就可以使用。但是,访问的值将被解释为定义字符串的作用域中的变量名。使用单个大括号({})将无法访问函数或方法的返回值,或者类常量或静态类变量的值。
$str="abcdefg ". foo() ." hijklmopqrst";
7条答案
按热度按时间1u4esq0p1#
如果你正在调用某个类的方法,你可以使用普通的变量扩展,例如:
这将输出:
东西说:你好
注意,调用 * 两边的大括号是必需的。
nzkunb0c2#
就用这个:
它将在字符串创建期间调用函数。
yhived7q3#
xmq68pz94#
输出:
这将允许任何小写字母作为函数名。如果您需要任何其他符号,请将它们添加到模式中,例如
[a-zA-Z_]
。非常小心你允许调用的函数。你至少应该检查$m[1]是否包含一个白名单函数以防止远程代码注入攻击。
在
"abcdefg foo() bat() hijklmopqrst"
输出"abcdefg bar bat() hijklmopqrst"
上进行测试。优化白名单方法(根据允许的函数名动态构建模式,例如
(foo|bar)
。dy1byipe5#
ulydmbyx6#
简短回答
不。没有本地构造可以完全做到这一点。
一个简单的连接可能更好,可能更难看,但对PHP解析器来说更有效。
长答案
好吧。是的。
如果你真的需要从一个双引号字符串中得到任意的表达式,你可以实现这个解决方案,推测一个叫做 * variable-functions * 的特性:
结果:
示例不限于
date()
、max()
和str_repeat()
:你当然可以定义你自己的函数,比如foo()
,并且只要它们返回一个有效的字符串就可以调用它们。简而言之,这个例子创建了一个简单的变量,它的名字很短:只是一个下划线,所以这个变量实际上叫做
$_
,这个变量,老实说,它是一个函数,老实说,它只返回你在第一个参数中表达的内容,这对你来说是语法糖,因为函数不容易在字符串中展开,相反,变量很容易展开,就是这样。我想知道PHP是否会引入一个原生特性来实现这一点(注意:我在2018年写了这张纸条)。
限制
注意,即使这样,函数在你定义字符串的时候也会被扩展。我真的猜不出你的需求,但是如果你以后需要扩展函数,而不是在字符串定义的时候,你可能需要采用一些更高级的东西,比如解析器。有很多,特别适合文本模板。但是我猜这超出了这个答案的范围。
您可以随意评论/建议其他方法来扩展字符串 * 内部 * 的函数,或者只是改进您的问题以分享更多关于您需求的上下文。
参考文献:
uoifb46i7#
它仍然是不可能的,有黑客可用,但不是我会建议,而是建议坚持与老学校点运算符iidoee.
$str="abcdefg ". foo() ." hijklmopqrst";
根据复杂( curl )语法文档
注:
函数、方法调用、静态类变量和类常量在{$}中从PHP 5开始就可以使用。但是,访问的值将被解释为定义字符串的作用域中的变量名。使用单个大括号({})将无法访问函数或方法的返回值,或者类常量或静态类变量的值。