gamexg
V2EX  ›  PHP

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

  •  
  •   gamexg · Mar 24, 2016 · 5070 views
    This topic created in 3879 days ago, the information mentioned may be changed or developed.
    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 ...

    Supplement 1  ·  Mar 25, 2016
    在 php7 两者的结果都变成了"I am B",这种和语言版本相关的特征已经放弃理解了...
    21 replies  •  2016-03-25 20:24:47 +08:00
    cz208209
    cz208209
    Mar 24, 2016❤️1
    1
    php 中的大括号 有一个用法是界定变量的界限,也可以界定表达式{$arr} = 'arr',网上都有总结
    cz208209
    cz208209
    Mar 24, 2016❤️1
    2
    还有你这个 类里面用的 var php5*差不多都淘汰了,建议你换高的版本
    wayne712
    wayne712
    Mar 24, 2016❤️1
    3
    在 php 中使用 var 声明类成员属性是 php4 时代的写法,
    另外$arr 与{$arr}结果一致没有什么不妥。
    iyaozhen
    iyaozhen
    Mar 24, 2016❤️1
    5
    @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
    iyaozhen
    Mar 24, 2016❤️1
    6
    大括号改变了解释的顺序。
    Sunyanzi
    Sunyanzi
    Mar 24, 2016❤️1
    7
    在 $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
    gamexg
    OP
    Mar 24, 2016
    8
    这个是直接复制的 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
    gamexg
    OP
    Mar 24, 2016
    9
    @Sunyanzi 的确,实际应用中基本用不到,这种复杂的情况一般都会手动指定优先级。

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

    @gamexg 话说你这个例子看看就好,实际开发都是不规范的写法,不必太深究这种变换
    bombless
    bombless
    Mar 25, 2016 via Android
    16
    php 里面不是传统的解析 ast 的那种思路, 233 。它的语法设计思路在某种意义上跟 Ruby 的语意设计思路有点像
    luffyfly
    luffyfly
    Mar 25, 2016
    17
    理解这个完全是浪费时间,我写了五六年 php ,也理解不了。。。
    wudanyang
    wudanyang
    Mar 25, 2016
    18
    这个是链式结构,我问过这个问题,楼主看一下这个->https://segmentfault.com/q/1010000004486442
    jhdxr
    jhdxr
    Mar 25, 2016
    19
    @bombless PHP7 开始也引入 AST 了
    leitwolf
    leitwolf
    Mar 25, 2016
    20
    怎么感觉是要去考试一样?计算机语言用的时候都是挑一种简单好理解就行了,考试才会找出各种对的和错误的。。。
    gamexg
    gamexg
    OP
    Mar 25, 2016
    21
    @leitwolf 打算认真学习下 php ,看 php.net 文档时碰到了这个问题,实在太违反常识了...
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1828 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 09:25 · PVG 17:25 · LAX 01:25 · JFK 04:25
    ♥ Do have faith in what you're doing.