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

问题描述 投票:0回答:8

假设我的字符串是:

$str = "abcdefg foo() hijklmopqrst";

如何让 PHP 调用函数

foo()
并将返回的字符串插入到该字符串的其余部分?

php
8个回答
32
投票

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

<?php
class thingie {

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

}

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

这将输出:

thingie 说:你好

请注意,调用周围的大括号是必需的。


24
投票
就用这个:

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

它将在字符串创建过程中调用函数。


21
投票
function foo() { return 'Hi'; } $my_foo = 'foo'; echo "{$my_foo()}";
    

9
投票
$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);
    

9
投票
$foo = foo(); $str = "abcdefg {$foo} hijklmopqrst";
    

7
投票
简短回答

不。没有原生结构可以完全做到这一点。

简单的串联可能会更好。也许更丑陋,但对于 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字符串,或者只是改进您的问题以分享有关您需求的更多背景信息。

参考资料:

  • https://secure.php.net/manual/en/functions.variable-functions.php
  • https://secure.php.net/manual/it/language.types.string.php#language.types.string.parsing

5
投票
这仍然是不可能的,有一些可用的技巧,但不是我推荐的,而是建议坚持使用老式的点运算符,即

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



根据

复杂(卷曲)语法文档

注:

自 PHP 5 起,{$} 中的函数、方法调用、静态类变量和类常量都可以工作。但是,访问的值将被解释为定义字符串的范围内的变量名称。使用单花括号 ({}) 无法访问函数或方法的返回值或者类常量或静态类变量的值。


0
投票
<? 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
    
© www.soinside.com 2019 - 2024. All rights reserved.