На веб-странице http://php.net/manual/en/language.operators.precedence.php второй уровень наивысшего приоритета содержит левоассоциативный оператор, называемый [
.
Я этого не понимаю. Используется ли [
для доступа / изменения записей массива, как в $myArray[23]
? Я не могу представить ни одного фрагмента кода, где нам нужно было бы знать «приоритет» его по отношению к другим операторам или где «ассоциативность» [
была бы полезна.
Это очень важный вопрос.
Во-первых, никогда не бывает двусмысленности в отношении того, что PHP должен сначала оценить, глядя на правую сторону [
, так как для скобки требуется закрытие, чтобы идти с ней, и поэтому каждый оператор между ними имеет приоритет над открывающей скобкой.
Пример:
$a[1+2]
+
Имеет приоритет, т.е. сначала 1 + 2 нужно оценить, прежде чем PHP сможет определить, какой элемент получить из $ a .
Но список приоритетов операторов не об этом.
Во-вторых, есть порядок оценки последовательных пар []
, как здесь:
$b[1][2]
Сначала PHP будет оценивать $b[1]
а затем применить [2]
к этому. Это оценка слева направо, и это то, что предполагается с левой ассоциативностью .
Но вопрос заключается не столько в ассоциативности, сколько в отношении приоритетов в отношении других операторов.
В списке указано, что clone
и new
операторы имеют приоритет над [
, и это непросто проверить.
Прежде всего, большинство конструктов, в которых вы должны комбинировать new
с квадратными скобками, считаются недопустимым синтаксисом. Например, оба этих утверждения:
$a = new myClass()[0]; $a = new myClass[0];
приведет к ошибке синтаксического анализа:
синтаксическая ошибка, неожиданно '['
PHP требует, чтобы вы добавляли круглые скобки, чтобы сделать синтаксис действительным. Поэтому мы не можем проверить правила приоритета, подобные этому.
Но есть другой способ, используя переменную, содержащую имя класса:
$a = new $test[0];
Это допустимый синтаксис, но теперь задача состоит в том, чтобы создать класс, который создает что-то, что действует как массив.
Это не так просто, поскольку свойство объекта ссылается так: obj->prop
, а не 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's 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's array element"; } } $test = "TestClass";
С помощью этой настройки мы можем проверить несколько вещей.
echo new $test;
Этот оператор создает новый экземпляр TestClass , который затем должен быть преобразован в строку, поэтому метод __toString вызывается в этом новом экземпляре, который возвращает:
Я объект TestClass
Это так, как ожидалось.
echo (new $test)[0];
Здесь мы начинаем с одних и тех же действий, так как скобки заставляют сначала выполнять new
операцию. На этот раз PHP не преобразует созданный объект в строку, а запрашивает из него элемент массива 0. На этот запрос отвечает метод offsetGet , и поэтому выведенный выше вывод выводит:
Я элемент массива объекта TestClass
echo new ($test[0]);
Идея состоит в том, чтобы заставить противоположный порядок исполнения. К сожалению, PHP не позволяет использовать этот синтаксис, поэтому для того, чтобы получить предполагаемый порядок оценки, вам придется разбить оператор на две части:
$name = $test[0]; echo new $name;
Итак, теперь [
выполняется первым, беря первый символ значения $ test , т. Е. «T» , а затем к нему применяется new
. Вот почему я определил также класс Т. echo
вызывает в этом экземпляре __toString , что дает:
Я объект T
Теперь идет заключительный тест, чтобы увидеть, какой порядок, когда нет круглых скобок:
echo new $test[0];
Это допустимый синтаксис и …
Выход:
Я объект T
Таким образом, на самом деле PHP применял [
перед new
оператором, несмотря на то, что указано в таблице приоритетов оператора !
clone
с new
Оператор clone
имеет аналогичное поведение в сочетании с [
. Как ни странно, clone
и new
не совсем равны с точки зрения правил синтаксиса. Повторный тест 2 с clone
:
echo (clone $test)[0];
приводит к ошибке синтаксического анализа:
синтаксическая ошибка, неожиданно '['
Но тест 4, повторенный с помощью clone
показывает, что [
имеет приоритет над ним.
@bishop сообщила, что это воспроизводит давнюю документальную ошибку # 61513: «Приоритет оператора clone
неправильный» .
Это просто означает, что переменная массива (левая ассоциативность – $ first) будет вычисляться до ключа массива (правая ассоциативность – $ second)
$first[$second]
Это имеет большой смысл, когда массив имеет несколько измерений
$first[$second][$third][$fourth]
В PHP вы можете инициализировать пустые массивы с помощью []
поэтому, чтобы знать, как определить массив, приоритет следующего символа определяет, как инициализировать массив.
Поскольку массивы являются частью структуры синтаксиса, это делается до любой математики, поэтому по этой причине она имеет более высокий приоритет, чем другие вычислительные операторы.
var_dump([5, 6, 7] + [1, 2, 3, 4]); # 5674 - The array's must be known before applying the operator
Однако, честно говоря, я не совсем понимаю этот вопрос. В большинстве языков программирования [
и ]
связаны с массивами, которые являются частью базового синтаксиса, который всегда имеет высокий приоритет (если не самый высокий)