Как мой класс включается дважды, когда код даже не достигает этой точки выполнения? - PullRequest
1 голос
/ 07 марта 2012

a.php

<?php

echo "AAA\n";
if(class_exists('NotImplementedException')) {
    echo "BBB\n";
    return;
    echo "DDD\n";
}

echo "CCC\n";

/**
 * Thrown when a feature is not yet implemented.
 */
class NotImplementedException extends Exception {}

b.php

<?php
include 'a.php';
include 'a.php';

Когда я запускаю b.php, я получаю:

AAA
BBB
PHP Fatal error:  Cannot redeclare class NotImplementedException in /home/mark/Tests/IncludeTwice/a.php on line 15

Что здесь происходит?Вывод, который я ожидаю, будет

AAA
CCC
(class gets declared for first time)
AAA
BBB
(execution stops)

Для тех, кто говорит «интерпретатор сначала сканирует и анализирует весь файл»: тогда почему это работает?:

<?php

class A{}

if(!class_exists('A')) {
    class A{}
}

Ответы [ 2 ]

3 голосов
/ 12 марта 2012

Я думаю, что одна часть является ошибкой ...

Интерпретатор PHP работает иначе, если вы расширяете класс.

Это работает:

<?php

class a {}
exit();
class a extends Exception {}

?>

Этоне:

<?php

class a extends Exception {}
exit();
class a {}

?>

Из того, что я вижу в PHP 5.4.0 source , есть две разные функции, которые обрабатывают связывание классов: do_bind_class:4494 для автономных классов иdo_bind_inherited_class:4533 для унаследованных классов (тех, которые используют ключевое слово extends).

Автономная функция имеет условие, которое игнорирует повторяющиеся определения классов во время компиляции, если оно никогда не срабатывает во время выполнения.В версии унаследованного класса отсутствует это условное условие (может быть, умышленно, а может и нет).

Я бы исправил унаследованную функцию, чтобы иметь то же самое условие, протестировал и отправил ее разработчикам.другая часть - это особенность ...

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

Это работает:

<?php

$a = new A();

//{
    class A {}
//}

?>

Это не работает, даже если оно логически идентично:

<?php

$a = new A();

{
    class A {}
}

?>

Когда вы объединяете эти две части функциональности, возникает ваша проблема, поскольку ваш класс является унаследованным классом и объявлен в глобальной области видимости.

2 голосов
/ 07 марта 2012

Вам нужно переместить объявление класса в оператор else из вызова class_exists().Оба раза вы объявляете, что включаете a.php.return не предотвращает синтаксический анализ файла, который в данном случае включает объявление класса.Таким образом, хотя выполнение скрипта не проходит мимо вашего возврата, PHP видит, что вы объявили NotImplementedException более одного раза.

Думайте об этом, как будто вы ставите кучу синтаксически некорректного кода после return.Синтаксический анализатор все равно выдаст вам ошибку, даже несмотря на то, что выполнение кода не сделает его там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...