项目子文件夹中的PHP命名空间


doctrine orm - PHP namespaces in project subfolders

我最近一直在努力解决PHP中的名称空间问题。以面向对象的方式开始一个新项目,我想把项目从结构到功能都准备得整洁干净。

正如我所说的,它是用面向对象的PHP开发的。使用原则作为ORM,项目的全局结构看起来像这样:

/admin
  |- /index.php
/css
/fonts
/img
/js
/src
  |- /controller
  |- /model
  |- /system
    |- /utils
      |- /Singleton.php
  |- /view
/vendor
/index.php

好的,我们来举一个简单的例子。

我有一个Singleton类,它位于以下路径:src/system/utils/Singleton.php

<?php
namespace system'utils;
/**
 * Base class for singleton use cases
 */
class Singleton 
{
    /**
     * Returns the *Singleton* instance of this class.
     * @staticvar Singleton $instance The *Singleton* instance of this class.
     * @return Singleton the *Singleton* instance.
     */
    public static function getInstance() {
        static $instance = null;
        if ($instance === null) {
            $instance = new static();
        }
        return $instance;
    }
   // Private constructor, only local construction allowed
    protected function __construct() {
    }
    // Private cloner, only current instance 
    private function __clone() {
    }
    // Private wakeup function, to prevent unserializing
    private function __wakeup() {
    }
}

可以看到,该类使用命名空间system'utils。然后,在主文件夹中的/index.php文件中,要使用这个类,我执行以下操作:

<?php
  require_once 'bootstrap.php';
  use system'utils'Singleton;
  $singleton = Singleton::getInstance();
  var_dump($singleton);
?>

(注:bootstrap.php为Doctrine的配置文件。我知道它使用了某种自动加载功能,这可能是我在这里暴露的问题的一部分,所以你可以在本文末尾找到它的内容

这个例子工作得很好。太好了。但是。如果我做完全相同的测试不是在/index.php,但/admin/index.php,它失败了,PHP说它找不到类Singleton。

我在这里真的很困惑,因为我认为名称空间是项目体系结构中每个类的某种"唯一"标识符,然后可以用来检索项目结构中的任何一个类。显然,我错了,到处搜索也帮不了我。

我最好的猜测是自动加载之类的东西,因为我知道Doctrine使用它。也许我在配置ORM时遗漏了一些东西。如前所述,以下是我的/bootstrap.php的内容,其中包含所有配置设置。

<?php
// bootstrap.php
use Doctrine'ORM'Tools'Setup;
use Doctrine'ORM'EntityManager;
require_once "vendor/autoload.php";
// Create a simple "default" Doctrine ORM configuration for Annotations
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/src/model/entities/"), $isDevMode);
// database configuration parameters
$conn = array(
    'driver' => 'pdo_mysql',
    'host' => 'host',
    'port' => 'port',
    'charset' => 'utf8',
    'dbname' => 'database',
    'user' => 'database',
    'password' => 'database'
);
// obtaining the entity manager
$entityManager = EntityManager::create($conn, $config);

我不知道这是否有帮助,但我可以在/src文件夹内的任何地方正确使用名称空间,但似乎它在主目录的另一个子文件夹中不起作用。

如果有人能清楚地解释这里发生了什么,如何在PHP中管理命名空间,以及最终如何对我的代码进行修正,那将是非常好的分享你的知识。


编辑:

它肯定和自动加载有关。我设法通过为命名空间编写正确的use语句并在../src/中声明需要文件的__autoload函数来使其工作。

<?php
    use system'utils'Singleton;
    $singleton = Singleton::getInstance();
    $singleton->manageSession();
    function __autoload($className)
    {
        echo "Autoloading $className.php in ../src/";
        require_once("../src/$className.php");
    }
    require_once '../bootsrap.php';
?>

输出Autoloading system'utils'Singleton.php in ../src/

所以它有效,我可以继续使用这个解。问题是,我认为这是一种变通办法,而不是解决办法。我仍然相信我做错了什么,它可以优化,但不知道如何…如果你有什么知识可以分享,我洗耳恭听!


提前感谢一群人,抱歉发了这么大的帖子。

问题是您在admin/index.php中做了完全相同的操作,在这种情况下是错误的。

问题出在下一行:

require_once 'bootstrap.php';

告诉php首先查找文件bootstrap.php,相对于包含/需要该文件的文件,如果失败,则在配置的包含路径中查找。

它没有包含在您的目录结构中,但是从它的外观来看,bootstrap.phpindex.php位于同一级别。要解决您的问题,请将admin/index.php中的上述行替换为以下内容:

require_once '../bootstrap.php';