在学 php,理解不了为什么 $foo->$arr[1] 和 $foo->{$arr}[1] 的结果不一致...

2016-03-24 19:42:16 +08:00
 gamexg
class foo {
    var $bar = 'I am bar.';
    var $arr = array('I am A.', 'I am B.', 'I am C.');
    var $r   = 'I am r.';
}

$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo $foo->$bar . "\n";  //$bar 的值是 bar ,$foo->bar 的值是 I am bar
echo $foo->$baz[1] . "\n"; //I am bar.

$start = 'b';
$end   = 'ar';
echo $foo->{$start . $end} . "\n";//$start 的值是'b' ,$end 的值是'ar' ,{$start . $end}的值是 'bar',$foo->{$start . $end} 的值是'I am bar.'

$arr = 'arr';
echo $foo->$arr[1] . "\n";// $arr 的值是 'arr' ,$arr[1] 的值是 r $foo->$arr[1]的值是 'I am r.'。
echo $foo->{$arr}[1] . "\n";// 我理解:$arr 的值是 'arr' ,{$arr}[1] 的值是 r $foo->$arr[1]的值是 'I am r.'。但实际输出是 I am B.不太理解这里的运算优先级是什么情况。查手册运算符优先级里面没有 -> ...

最后一行实在理解不了为什么输出 I am B ...

4036 次点击
所在节点    PHP
21 条回复
laucie
2016-03-24 19:57:52 +08:00
php 中的大括号 有一个用法是界定变量的界限,也可以界定表达式{$arr} = 'arr',网上都有总结
laucie
2016-03-24 19:59:00 +08:00
还有你这个 类里面用的 var php5*差不多都淘汰了,建议你换高的版本
wayne712
2016-03-24 20:00:12 +08:00
在 php 中使用 var 声明类成员属性是 php4 时代的写法,
另外$arr 与{$arr}结果一致没有什么不妥。
iyaozhen
2016-03-24 20:17:04 +08:00
iyaozhen
2016-03-24 20:19:32 +08:00
@iyaozhen
$$foo['bar']['baz'] // interpreted as ($$foo)['bar']['baz']
$foo->$bar['baz'] // interpreted as ($foo->$bar)['baz']
$foo->$bar['baz']() // interpreted as ($foo->$bar)['baz']()
Foo::$bar['baz']() // interpreted as (Foo::$bar)['baz']()

理解就好,而且一般也不这么写,看起来好费劲。
iyaozhen
2016-03-24 20:20:46 +08:00
大括号改变了解释的顺序。
Sunyanzi
2016-03-24 20:52:33 +08:00
在 $b 等于 c ... $b[$d] 等于 e 的情况下 ...

在旧版本的 php 中 $a->$b[$d] 的含义是从 a 对象中取得 $c [$d] 的值 ... 即 $e 的值 ...

使用变量定界符的话 $a->{$b}[$d] 的含义是从 a 对象中优先取得 $c 的值然后取 $d 位 ...

如楼上所说这种差异在 php7 里面已经不存在了 ... php7 中你这两种情况都视为有定界符 ...

假如你要获得原始的结果需要使用 $a->{$b[$d]} ... 等同于 $a->e ... 这也是最规范的写法 ...

两点建议第一是从最新版的 php 用起 ... 现在还从 5.2 年代的教程看起的话未免太过误人子弟 ...

第二是 php 里面这种小坑其实还挺多的 ... 这类知识点除了面试时候有用实际开发中很难遇到 ...

所以学的时候觉得头疼也不用太过担心 ... 这不是个常见情况 ... 能记则记不能记也没关系的 ...
gamexg
2016-03-24 20:54:30 +08:00
这个是直接复制的 php.net 的例子,就没动 var 声明。

@wayne712 问题是结果不一致...
@laucie 搜索了 Php 中"{}"大括号的用法总结,但是还是不理解这里的运算优先级。

$foo->$arr[1] 是[]运算符优先,但是 $foo->{$arr}[1] 就变成了 -> 运算符优先。怎么理解 -> [] 的优先级呢?
查 php 文档运算符优先表里面没有->,好头疼...


@iyaozhen 的确在 php7 下结果变了,这样会让一些程序掉坑里吧?

echo $foo->$arr[1]
echo $foo->{$arr}[1]
都输出 "I am B."
gamexg
2016-03-24 21:06:46 +08:00
@Sunyanzi 的确,实际应用中基本用不到,这种复杂的情况一般都会手动指定优先级。

看的是 php.net 的中文文档,刚刚又看了一下英文版本,发现删掉了这一部分,并说明 php7 有变更,详情查看 php7 迁移指南。
不过英文版本也很多地方没更新,这里还是使用 var 声明的类变量。
cxbig
2016-03-24 21:30:50 +08:00
输出 B 是因为 Array 的 index 从 0 开始, 1 当然是输出第二个。
jhdxr
2016-03-24 22:50:50 +08:00
@gamexg 手册更新也是逐步的。。。能否告知下你看的是中文手册的那一部分,我去更新下_(:з」∠)_
MrZephyrus
2016-03-25 07:59:57 +08:00
@cxbig 233 你理解错楼主意思了
gamexg
2016-03-25 08:34:58 +08:00
likezun
2016-03-25 08:54:44 +08:00
为什么要简单的问题,搞这么复杂! 我觉得编程就应避繁从简,回避这种容易产生歧义用法
cxbig
2016-03-25 09:56:35 +08:00
@MrZephyrus 好像是的,他的问题不在 index ,在 variable 名称变换

@gamexg 话说你这个例子看看就好,实际开发都是不规范的写法,不必太深究这种变换
bombless
2016-03-25 10:30:08 +08:00
php 里面不是传统的解析 ast 的那种思路, 233 。它的语法设计思路在某种意义上跟 Ruby 的语意设计思路有点像
luffyfly
2016-03-25 11:27:45 +08:00
理解这个完全是浪费时间,我写了五六年 php ,也理解不了。。。
wudanyang
2016-03-25 13:14:13 +08:00
这个是链式结构,我问过这个问题,楼主看一下这个->https://segmentfault.com/q/1010000004486442
jhdxr
2016-03-25 14:52:11 +08:00
@bombless PHP7 开始也引入 AST 了
leitwolf
2016-03-25 18:02:35 +08:00
怎么感觉是要去考试一样?计算机语言用的时候都是挑一种简单好理解就行了,考试才会找出各种对的和错误的。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/266147

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX