PHP - require_once 和类继承问题
Posted
技术标签:
【中文标题】PHP - require_once 和类继承问题【英文标题】:PHP - require_once and class inheritance issue 【发布时间】:2013-09-10 23:48:58 【问题描述】:我收到一个致命错误:Fatal error: Class 'Foo1' not found in .../Foo2.php on line 5
包含以下文件:
index.php:
<?php
require_once("./Foo1.php");
?>
<h1>Success</h1>
Foo1.php:
<?php
require_once('./IFoo.php');
require_once('./Bar.php');
class Foo1 implements IFoo
/** @var Bar */
private $bar;
IFoo.php:
<?php
interface IFoo
Bar.php:
<?php
require_once('./Foo2.php');
class Bar
/** @var Foo2 */
private $foo;
Foo2.php:
<?php
require_once("./Foo1.php");
class Foo2 extends Foo1
问题:
-
如何解决这种情况?
为什么当我禁止
implements IFoo
语句时,这段代码可以工作?
更新 大多数提出的解决方案都涉及自动加载。不幸的是,我的问题出在一个有很多现有代码和很多不良做法的旧项目上。我们离 PSR-0 标准还差得很远。
在性能方面引入自动加载的成本是多少?
【问题讨论】:
【参考方案1】:-
使用autoloading 功能。不要在具有类定义的文件中添加任何其他可执行代码(如
require
/ include
)。
因为Foo1
实现IFoo
时,php对IFoo
一无所知,所以无法注册类Foo1
。由于没有注册自动加载器,php 开始解释代码,省略 Foo1.php
中的类声明,直到包含和解析其他文件。当它到达Foo2.php
时,它不包括Foo1.php
(由于require_once
)并开始解释文件-在这里它遇到类Foo1
,由于当时不存在接口实现,因此跳过了定义。此时 php 不知道 Foo1 是在已经需要的Foo1.php
中声明的,因为它没有机会完全解释这个文件。
【讨论】:
1. autoloading 可能是一个解决方案,但我有点犹豫是否要介绍它的使用,因为我不知道对性能的影响。 2.“因为当Foo1实现IFoo时,php对IFoo一无所知”——我不明白,因为在Foo1.php中首先包含的是IFoo... 包含但不解析,因为它实现了未知接口,所以不是注册已知类,而是逐行执行文件,深入require_once
。至于性能,there is no reason not to autoload【参考方案2】:
如果你把Foo1.php文件修改成这个
<?php
require_once('./IFoo.php');
class Foo1 implements IFoo
/** @var Bar */
private $bar;
require_once('./Bar.php');
?>
这行得通。
原因是 PHP 是解释型语言(解释器逐行执行脚本)。 因此,在您的情况下,解释器错过了 Foo1 声明语句,并在遇到 Foo2.php 中未定义的类 Foo1 时引发错误。
【讨论】:
有趣的命题...这是否意味着管理包含的最佳方法首先是类将实现的父级或接口。并在类之后,包括运行时使用的其他类?【参考方案3】:我建议使用Autoloading Standard PSR-0。它描述了自动加载器互操作性必须遵守的强制性要求。
无论如何,在这种情况下:
Foo1.php
您包括Bar.php
,并且因为这条线:require_once('./Foo2.php');
,Class Foo2
扩展Class Foo1
。但是Foo1
类还没有定义!只有在它的定义之后,你才能扩展一个类。
所以看来require_once('./Foo2.php');
不应该在Bar.php
中。或者你应该在class Foo1
定义之后移动require_once('./Bar.php');
。
<?php
require_once('./IFoo.php');
class Foo1 implements IFoo
/** @var Bar */
private $bar;
require_once('./Bar.php');
【讨论】:
感谢这两个提议。请参阅我的问题更新。因此,如果我不想使用自动加载,解决方案是首先导入类声明所需的类。并在实现之后,包括运行时需要的其他类...? @AlbanSoupper 如果您不想使用自动加载,您真正关心的是:在定义之前不要扩展或不要创建新的类实例。因为php
逐行解释脚本。
@AlbanSoupper 在单独的文件中定义每个Class
或Interface
,require_once
只需要当前类的接口或类。对你有很大帮助。以上是关于PHP - require_once 和类继承问题的主要内容,如果未能解决你的问题,请参考以下文章