在PHP中,如何调用字符串中的插值函数?

bfnvny8b  于 2023-03-07  发布在  PHP
关注(0)|答案(7)|浏览(216)

假设我的字符串是:

$str = "abcdefg foo() hijklmopqrst";

如何让PHP调用函数foo()并将返回的字符串插入到该字符串的其余部分?

1u4esq0p

1u4esq0p1#

如果你正在调用某个类的方法,你可以使用普通的变量扩展,例如:

<?php
class thingie {

  public function sayHello() {
    return "hello";
  }

}

$t = new thingie();
echo "thingie says: {$t->sayHello()}";

这将输出:
东西说:你好
注意,调用 * 两边的大括号是必需的。

nzkunb0c

nzkunb0c2#

就用这个:

$str = "abcdefg".foo()."hijklmnopqrstuvwxyz";

它将在字符串创建期间调用函数。

yhived7q

yhived7q3#

function foo()
{
    return 'Hi';
}
$my_foo = 'foo';
echo "{$my_foo()}";
xmq68pz9

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_]

非常小心你允许调用的函数。你至少应该检查$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);
dy1byipe

dy1byipe5#

$foo = foo();
$str = "abcdefg {$foo} hijklmopqrst";
ulydmbyx

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年写了这张纸条)。

限制

注意,即使这样,函数在你定义字符串的时候也会被扩展。我真的猜不出你的需求,但是如果你以后需要扩展函数,而不是在字符串定义的时候,你可能需要采用一些更高级的东西,比如解析器。有很多,特别适合文本模板。但是我猜这超出了这个答案的范围。
您可以随意评论/建议其他方法来扩展字符串 * 内部 * 的函数,或者只是改进您的问题以分享更多关于您需求的上下文。
参考文献:

uoifb46i

uoifb46i7#

它仍然是不可能的,有黑客可用,但不是我会建议,而是建议坚持与老学校点运算符iidoee. $str="abcdefg ". foo() ." hijklmopqrst";
根据复杂( curl )语法文档
注:
函数、方法调用、静态类变量和类常量在{$}中从PHP 5开始就可以使用。但是,访问的值将被解释为定义字符串的作用域中的变量名。使用单个大括号({})将无法访问函数或方法的返回值,或者类常量或静态类变量的值。

相关问题