Не удается найти класс с пространством имен PHP
Ранее я задавал некоторые вопросы относительно использования пространств имен в PHP и из того, что я получил, этот примерный код, который у меня ниже, должен работать.
Однако я получаю ошибки, когда я пытаюсь использовать пространство имен в PHP, как это. Вот первая ошибка при запуске кода ниже, как...
Fatal error: Class 'Controller' not found in E:\Controllers\testing.php on line 6
E:\Controller\testing.php Файл
<?php
use \Controller;
include('testcontroller.php');
$controller = new Controller;
$controller->show();
?>
E:\Controller\testcontroller.php Файл
<?php
use \Library\Registry;
namespace Controller
{
class Controller
{
public $registry;
function __construct()
{
include('E:\Library\Registry.class.php');
$this->registry = new Registry;
}
function show()
{
echo $this->registry;
echo '<br>Registry was ran inside testcontroller.php<br>';
}
}
}
?>
E:\Library\Registry.class.php Файл
<?php
namespace Library\Registry
{
class Registry
{
function __construct()
{
return 'Registry.class.php Constructor was ran';
}
}
}
?>
Как вы можете видеть, я попытался сделать это как можно проще, чтобы получить часть пространства имен. Я пробовал разные варианты и не могу понять, как это понять.
Ответы
Ответ 1
Даже при использовании инструкции use
вам необходимо указать пространство имен класса, который вы пытаетесь создать. Здесь есть много примеров: http://www.php.net/manual/en/language.namespaces.importing.php
Чтобы понять это лучше, я расскажу вам, как это работает. В вашем случае, когда вы выполняете use \Controller
, пространство имен Controller
становится доступным для вас, но не классы, которые находятся в этом пространстве имен. Итак, например:
<?php
include('testcontroller.php');
use \Controller;
// Desired class is in namespace!
$controller = new Controller\Controller();
// Error, because in current scope there is no such class
$controller = new Controller();
$controller->show();
?>
Другой пример:
testcontoller.php:
<?php
namespace Some\Path\To\Controller;
class Controller
{
function __construct()
{
}
function show()
{
echo '<br>Was run inside testcontroller.php<br>';
}
}
?>
testing.php:
<?php
include('testcontroller.php');
use \Some\Path\To\Controller;
// We now can access Controller using only Controller namespace,
// not Some\Path\To\Controller
$controller = new Controller\Controller();
// Error, because, again, in current scope there is no such class
$controller = new Controller();
$controller->show();
?>
Если вы хотите импортировать именно Controller
класс, вам нужно сделать use Controller\Controller
- тогда этот класс будет доступен в вашей текущей области.
Ответ 2
Не так уж и хорошая идея назвать пространство имен, как класс, потому что это запутывает (и я думаю, что это то, что здесь происходит). В тот момент, когда вы определяете псевдоним через use Controller
, это относится либо к классу \Controller
, либо к пространству имен \Controller
, но ваш класс, поскольку он находится в пространстве имен, называется \Controller\Controller
1
use Controller;
$class = new Controller\Controller;
или
$class = new \Controller\Controller;
или
use Controller\Controller;
$class = new Controller;
Идея заключается в том, что в тот момент, когда вы пытаетесь получить доступ к классу с его относительным именем, он пытается сопоставить "первую часть" с любым псевдонимом, определенным с помощью use
(remeber use MyClass
совпадает с use MyClass as MyClass
. Вещь после as
является псевдонимом).
namespace MyNamespace\MyPackage\SomeComponent\And\So\On {
class MyClass {}
}
namespace Another {
use MyNamespace\MyPackage\SomeComponent; // as SomeComponent
$class = new SomeComponent\An\So\On\MyClass;
}
Как вы можете видеть, PHP находит SomeComponent
как первую часть и сопоставляет ее с SomeComponent
-alias строкой выше.
Подробнее об этом можно прочитать в об пространствах имен.
1 Его называют "Полноценное имя класса", если вы назвали класс с его полным именем.
Ответ 3
Когда вы помещаете класс Controller
в пространство имен Controller
, вы должны ссылаться на него следующим образом:
$controller = new Controller\Controller();
\Controller
будет классом в глобальном (по умолчанию) пространстве имен, т.е. как будто вы вообще не использовали пространство имен.
Ответ 4
Странно я обнаружил, что в моем примере кода из Вопроса выше, если я изменяю все Namespace's
, которые определены как-то вроде MyLibrary
, так что это будет как этот код ниже...
E:\Library\Registry.class.php Файл
<?php
namespace MyLibrary
{
class Registry
{
function __construct()
{
echo 'Registry.class.php Constructor was ran';
}
}
}
?>
Затем, когда я использую use MyLibrary\Registry;
в другом файле, я могу получить к нему доступ, как я планировал...
$this->registry = new Registry;
Причина, по которой это очень странно для меня, заключается в том, что теперь имя класса выглядит как Namespace
. Поэтому мне не нужно было устанавливать пространство имен в "MyLibrary\Library" для доступа к Registry
, вместо этого я бы сделал это, как показано в этом ответе, чтобы иметь доступ к нему, просто называя имя класса.
Я надеюсь, что это имеет смысл и помогает кому-то другому. Я не буду принимать это как ответ, поскольку я надеюсь, что кто-то с большим количеством ноу-хау войдет и опубликует лучший ответ с объяснением.
Ответ 5
попробовать
<?php
use \Library\Registry;
namespace Controller;
class Controller
{
public $registry;
function __construct()
{
include('E:\Library\Registry.class.php');
$this->registry = new Registry;
}
function show()
{
echo $this->registry;
echo '<br>Registry was ran inside testcontroller.php<br>';
}
}
?>
и
<?php
namespace Library\Registry;
class Registry
{
function __construct()
{
return 'Registry.class.php Constructor was ran';
}
}
?>