Так, при попытке сделать вложенный класс как это:
//nestedtest.php
class nestedTest{
function test(){
class E extends Exception{}
throw new E;
}
}
Вы получите ошибку Fatal error: Class declarations may not be nested in [...]
но если у Вас есть класс в отдельном файле как так:
//nestedtest2.php
class nestedTest2{
function test(){
include('e.php');
throw new E;
}
}
//e.php
class E Extends Exception{}
Так, почему делает второй hacky способ сделать его работа, но non-hacky способ сделать его не работает?
Из руководства ( http://php.net/manual/en/function.include.php ):
Когда файл включено, код, который он содержит, наследует область видимости переменной строки, в которой происходит включение . Любые переменные, доступные в этой строке в вызывающем файле, будут доступны в вызываемом файле, начиная с этой точки. Однако все функции и классы , определенные во включенном файле , имеют глобальную область видимости.
Второй способ - это не вложение классов. У вас просто есть оба объявления в одном файле, который отличается от вашего первого примера. В PHP вы можете иметь несколько объявлений классов в одном файле, это организационное решение, а не требование.
Нет никакой веской причины определять класс внутри метода. Второй способ "работает" только в том смысле, что он не приводит к ошибке - класс по-прежнему существует в той же области видимости/пространстве имен, что и все остальные определенные классы. Таким образом, в этом сценарии вы на самом деле не "вложенность" класса.
Кстати, причина, по которой это работает, заключается в том, что класс - это просто определение - нет никакого выполнения, связанного с определением класса. Поэтому файл (e.php) разбирается, как только вы его включаете, и тогда его класс становится доступным для текущего контекста выполнения. Только исполняемые части кода (например, throw new E;
) будут фактически принадлежать области видимости вызывающей стороны.