PHP命名空间行为使用spl_autoload_register产生FATAL错误

时间:2015-01-22 09:40:20

标签: namespaces php-5.5 spl-autoload-register

我想一起使用namespacespl_autoload_register,但每次都失败并出现不同的错误。

请参阅github上的完整代码文件。

以下是文件

  1. 一个基本文件,用于创建一个名为 class.alpha.php
  2. 的类
  3. 我在其中定义spl_autoload_register include.php
  4. 的包含文件
  5. 实例化类对象 eg.php
  6. 的示例文件

    现在,当我从 eg.php 创建对象时,它会产生致命错误,但当我在 class.alpha.php 中评论命名空间行时,它就会出现问题。工作

    请参阅以下代码。

    alpha.class.php

    <?php
    //namespace Alpha; //<< comment and uncomment this to regenerate the error
    
    class Alpha
    {
        // public static $baseDir_;
        public $dir = __DIR__;
        public static $baseDir_;
        public function __construct()
        {
            echo __FILE__."=>".__METHOD__;
            var_dump(self::$baseDir_, $this->dir);
            $firstDir = !empty(self::$baseDir_) ? self::$baseDir_ :  $this->dir;
        }
    }
    

    include.php

    <?php //namespace Alpha\config;
    spl_autoload_extensions(".php");
    spl_autoload_register('loadclass');
    
    function loadclass($class)
    {
        try {
            if (is_readable(strtolower($class).".class.php")) {
                include_once strtolower($class).".class.php";
            }
        } catch (Exception $e) {
            print "Exception:". $e;           
        }
    }
    //@link http://php.net/manual/en/function.spl-autoload-register.php
    // spl_autoload_register(__NAMESPACE__.'Alpha\Alpha()' );
    

    eg.php

    <?php
    require_once 'include.php';
    
    /** below code works by commenting 1st line on alpha.class.php 
    if we un comment then below code gives Fatal error: Class 'Alpha' not found */
    Alpha::$baseDir_ = '/opt/lampp/archive/';
    $obj_ = new Alpha();
    var_dump(get_included_files());
    var_dump($obj_);
    
    /** now we define namespace Alpha on alpha.class.php */
    // $ns_ = new Alpha\Alpha(); // Fatal error: Class 'Alpha\Alpha' not found
    // var_dump($ns_);
    
    /** not working even with use statement */
    // use Alpha;
    // use Alpha;
    // $fn = new Alpha\Alpha();
    // var_dump($fn);
    

    请帮我解决这个问题。

    由于

1 个答案:

答案 0 :(得分:1)

如果您取消注释alpha.class.php中的命名空间并将use Alpha\Alpha放入例如,您的自动装带器将收到“Alpha \ Alpha”类的请求。这意味着它希望找到您班级的位置为alpha\alpha.class.php

除非您使用的是Windows,否则目录分隔符通常是正斜杠(/)。所以有很多可能的解决方案。

**可能的解决方案#1 - 将所有文件保留在同一个地方**

如果要将所有内容保留在现在的位置,则需要从自动装带器中的类名中删除命名空间。如果将这些行添加到自动装带器的顶部,则会使其表现如下:

$classParts = explode("\\", $class);
$class = $classParts[count($classParts) - 1];

我不建议使用此解决方案,因为这意味着您不能再在不同的命名空间中提供相同的类名。

可能的解决方案#2 - 将名称空间放在子目录中

对于此解决方案,您将创建一个新目录“alpha”并将“alpha.class.php”移入其中。对于自动装带器更改,您可以将以下行添加到自动装带器的顶部:

$class = str_replace("\\", "/", $class);

这会使用正斜杠将命名空间分隔符从反斜杠更改为文件路径分隔符。这将适用于Windows以及Mac和Linux。

可能的解决方案#3 - 遵循既定的自动加载标准

已经有许多标准的PHP自动加载标准。 PSR-0(现已弃用)有效,但建议使用PSR-4:

遵循其中一个标准的一个重大优点是已经有很多实现它们,并且已经有很多想法应该如何工作并保持与您可能最终想要使用的其他库的兼容性。 Composer(http://getcomposer.org)允许您根据非常简单的配置设置和使用PSR-0和PSR-4样式的自动加载器。

无论如何,对于TL; DR众人,问题是自动加载器接收整个命名空间路径以便知道如何加载类。致命错误是因为自动加载器没有正确地从该命名空间类映射到文件系统位置,因此从未加载包含该类的文件。

希望这有帮助。