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

PHP Использование языковых конструкций в сочетании с магическими методами

Этот question заставлял меня любопытно использовать языковые конструкции в сочетании с магическими методами PHP. Я создал демо-код:

<?php
class Testing {

    public function scopeList() {
        echo "scopeList";
    }

    public function __call($method, $parameters) {
        if($method == "list") {
            $this->scopeList();
        }
    }

    public static function __callStatic($method, $parameters) {
        $instance = new static;
        call_user_func_array([$instance, $method], $parameters);
    }
}

//Testing::list();
$testing = new Testing();
$testing->list();

Почему Testing::list() выдает синтаксическую ошибку, а $testing->list() - нет?

Из-за php зарезервированные ключевые слова оба должны потерпеть неудачу?

4b9b3361

Ответ 1

Обновить PHP 7

PHP 7 обратился к описанному поведению и реализовал функцию, называемую контекстно-зависимым лексером, представленную marcio.

Ваш код будет просто работать с PHP 7.


Ситуация перед PHP 7

Синтаксические ошибки выдаются до того, как PHP даже осознает, что метод доступен через __callStatic(), это происходит на этапе синтаксического анализа.

Поведение, которое вы описали, кажется ошибкой в ​​парсере PHP, по крайней мере, несоответствие, которое должно быть описано в документации.

Я бы опубликовал отчет об ошибке. Хороший улов!


Обновление: у файла OP есть файл с отчетом об ошибке, который можно найти здесь: https://bugs.php.net/bug.php?id=71157

Ответ 2

Контекстно-зависимые идентификаторы теперь поддерживаются для PHP 7.0 +, и ваш код будет работать. Обновление вашего PHP решит проблему.

Это был одобренный RFC, который внес изменения: https://wiki.php.net/rfc/context_sensitive_lexer.

Вы можете получить дополнительную информацию о новых функциях и об изменениях на следующей (неофициальной) ссылке на PHP 7: https://github.com/tpunt/PHP7-Reference#loosening-reserved-word-restrictions

Ответ 3

По-моему, это потому, что зарезервированные слова,

если вы замените Testing::list(); на call_user_func_array(['Testing', 'list'], []);, он будет работать как ожидалось.