V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gamexg
V2EX  ›  PHP

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

  •  
  •   gamexg · 2016-03-24 19:42:16 +08:00 · 4108 次点击
    这是一个创建于 3185 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 ...

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

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

    @gamexg 话说你这个例子看看就好,实际开发都是不规范的写法,不必太深究这种变换
    bombless
        16
    bombless  
       2016-03-25 10:30:08 +08:00 via Android
    php 里面不是传统的解析 ast 的那种思路, 233 。它的语法设计思路在某种意义上跟 Ruby 的语意设计思路有点像
    luffyfly
        17
    luffyfly  
       2016-03-25 11:27:45 +08:00
    理解这个完全是浪费时间,我写了五六年 php ,也理解不了。。。
    wudanyang
        18
    wudanyang  
       2016-03-25 13:14:13 +08:00
    这个是链式结构,我问过这个问题,楼主看一下这个->https://segmentfault.com/q/1010000004486442
    jhdxr
        19
    jhdxr  
       2016-03-25 14:52:11 +08:00
    @bombless PHP7 开始也引入 AST 了
    leitwolf
        20
    leitwolf  
       2016-03-25 18:02:35 +08:00
    怎么感觉是要去考试一样?计算机语言用的时候都是挑一种简单好理解就行了,考试才会找出各种对的和错误的。。。
    gamexg
        21
    gamexg  
    OP
       2016-03-25 20:24:47 +08:00
    @leitwolf 打算认真学习下 php ,看 php.net 文档时碰到了这个问题,实在太违反常识了...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5391 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 1183ms · UTC 02:30 · PVG 10:30 · LAX 18:30 · JFK 21:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.