PHP8.2中字符串变量解析的新用法

2022-05-25 奥古斯宏

PHP允许在双引号的字符串中嵌入变量,之前支持这几种方式:

  1. 直接嵌入变量("$var"
  2. 变量外使用大括号包含("{$var}"
  3. $后使用大括号包含("${var}"
  4. 可变变量("${expr}"),可变变量参考

第1种和第2中用法各有利弊。但是由于语法重叠,第3种用法和第4种很容易混淆。第3种用法不像前两种那样严格,并且会和第4中用法产生混淆,(可参考可变变量文档),在字符串变量解析中很少使用。

在PHP8.2中将弃用第3和4的用法,并且在PHP9中将他们删除。

var_dump("${foo}"); 
// 不推荐使用:不推荐在字符串中使用 ${} 
 
var_dump("${(foo)}"); 
// 不推荐使用:不推荐在字符串中使用 ${}(可变变量) 

这样只剩下了前两个用法,第一种直接简单,第二种强大,支持各种类型的用法(数组写法等)

现状版本

在现在版本中,前三种用法的目的是一样的,都是将简单的变量嵌入到字符串中。只是他们用起来不太一样。

简单地拼接变量

前三种用法都支持基本的变量拼接。

$foo  =  'foo' ; 
 
var_dump("$foo"); 
var_dump("{$foo}"); 
var_dump("${foo}"); 

拼接指定数组索引

前三种用法也支持拼接指定数组索引,但是语法并不一致。

版权声明:本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

$foo = ['bar' => 'bar'];
 
var_dump("$foo[bar]");
var_dump("{$foo['bar']}");
var_dump("${foo['bar']}");

这里要注意,第2和3用法支持任何索引名,但是在第1中用法中,索引并不能包含空格和其他特殊符号,只能是简单地字符串(比如$foo[a b] )。

拼接对象属性

前两种方法支持访问对象属性。

$foo = (object) ['bar' => 'bar'];
 
var_dump("$foo->bar");
var_dump("{$foo->bar}");

拼接对象方法

只有第二种方法支持访问对象方法。

class Foo {
    public function bar() {
        return 'bar';
    }
}
 
$foo = new Foo();
var_dump("{$foo->bar()}");

复合调用拼接

只有第二种方法支持复杂的调用方式。

class Bar {
    public function baz() {
        return 'baz';
    }
}
 
$foo = ['bar' => new Bar()];
var_dump("{$foo['bar']->baz()}");

第4种用法

PHP有一个特性叫可变变量,它允许按照名称获取变量,而这个名称可以存储在一个变量中。

$foo = 'Hello world!';
$bar = 'foo';
var_dump(${$bar});

即便是在字符串变量解析中,也是如此:

版权声明:本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

$foo = 'world!';
$bar = 'foo';
var_dump("Hello ${$bar}");

你会发现,这个语法跟第3中冲突了。如果大括号中间的语法与用法3不一致,则PHP会按照完全不同的语义执行变量解析。

const foo = 'bar';
$foo = 'foo';
$bar = 'bar';
 
var_dump("${foo}");
//> foo
 
var_dump("${(foo)}");
//> bar

大括号从用法3 切换到用法 4,因为用法 3 中不允许使用括号。这意味着 foo 不再被解释为变量而是常量,然后用法 4 将尝试通过该常量的名称查找局部变量。  这是非常绕。  虽然这种表现可能会很有用(作者想象不到会有什么用),但值得注意的是,它们使用语法2会也一样能用,语法也更直观。

结论

用法1简单易用,非常常见。

用法2很强大,也非常常见。

用法3只是只实现了前两种用法的部分功能,并且用的并不多。

用法4的功能很少,并且很容易与选项3混淆。

版权声明:本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

综上所述,PHP8.2将弃用这两种用法,并且在PHP9中删除这两种用法。

影响

对前 1000 个 packagegist 存储库的分析得出了选项 3 的 267 次使用,选项 4 的 0 次使用。 

如何迁移代码

从用法3迁移到用法2是很简单的,只需要简单的移动$符号。

"${foo}" => "{$foo}"
"${foo[expr]}" => "{$foo[expr]}"

从用法4迁移到用法2也很简单,只需要在差值两侧加上大括号。

"${foo->bar}" => "{${foo->bar}}"

唯一的麻烦在于如何正确区分这段代码是想要使用用法3还是用法4,(这次修改就是为了解决这个问题)。但是在统计中发现,用法4应该不存在。

不变的用法

  • 字符串之外的可变变量$foo = ${'bar'};
  • 用法1的可变变量 echo “$$foo”;

和其他语言的比较

其他很多语言都有用法3的语法,尤其是Bash和JavaScript的模板解析中。但是他们的行为和PHP完全不同。在PHP中该语法意味着可变变量。在JavaScript中,他支持任意形式的用法2。目前用法3和用法4的用途有限,并且对于学习过其他语言的开发者来说,容易产生混淆。他们的行为完全不同。

版权声明:本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

未来的发展方向

用法1和用法2还是不够完美,它们只允许简单地变量解析。在未来,我们可能讨论在字符串中可以解析任何表达式,比如像这样解析函数。

var_dump("{$:func()}")

在这之前,删除一些会产生混乱的用法就很有必要了。


参考文章: https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation 

最近浏览
IP用户:51.222.*.*
3 天前 aHrefs Bot
IP用户:107.173.*.*
6 天前 Chrome Windows 10
IP用户:54.36.*.*
6 天前 aHrefs Bot
IP用户:17.241.*.*
7 天前 Applebot
IP用户:153.3.*.*
10 天前 Firefox Windows 7
IP用户:54.36.*.*
10 天前 aHrefs Bot
IP用户:66.249.*.*
10 天前 Googlebot
IP用户:101.67.*.*
12 天前 Generic Bot
IP用户:206.189.*.*
12 天前 Chrome Windows 10
IP用户:60.188.*.*
14 天前 Generic Bot
IP用户:124.237.*.*
14 天前 Firefox Windows 7
IP用户:51.222.*.*
15 天前 aHrefs Bot
累计浏览次数:1976
评论
点击登录
phpreturn,PHP武器库,专注PHP领域的项目和资讯,收录和介绍PHP相关项目。
最近浏览 点击登录
累计浏览次数:190848
一周浏览次数:1097
今日浏览次数:119

本站所有权利归 phpreturn.com 所有

举报/反馈/投稿邮箱:phpreturn@ulthon.com

鲁ICP备19027671号-2