dsafew1231 2011-10-29 20:07
浏览 95
已采纳

在PHP中处理include / require指令

Background: I'm building an automated test framework for a PHP application, and I need a way to efficiently "stub out" classes which encapsulate communication with external systems. For example, when testing class X that uses DB wrapper class Y, I would like to be able to "swap in" a "fake" version of class Y while running automated tests on class X (this way I don't have to do full setup + teardown of the state of the real DB as part of the test).

Problem: PHP allows "conditional includes", which means basically that include/require directives are handled as part of processing the "main" logic of a file, e.g.:

if (condition) {
    require_once('path/to/file');
}

The problem is that I can't figure out what happens when the "main" logic of the included file calls "return". Are all of the objects (defines, classes, functions, etc.) in the included file imported into the file which calls include/require? Or does processing stop with the return?

Example: Consider these three files:

A.inc

define('MOCK_Z', true);
require_once('Z.inc');
class Z {
    public function foo() {
        print "This is foo() from a local version of class Z.
";
    }
}
$a = new Z();
$a->foo();

B.inc

define('MOCK_Z', true);
require_once('Z.inc');
$a = new Z();
$a->foo();

Z.inc

if (defined ('MOCK_Z')) {
    return true;
}
class Z {
    function foo() {
        print "This is foo() from the original version of class Z.
";
    }
}

I observe the following behavior:

$ php A.inc
> This is foo() from a local version of class Z.

$ php B.inc
> This is foo() from the original version of class Z.

Why This is Strange: If require_once() included all of the defined code objects, then "php A.inc" ought to complain with a message like

Fatal error: Cannot redeclare class Z

And if require_once() included only the defined code objects up to "return", then "php B.inc" ought to complain with a message like:

Fatal error: Class 'Z' not found

Question: Can anyone explain exactly what PHP is doing, here? It actually matters to me because I need a robust idiom for handling includes for "mocked" classes.

  • 写回答

5条回答 默认 最新

  • doudi5291 2012-03-03 22:54
    关注

    I've thought about this for a while now, and nobody has been able to point me to a clear and consistent explanation for the way PHP (up to 5.3 anyway) processes includes.

    I conclude that it would be better to avoid this issue entirely and achieve control over "test double" class substitution via autoloading:

    spl-autoload-register

    In other words, replace the includes at the top of each PHP file with a require_once() which "bootstraps" a class which defines the logic for autoloading. And when writing automated tests, "inject" alternative autoloading logic for the classes to be "mocked" at the top of each test script.

    It will naturally require a good deal of effort to modify existing code to follow this approach, but the effort appears to be worthwhile both to improve testability and to reduce the total number of lines in the codebase.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP