пространство имен это фактически уникальный идентификатор класса
Вполне можно рассматривать это с такой позиции. Например в том же Windows, если в папке d:\Downloads\
лежит файл Приколы.doc
, то система считает, что его имя на самом деле d:\\Downloads\\Приколы.doc
. Таким образом система считает файлы с одинаковым названием и расширением, но лежащие в разных папках - разными файлами.
namespace Abracadabra\Abra\cadabra\NoFolder\AnyText;
// Файл Strings.php лежит в папке MyPHPProject\classes
// Но мы решили просто написать какое то пространство имен-текст который первым пришел в голову
Да, такое может быть, используя загрузчики, типа composer
. Там можно задать папки или файлы немного кастомные, так скажем, у которых пространство имён никак не совпадает с физическим расположением в системе. Однако стОит понимать, что общая практика склоняется всё же к совпадению путей в пространстве имён и пути в проекте, именно для того, чтобы подсказать программисту где лежат эти файлы. Поэтому часто загрузчик делают по PSR-4
и в таком случае если указать выдуманный из головы namespace - то получишь ошибку Class 'app\models\test\Testy1' not found
вложенность как то ещё влияет на вызов классов?
Вложенность может влиять некоторым образом на производительность. Но не значительно. Как правило, при использовании автозагрузчика эти файлы могут быть перечислены у него в специальном файле, типа такого
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'ArithmeticError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php',
'AssertionError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php',
'Codeception\\Exception\\ExternalUrlException' => $vendorDir . '/codeception/lib-innerbrowser/src/Codeception/Exception/ExternalUrlException.php',
'Codeception\\Lib\\Connector\\Yii2' => $vendorDir . '/codeception/module-yii2/src/Codeception/Lib/Connector/Yii2.php',
'Codeception\\Lib\\Connector\\Yii2\\ConnectionWatcher' => $vendorDir . '/codeception/module-yii2/src/Codeception/Lib/Connector/Yii2/ConnectionWatcher.php',
'Codeception\\Lib\\Connector\\Yii2\\FixturesStore' => $vendorDir . '/codeception/module-yii2/src/Codeception/Lib/Connector/Yii2/FixturesStore.php',
);
и он просто будет их подключать в цикле в коде через require
. В целом все классы требуют подключения через require
и на это тратится время. Однако, как правило, оно не столь значительное, чтобы сильно влиять на производительность.
зачем нужны относительные и абсолютные пути?
Относительный путь удобно использовать во вложенности. Если есть класс по пути app\models\test\Test
и app\models\test\Test2
, то в первом достаточно будет написать use Test2
, а не use app\models\test\Test2
.
Абсолютный - я бы сказал, что нужен больше для предохранения от случайного подключения неправильного класса. Например
namespace My\Other\NS {
use \My\Other as Other;
use Other\NS as Duh; // Будет искать \My\Other\NS
}
namespace My\Other\NS {
use My\Other as Other;
use Other\NS as Duh; // Будет искать \My\Other\NS\My\Other\NS
}
Такое может возникнуть например, когда есть "несколько корней". Например у используемого фреймворка, который лежит в папке vendor
, может всё начинаться с Yii
или Sympony
, а в приложении всё начинается с app
. В таком случае может произойти следующее:
namespace app\controllers;
class SiteController extends Controller {
public function actionTest() {
echo Yii::$app->user->isGuest;
}
}
В этом случае будет ошибка Class 'app\controllers\Yii' not found
потому что путь относительный. Однако если поставить путь "от корня", абсолютный, вот так:
echo \Yii::$app->user->isGuest;
то всё будет работать.
А тут это зачем? Зачем пишут MyPHPProject\Strings и \MyPHPProject\Strings?
Во-первых - см. текст выше. Второе - это может быть сделано для перестраховки, чтобы наверняка подключить нужный класс, а не бояться, что подключится класс из относительного пути. Но как правило все классы подключают в use
, если нужно назначают алиасы, а уже в коде ниже пишут всё без обратной черты. Код становится чище.
Обратную черту перед классом любят ставить по многим причинам (мне лично кажется это избыточным), например для встроенных функций PHP, типа new \PDO
или \strlen(...)
. Чтобы отличить свои написанные классы, от встроенных.
Ну и если есть конфликт имён (например при наследовании класса из другого неймспейса.), тоже можно это использовать.
namespace foo;
class Bar extends \baz\Bar { }
Однако я лично предпочитаю задать алиас и писать так:
namespace foo;
use baz\Bar as CoreBar;
class Bar extends CoreBar { }