Не удается найти класс с пространством имен 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';
    }
}
?>