PHP致命错误:无法重新声明类


Answers:


117

这意味着您已经创建了一个类。

例如:

class Foo {}

// some code here

class Foo {}

第二个Foo将抛出错误。


75
这个答案没有AaronLS的有用。我认为提问者不会问这样一个问题,即他是否写过这样明显的重复(即使在非常复杂的情况下)。include_once提示有助于阐明PHP的晦涩功能。
DavidHyogo,2013年

2
如果多次定义__construct方法,也可能发生此错误。
杰克·特罗布里奇

4
只需使用include_once('FooBar.php')即可包含您的课程。该函数的名称不言自明。
Marco Matarazzi 2014年

2
AaronLS的答案获得了更高的评价,您可以在这里找到答案。
qris 2014年

1
实际上,这完美地回答了这个问题,而且是永恒的,AaronLS做出了一个假设,然后尝试解决该问题,现在可以通过许多更好的方法来解决该问题。
TarranJones

317

您有多次声明的同名类。也许通过多个包含。当包含其他文件时,您需要使用类似

include_once "something.php";

防止多个夹杂物。这很容易发生,尽管并不总是很明显,因为您可能会包含一长串文件。


10
这真的帮助很大!
Marci-man

4
避免include_once,它很慢,请改用其他方法,例如autoloading :)
Timo Huovinen 2012年

21
@Timo根据我查看过的基准,如果您的文件包含100,000个include_once,则只有大约1秒的明显差异。优化数据库访问权限或其他逻辑要比使用包括主文件在内的不标准技术过早地优化文件包括更好。自动加载功能的性能没有明显不同。每种功能均不同,因此不能互换使用。您可以将其中一个用于其他用途,但是在某些极端情况下,它们的功能可能不同。
AaronLS 2012年

3
@Timo要引用链接的页面,“不鼓励使用__autoload(),将来可能会弃用或删除该页面。”
AaronLS 2012年

1
@AaronLS无法在SO上编辑评论,该链接还链接到更好的示例。在阅读APC开发人员的评论以及他如何讨厌include_once(我对他感到难过)之后,我提出了建议。此外,区别还不仅仅在于性能。
Timo Huovinen 2012年

55

当您在页面中多次声明一个类时,就会发生这种情况。您可以通过用if语句包装该类(如下所示)来解决该问题,也可以将其放入单独的文件中并使用require_once()代替include()

if (!class_exists('TestClass')) {
   // Put class TestClass here
}

5
是class_exists('TestClass')=== false或!class_exist('TestClass')
Jens A. Koch 2012年

2
在@Jens-AndréKoch注释中,第二个示例中缺少“ s”-> class_exists('TestClass') === false!class_exists('TestClass')
furins 2013年

真正。感谢您指出了这一点。不再可编辑..超时。
詹斯·科赫

感谢您的逻辑。
弗兰克

21

使用include_once();-这样,您的代码将仅包含一次。


15

如果我们使用php库中的任何内置类,就会发生这种情况。我将类名用作Directory,并且遇到相同的错误。如果首先出错,请确保所使用的类名不是内置类之一。


对我来说,这是个黄金答案-我什至没有想到PHP可能与我使用的类名相同!
Jamie M

12

如果__construct多次定义该方法,也可能会发生此错误。


2
这应该是对已经被接受并高度评价的答案的评论
雅罗斯拉夫,

8

有时由于PHP的FastCGI中的一些错误而发生。

尝试重新启动它。在Ubuntu,它是:

service php-fastcgi restart

好的,这是一个解决方案,但不能解决问题。就我而言,该问题每月随机出现一两次。:(
SkaJess

@SkaJess-您可以将重新启动命令添加到crontab中以每小时重新启动一次。脏-但会确保您的网站的最大停机时间为1小时。
luchaninov

@how-对我来说,这不是一个好的解决方案,因为php在工作日内下降。我认为,我每天晚上都会添加重新启动命令的一种方式。在第二种方式中,我将考虑升级IIS和PHP。
SkaJess

6

我在使用autoload类似的东西时遇到了同样的问题:

<?php

function __autoload($class_name)
{
    include $class_name . '.php';
}


__autoload("MyClass1");

$obj = new MyClass1();

?>

在其他班级有:

namespace testClassNamespace;


class MyClass1
{

    function  __construct()
    {
        echo "MyClass1 constructor";
    }
}

解决方案是namespace testClassNamespace;在两个文件中都保持名称空间兼容性。


3

只是添加;

如果您错误地将一个函数放在另一个函数中,也会发生此错误。


3

PHP 5.3(我认为也是旧版本)似乎在不同情况下具有相同名称的问题。因此,当一个类具有Login和它实现LogIn的接口时,我遇到了这个问题。将LogIn重命名为Log_In之后,问题得到解决。


3

只要您包含或需要文件名(即class.login.php),就只需做一件事。您可以这样包含它:

include_once class.login.php or 
require_once class.login.php

这样,它永远不会抛出错误。


2

此函数将打印一个堆栈,告诉您从何处调用它:

function PrintTrace() {
    $trace = debug_backtrace();
    echo '<pre>';
    $sb = array();
    foreach($trace as $item) {
        if(isset($item['file'])) {
            $sb[] = htmlspecialchars("$item[file]:$item[line]");
        } else {
            $sb[] = htmlspecialchars("$item[class]:$item[function]");
        }
    }
    echo implode("\n",$sb);
    echo '</pre>';
}

在包含您的类的文件的顶部调用此函数。

有时,即使您的班级被包括两次或多次,它也只会打印一次。这是因为PHP实际上在执行任何代码之前会解析文件中的所有顶级类,并立即引发致命错误。为了解决这个问题,请将您的类声明包装在中if(true) { ... },这将使您的类在范围上下移。然后,应该在发生PHP致命错误之前得到两条跟踪记录。

这应该可以帮助您从一个复杂的项目中多次查找您的班级所在的位置。


1

您是否使用过Zend Framework?我也有同样的问题。
我通过将以下行注释掉来解决了它config/application.ini

;includePaths.library = APPLICATION_PATH "/../library"

我希望这能帮到您。


1

另一个可能的罪魁祸首是源代码控制和未解决的冲突。SVN可能导致同一类在冲突的代码文件中出现两次;它的两个替代版本(“我的”和“他们的”)。


1

我遇到了同样的问题:较新的php版本在处理同一个文件的多个包含项时(作为库)不能处理相同的问题,因此现在我必须通过include_once更改所有包含。

如果您的图书馆没有太多的课,或者这招可能会有所帮助...

if( class_exists('TestClass') != true )
{
   //your definition of TestClass
}

1

我遇到了同样的问题“ PHP致命错误:无法重新声明类XYZ.php”。

我有两个目录,例如controllermodel,我在两个目录中都错误地上传了XYZ.php。(因此,文件名相同会导致问题)。

第一个解决方案:

查找整个项目,并确保只有一个类XYZ.php。

第二种解决方案:

在您的类中添加一个名称空间,以便您可以使用相同的类名。


0

我遇到了同样的问题。发现案件是班级名称。我通过更改名称来处理它。因此解决了这个问题。


0

实际上,这意味着该类已经在页面中声明,并且您正在尝试重新创建它。

一种简单的技术如下。

我用以下方法解决了这个问题。希望这会对您有所帮助。

if(!class_exists("testClassIfExist"))
{
    require_once("testClassIfExist.php");
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.