Итак, если вы попытаетесь сделать вложенный класс следующим образом:
//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{}
в//nestedtest2.php class nestedTest2{ function test(){ include('e.php'); throw new E; } } //e.php class E Extends Exception{}
Итак, почему второй хакерский способ сделать это, но не-хакерский способ сделать это не работает?
Из руководства ( http://php.net/manual/en/function.include.php ):
Когда файл включен, код, который он содержит, наследует область изменения строки, в которой происходит включение. Любые переменные, доступные в этой строке в вызывающем файле, будут доступны в вызываемом файле с этой точки вперед. Однако все функции и классы, определенные во включенном файле, имеют глобальную область видимости.
Второй способ – не вложение классов. У вас есть только две объявления в одном файле, которые отличаются от вашего первого примера. В PHP вы можете иметь несколько деклараций классов в одном файле, это организационное решение не является требованием.
Нет веских оснований для определения класса внутри метода. Второй способ «работает» только в том смысле, что он не выдает ошибку – класс все еще существует в том же пространстве scope / namespace, что и все другие определенные классы. Таким образом, вы на самом деле не «вложен» в класс в этом сценарии.
Кстати, причина, по которой он работает, состоит в том, что класс – это просто определение – нет никакого выполнения, связанного с определением класса. Таким образом, файл (e.php) анализируется сразу же после его включения, а затем его класс становится доступным для текущего контекста выполнения. Только исполняемые части кода (т. throw new E;
) будут фактически принадлежать области действия вызывающего.