# 统一变量语法

我们有可能会遇到这种情况：方法、变量、类名等会被保存在某个变量里，例如如下代码：

```php
$objects['class']->name
```

`$objects['class']`先会被解析，之后name属性被解析，由左到右。

新的情况，代码如下：

```php
$first = ['name'] => 'revin'];
$revin = 'xiaoxiami';

echo $$first['name'];
```

**PHP5.X版本中**，代码会正常运行，并且输出`xiaoxiami`。解析的过程不是按照如第一个例子那样从左到右解析的原则，在PHP7中，会产生一个Notice级别的错误。为了避免解析混淆，PHP7 引入了统一变量语法。

```php
echo ${$first['name']};
```

再举一个栗子：

```php
class Info
{
    public $title = 'PHP 7';
    public $description = 'PHP 7 descriptions';

    public function geTitle() : string
    {
        return $this->title;
    }

    public function getDescription() : string
    {
        return $this->description;
    }
}

$methods = ['title' => 'geTitle', 'description' => 'getDescription'];
$object = new Info();

echo 'Info ' . $object->$methods['title']() . ' description : ' . $object->$methods['description']();
```

PHP5.X版本中，代码会正常运行，但是在PHP7中最后一行会先解析`$object->$methods`,之后才会尝试解析`['title']`等，这样并不是我们想要达到的解析预期。所以想要在PHP7中成功运行，则最后echo输出行修改为：

```php
echo 'Info ' . $object->{$methods['title']}() . ' description : ' . $object->{$methods['description']}();
```

## 总结:

**PHP7 中 对变量、属性和方法的间接调用现在将严格遵循从左到右的顺序来解析，而不是之前的混杂着几个特殊案例的情况**。 下面这张表说明了这个解析顺序的变化。

### 间接调用的表达式的新旧解析顺序

| **表达式**               | **PHP 5 的解析方式**         | **PHP 7 的解析方式**         |
| --------------------- | ----------------------- | ----------------------- |
| `$$foo['bar']['baz']` | `${$foo['bar']['baz']}` | `($$foo)['bar']['baz']` |
| `$foo->$bar['baz']`   | `$foo->{$bar['baz']}`   | `($foo->$bar)['baz']`   |
| `$foo->$bar['baz']()` | `$foo->{$bar['baz']}()` | `($foo->$bar)['baz']()` |
| `Foo::$bar['baz']()`  | `Foo::{$bar['baz']}()`  | `(Foo::$bar)['baz']()`  |

使用了旧的从右到左的解析顺序的代码必须被重写，明确的使用圆括号来表明顺序（参见上表）。 这样使得代码既保持了与PHP 7.x的前向兼容性，又保持了与PHP 5.x的后向兼容性。
