Как можно & quot; [& quot; быть оператором в спецификации языка PHP?

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

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

46

Решение

Это очень актуальный вопрос.

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

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

Пример:

$a[1+2]

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

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

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

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

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

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";

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

Тест 1

echo new $test;

Это утверждение создает новый TestClass экземпляр, который затем должен быть преобразован в
строка, так что __нанизывать метод вызывается для этого нового экземпляра, который возвращает:

Я объект TestClass

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

Тест 2

echo (new $test)[0];

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

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

Тест 3

echo new ($test[0]);

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

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

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

Я объект Т

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

Тест 4

echo new $test[0];

Это правильный синтаксис, и …

4. Вывод

Выход:

Я объект Т

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

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

clone Оператор имеет похожее поведение в сочетании с [, Достаточно странно, clone а также new не полностью равны с точки зрения правил синтаксиса. Повторение теста 2 с clone:

echo (clone $test)[0];

выдает ошибку разбора:

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

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

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

67

Другие решения

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

$first[$second]

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

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

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

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

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

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

4
По вопросам рекламы [email protected]