在PHP中处理include / require指令 [英] Processing include/require directives in PHP

查看:137
本文介绍了在PHP中处理include / require指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

后台:
我正在为PHP应用程序构建一个自动化测试框架,我需要一种有效的方法stub out类封装了与外部系统的通信。例如,当测试使用DB包装器类Y的类X时,我希望能够在类X上运行自动化测试时交换类Y的假版本(这样我就不必这样做了)完全设置+拆除真实数据库的状态作为测试的一部分。)

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).

问题:
PHP允许有条件的包括,这意味着include / require指令基本上是作为处理文件主逻辑的一部分处理的,例如:

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');
}

问题是我无法弄清楚当包含文件的逻辑调用return。是否将所包含文件中的所有对象(定义,类,函数等)导入到调用include / require的文件中?或处理是否停止返回?

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.\n";
    }
}
$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.\n";
    }
}

我观察到以下行为:

$ 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.

为什么这是奇怪的:
如果require_once()包含所有已定义的代码对象,那么php A.inc应该

Fatal error: Cannot redeclare class Z

如果require_once()仅包含定义的代码对象,直到返回,那么php B.inc应该抱怨如下消息:

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

问题:
有人能解释完全 PHP在做什么吗?它实际上对我很重要,因为我需要一个强大的习惯用于处理包括模拟类。

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.

推荐答案

我想过现在已经有一段时间了,没有人能够指出我对PHP(最终5.3)流程包括的方式的清晰一致的解释。

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

换句话说,替换顶部的包含每个带有require_once()的PHP文件,它引导一个定义自动加载逻辑的类。在编写自动化测试时,注入替代自动加载逻辑,以便在每个测试脚本的顶部模拟类。

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.

这篇关于在PHP中处理include / require指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆