Подтвердить что ты не робот

Как "[" быть оператором в спецификации языка PHP?

На веб-странице http://php.net/manual/en/language.operators.precedence.php второй уровень старшего приоритета содержит лево-ассоциативный оператор с именем [.

Я этого не понимаю. Используется ли [ для доступа/изменения записей массива, как в $myArray[23]? Я не могу представить фрагмент кода, где нам нужно было бы знать "приоритет" его по отношению к другим операторам или где "ассоциативность" [ была бы полезна.

4b9b3361

Ответ 1

Это очень важный вопрос.

1. Приоритет между [...]

Во-первых, никогда не бывает двусмысленности в отношении того, что PHP должен сначала оценить, глядя на правая сторона [, так как скобка требует закрытия, чтобы идти с ней, и поэтому каждый оператор между ними имеет приоритет над открывающей скобкой.

Пример:

$a[1+2]

+ имеет приоритет, т.е. первый 1 + 2 должен быть оценен до того, как PHP сможет определить, элемент для из $a.

Но список приоритетов операторов не об этом.

2. Ассоциативность

Во-вторых, существует порядок оценки последовательных пар [], как здесь:

$b[1][2]

PHP сначала оценит $b[1], а затем применит к нему [2]. Это слева направо оценки и является тем, что предполагается с левой ассоциативностью.

Но вопрос заключается не столько в ассоциативности, сколько в отношении приоритетов в отношении других операторов.

3. Приоритет над операторами в левой части

В списке указано, что операторы clone и new имеют приоритет над [, и это непросто проверить.

Прежде всего, большинство конструктов, в которых вы бы объединили new с квадратными скобками, считаются недействительными синтаксис. Например, оба этих утверждения:

$a = new myClass()[0];
$a = new myClass[0];

даст ошибку синтаксического анализа:

синтаксическая ошибка, неожиданная '['

PHP требует, чтобы вы добавляли круглые скобки, чтобы сделать синтаксис действительным. Таким образом, мы не можем проверить правила приоритета, подобные этому.

Но есть и другой способ, используя переменную, содержащую имя класса:

$a = new $test[0];

Это допустимый синтаксис, но теперь задача состоит в том, чтобы создать класс, который создает что-то который действует как массив.

Это не так просто, поскольку свойство объекта ссылается следующим образом: obj->prop, not как obj["prop"]. Однако можно использовать класс ArrayObject, который может иметь дело с квадратными скобками. Идея состоит в том, чтобы расширить этот класс и переопределить метод offsetGet, чтобы убедиться, что только что созданный объект этого класса возвратил элементы массива.

Чтобы сделать объекты доступными для печати, я закончил использование магического метода __ toString, который выполняется, когда объект должен быть перенесен в строку.

Итак, я придумал эту настройку, определив два похожих класса:

class T extends ArrayObject {
    public function __toString() {
        return "I am a T object";
    } 
    public function offsetGet ($offset)  {
        return "I am a T object array element";
    }
}

class TestClass extends ArrayObject {
    public function __toString() {
        return "I am a TestClass object";
    } 
    public function offsetGet ($offset)  {
        return "I am a TestClass object array element";
    }
}

$test = "TestClass";

С помощью этой настройки мы можем проверить несколько вещей.

Тест 1

echo new $test;

Этот оператор создает новый экземпляр TestClass, который затем необходимо преобразовать в string, поэтому метод __toString вызывается в этом новом экземпляре, который возвращает:

Я объект TestClass

Это как и ожидалось.

Тест 2

echo (new $test)[0];

Здесь мы начинаем с одних и тех же действий, так как скобки принудительно выполняют операцию new. На этот раз PHP не преобразует созданный объект в строку, а запрашивает из него элемент массива 0. На этот запрос отвечает метод offsetGet, и поэтому выведенный выше вывод выводит:

Я - элемент массива объекта TestClass

Тест 3

echo new ($test[0]);

Идея состоит в том, чтобы заставить противоположный порядок исполнения. К сожалению, PHP не позволяет использовать этот синтаксис, поэтому для того, чтобы получить предполагаемый порядок оценки, вам придется разбить оператор на две части:

$name = $test[0];
echo new $name;

Итак, теперь выполняется [, беря первый символ значения $ test, т.е. "T", а затем new. Вот почему я определял также класс Т. echo вызывает этот экземпляр __toString, который дает:

Я объект T

Теперь идет заключительный тест, чтобы увидеть, какой порядок, когда нет круглых скобок:

Тест 4

echo new $test[0];

Это допустимый синтаксис и...

4. Вывод

Вывод:

Я объект T

Таким образом, PHP применял [ до оператора new, несмотря на то, что указано в таблица приоритетов операторов!

5. Сравнивая clone с new

Оператор clone имеет аналогичное поведение в сочетании с [. Как ни странно, clone и new не полностью равны в терминах правил синтаксиса. Повторный тест 2 с помощью clone:

echo (clone $test)[0];

выдает ошибку синтаксического анализа:

синтаксическая ошибка, неожиданная '['

Но тест 4, повторенный с помощью clone, показывает, что [ имеет приоритет над ним.

@bishop сообщил, что это воспроизводит долговременную ошибку документации # 61513: "clone приоритет оператора неверен" .

Ответ 2

Это просто означает, что переменная массива (левая ассоциативность - $first) будет вычисляться до ключа массива (правая ассоциативность - $second)

$first[$second]

Это имеет большой смысл, когда массив имеет несколько измерений

$first[$second][$third][$fourth]

Ответ 3

В PHP вы можете инициализировать пустые массивы с помощью [], поэтому, чтобы знать, как определить массив, приоритет следующего символа определяет, как инициализировать массив.

Поскольку массивы являются частью структуры синтаксиса, это делается до любой математики, поэтому по этой причине у нее просто больше приоритета, чем другие вычислительные операторы.

var_dump([5, 6, 7] + [1, 2, 3, 4]); # 5674 - The array must be known before applying the operator

Однако, честно говоря, я не совсем понимаю вопрос. В большинстве языков программирования [ и ] связаны с массивами, которые являются частью базового синтаксиса, который всегда имеет высокий приоритет (если не самый высокий)