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 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化