【问题标题】:php cannot redeclare _autoload()php 无法重新声明 _autoload()
【发布时间】:2012-06-14 13:49:05
【问题描述】:

我对 php 有了更深入的了解,我正在创建自己的 mini mvc 框架来学习 OOP。

我有一个将所有内容重定向到 index.php 的 .htaccess 文件。在 index.php 中,我包含一个名为 bootstrap.php 的文件来解析 url 并加载类 php 文件。

现在我正在添加 ActiveRecord http://www.phpactiverecord.org 以添加数据库访问权限。我得到了错误:

致命错误:无法在第 4 行的 /home/i554246/public_html/mvc/lib/Autoloader.php 中重新声明类 AutoLoader

我不确定如何停止冲突。

index.php:

include(MVC_CORE_INCLUDE_PATH . DS . 'Bootstrap.php')
include(MVC_CORE_INCLUDE_PATH . DS . 'activerecord/ActiveRecord.php');

bootstrap.php中包含的autoloader.php

<?php

class AutoLoader
{
    public static function Load($Class)
    {
        $File = BASEDIR.$Class.'.php';

        if(is_readable($File))
        {
            require($File);
        }
        else
        {
            die('Requested module "'.$Class.'" is missing. Execution stopped.');
        }
   }
}

spl_autoload_register('AutoLoader::Load');

ActiveRecord.php

if (!defined('PHP_ACTIVERECORD_AUTOLOAD_DISABLE'))
    spl_autoload_register('activerecord_autoload',false,PHP_ACTIVERECORD_AUTOLOAD_PREPEND);

function activerecord_autoload($class_name)
{
    $path = ActiveRecord\Config::instance()->get_model_directory();
    $root = realpath(isset($path) ? $path : '.');

    if (($namespaces = ActiveRecord\get_namespaces($class_name)))
    {
        $class_name = array_pop($namespaces);
        $directories = array();

        foreach ($namespaces as $directory)
            $directories[] = $directory;

        $root .= DIRECTORY_SEPARATOR . implode($directories, DIRECTORY_SEPARATOR);
    }

    $file = "$root/$class_name.php";

    if (file_exists($file))
        require $file;
}
?>

【问题讨论】:

    标签: php phpactiverecord


    【解决方案1】:

    也许会改变

    if (file_exists($file))
        require $file;
    

    if (file_exists($file))
        require_once($file);
    

    【讨论】:

    • 如果可能的话,我不想更改 ActiveRecord.php 的任何内容,因为它是第三方的,可能会导致升级问题。还有其他方法吗?
    • 也许吧,但我倾向于同意Nanne 的观点,即您的下一步应该是调试堆栈。我认为您需要准确说明事情发生的顺序。还要听听 Nanne 关于命名空间的建议——即使这个问题的根源不存在命名空间冲突,额外的纪律也将帮助您排除红鲱鱼。
    【解决方案2】:

    您要么尝试包含一个文件两次(您可能想要使用 require_once),要么您有 2 个具有相同名称的类(一个来自您使用的库?)。

    如果似乎有 2 个名为 AutoLoader 的类,您可能需要查看命名空间。我不记得 phpactiverecord 有一个叫做那个的类,但是你可能会使用几个库,所以你一定会遇到这个。

    最好的方法是将您自己的自动加载器类放在namespace 中。确保你的所有调用都正确,所以对自动加载器的调用应该在它前面有\yournamespace\,并且自动加载器内部的调用可能需要在前面加上一个\(例如\Exception

    【讨论】:

    • 如果我首先加载 ActiceRecord.php 我有一个致命错误的问题:无法重新声明 activerecord_autoload() (之前在 /home/i554246/public_html/mvc/lib/activerecord/ActiveRecord.php 中声明:28) 在 /home/i554246/public_html/mvc/lib/activerecord/ActiveRecord.php 第 48 行
    • 嗯,activerecord 本身没有这个问题,所以肯定有其他问题。您可能包含该文件两次,也许两个自动加载器都包含它?我建议您仅对其进行调试:将记录堆栈跟踪的内容放入该双重调用的文件中,然后检查发生了什么:现在您知道代码的哪些部分加载了该文件。第二次你会得到错误,但你可以继续阻止它被加载两次。
    • 谢谢,我将 require_once 添加到 ActiveRecord.php 中,错误转移到下一个包含并抱怨该类。我再次向其中添加了 require_once,错误再次移动到下一个包含并且无法重新声明该类。似乎重新加载了所有包含所在的 index.php。很奇怪,只有当我包含 ActiveRecords 时才会发生。
    • 也许 activerecord 自动加载器触发与您自己的自动加载器相同的请求?所以它会加载你的自动加载器两次?还是自动加载的所有内容都会自动加载两次?
    • 是的,这么想,对我来说都是新的,所以我有点困惑。这似乎发生在我在 index.php 中包含 $Bootstrap = new Bootstrap(); 下的这一行
    【解决方案3】:

    PHP-ActiveRecord 没有任何AutoLoader 类。我猜这里发生的事情是您有两个加载程序正在加载文件。

    由于它符合 PSR-0 标准,您可以使用自己的加载实用程序加载它(假设它接受该约定)。如果您这样做,只需禁用 PHP-AR 自动加载实用程序。

    define('PHP_ACTIVERECORD_AUTOLOAD_DISABLE', true);
    

    vanilla 加载器对于查找模型类非常有用,如果您将它们放在它们自己的命名空间中则不需要这些类。由于您的框架可能不遵循关于模型位置的 PHP-AR 约定,因此禁用该自动加载器似乎是正确的。

    查看 PHP-AR 与锂框架集成的示例:li3_activerecord

    【讨论】:

      【解决方案4】:

      我移动了这条线

      $Bootstrap = new Bootstrap(); 
      

      include(MVC_CORE_INCLUDE_PATH . DS . 'Bootstrap.php'); 
      include(MVC_CORE_INCLUDE_PATH . DS . 'Controller.php'); 
      

      但高于

      require_once 'lib/activerecord/ActiveRecord.php'; the ActiveRecord seemed to want to load it again
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-11
        • 2013-08-21
        • 2023-04-02
        相关资源
        最近更新 更多