web-dev-qa-db-fra.com

Impossible de trouver la classe avec PHP Espace de noms

J'ai déjà posté quelques questions concernant l'utilisation des espaces de noms dans PHP. D'après ce que j'ai obtenu, cet exemple de code ci-dessous devrait fonctionner.

Cependant, je reçois des erreurs lorsque j'essaie d'utiliser Namespace dans PHP comme ceci. Voici la première erreur lors de l'exécution du code ci-dessous tel quel ... 

Fatal error: Class 'Controller' not found in E:\Controllers\testing.php on line 6

Fichier E:\Controller\testing.php

<?php
use \Controller;

include('testcontroller.php');

$controller = new Controller;
$controller->show();
?>

Fichier 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>';
        }
    }
}
?>

Fichier E:\Library\Registry.class.php

<?php
namespace Library\Registry
{
    class Registry
    {
        function __construct()
        {
            return 'Registry.class.php Constructor was ran';
        }
    }
}
?>

Comme vous pouvez le constater, j’ai essayé de rendre la chose aussi simple que possible, simplement pour que la partie Namespace fonctionne. J'ai essayé différentes variantes et n'arrive pas à comprendre.

19
JasonDavis

Même lorsque vous utilisez l'instruction use, vous devez spécifier l'espace de nom de la classe que vous essayez d'instancier. Il existe de nombreux exemples ici: http://www.php.net/manual/fr/language.namespaces.importing.php

Pour mieux le comprendre, je vais vous décrire comment cela fonctionne. Dans votre cas, lorsque vous utilisez use \Controller, tout l'espace de noms Controller devient disponible, mais pas les classes qui se trouvent dans cet espace de noms. Donc, par exemple:

<?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();
?>

Un autre exemple:

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();
?>

Si vous souhaitez importer exactement la Controllerclass, vous devez faire use Controller\Controller - cette classe sera accessible dans votre portée actuelle.

30
Timur

Ce n’est pas une bonne idée de nommer l’espace de noms, comme la classe, parce que cela prête à confusion (et je pense que c’est ce qui se passe ici). À ce moment, vous définissez l’alias via use Controller qui se réfère soit à une classe \Controller, soit à l’espace de nommage \Controller, mais votre classe, parce qu’elle se trouve dans l’espace de nommage, est nommée \Controller\Controller1

use Controller;
$class = new Controller\Controller;

ou

$class = new \Controller\Controller;

ou

use Controller\Controller;
$class = new Controller;

L'idée est que, dès que vous essayez d'accéder à une classe portant son nom relatif, elle tente de mapper la "première partie" avec tout alias défini à l'aide de use (remeber use MyClass est identique à use MyClass as MyClass. L'option après as est l'alias).

namespace MyNamespace\MyPackage\SomeComponent\And\So\On {
  class MyClass {}
}
namespace Another {
  use MyNamespace\MyPackage\SomeComponent; // as SomeComponent
  $class =              new SomeComponent\An\So\On\MyClass;
}

Comme vous pouvez le constater, PHP trouve SomeComponent en tant que première partie et la mappe avec la SomeComponent- alias de la ligne ci-dessus.

Vous pouvez en savoir plus à ce sujet dans le manuel sur les espaces de noms .

1 Il s'appelle "Nom de classe qualifié complet", si vous nommez une classe avec son nom complet.

8
KingCrunch

Lorsque vous mettez une classe Controller dans l'espace de noms Controller, vous devez la référencer de la manière suivante:

$controller = new Controller\Controller();

\Controller serait une classe de l’espace de noms global (par défaut), c’est-à-dire comme si vous n’utilisiez aucun espace de noms.

5
Dan Soap

Étrangement, j'ai trouvé cela dans mon exemple de code de la question ci-dessus, si je modifie tous les Namespace's définis en quelque chose comme MyLibrary, ce serait donc comme ce code ci-dessous ...

Fichier E:\Library\Registry.class.php

<?php
namespace MyLibrary
{
    class Registry
    {
        function __construct()
        {
            echo 'Registry.class.php Constructor was ran';
        }
    }
}
?>

Ensuite, lorsque j'utilise use MyLibrary\Registry; dans un autre fichier, je peux y accéder comme je l'avais prévu ...

$this->registry = new Registry;

La raison pour laquelle cela m'est très étrange est que cela fait maintenant apparaître un nom de classe comme étant une variable Namespace. Je n'aurais donc pas besoin de définir un espace de noms sur 'MyLibrary\Library' pour accéder à Registry. Je le ferais comme je l'ai montré dans cette réponse pour pouvoir y accéder simplement en appelant le nom de la classe.

J'espère que cela a du sens et aide quelqu'un d'autre. Je n'accepterai pas cela comme réponse car j'espère qu'une personne plus expérimentée viendra poster une meilleure réponse avec explication

2
JasonDavis

essayer

<?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>';
    }
}
?>

et

<?php
namespace Library\Registry;
class Registry
{
    function __construct()
    {
        return 'Registry.class.php Constructor was ran';
    }
}
?>
0
Ascherer