PHP require_once被多次调用

时间:2018-05-29 02:09:14

标签: php iis php-7

我发布了解决方案作为答案

我在将一些PHP代码迁移到新服务器时遇到了一个奇怪的问题。旧服务器运行PHP 5.3(x86),新服务器运行PHP 7.0(x64)。两者都在IIS 7.5上运行。

导致问题的代码已经生产了近三年没有问题。它在当前的生产服务器以及两个开发系统上运行良好。这三个都运行PHP 5.3(x86)。

当我在新服务器上使用PHP 5.3(x86)时,不会发生这些错误。

共享文件(名为_common_funcs.php)包含从许多脚本调用的常用函数。由于其中一些脚本可以交互,因此我使用require_once(' _common_funcs.php')来包含该文件。这是非常基本的方法。

在新服务器上,第一次一个脚本运行它会生成一个'无法重新声明'错误。刷新页面不会显示错误 - 它会按预期显示页面。例如:

  • // localhost / app / display_account.html?account = 123456生成错误。
  • // localhost / app / display_account.html?account = 123456再次显示错误。

重新启动IIS服务器会导致在第一次运行时再次生成错误。

现在是奇怪的部分。请注意以下错误中驱动器号的大小写:

Cannot redeclare acct_has_graduated() (previously declared in D:\app_directory\includes\_common_funcs.php:2061) in d:\app_directory\includes\_common_funcs.php on line 2061

如果我在一个require_once()行中硬编码完整路径,并使用小写' d',则日志中的错误将交换大小写。结果是&#d; \ app ...'和' D:\ app ...'。

如果我对这个脚本运行时遇到调用的两个调用进行硬编码,那么无论我使用何种大小写混合都不会生成错误。

为了使这更有趣,acct_has_graduated()函数是_common_funcs.php文件中的最后一个函数。但如果我在php.ini中禁用OpCache,我会收到以下错误:

Cannot redeclare update_ledger() (previously declared in D:\app_directory\includes\_common_funcs.php:7) in d:\app_directory\includes\_common_funcs.php on line 42

需要注意两点:update_ledger()是_common_funcs.php文件中的第一个函数,"第42行"是update_ledger()函数的结束括号(第7行是声明)。

如果有人能指出我正确的方向,我会非常感激。

2 个答案:

答案 0 :(得分:2)

解决方案

我发现了问题,文件绝对被包含两次。这是在特定情况下发生的。它会影响PHP 7.0,但不会影响PHP 5.3。我没有测试任何其他版本的PHP。

这种情况肯定是一个异常值,但现在是:

  1. 我有一个目录符号链接,从c:\ inetpub \ wwwroot \ app_location到d:\ app_location。
  2. 此站点的IIS配置指向c:\ inetpub \ wwwroot \ app_location。
  3. 应用程序的配置文件使用c:\​​ inetpub \ wwwroot \ app_location作为基础来定义include_path。
  4. 此网站的所有文件均位于d:\ app_location。
  5. 使用上面的配置,应用程序日志文件中的所有条目(跟踪,审核,错误和回溯)都会将 D:\ app_location 显示为所有文件的基本位置。

    多次调用文件require_once(),同时允许include_path解析一个或两个调用中文件的位置,生成'无法重新声明&#39 ;错误。该错误报告了“D:”的相反大写字母:'驱动器号(请参阅上面帖子中的错误文本)。

    将include_path(上面的#3)的基础更改为d:\ app_location解决了此问题。

答案 1 :(得分:-1)

问题很简单。

require_once('D:\file.php');
require_once('file.php');

会运行两次,因为你包含了绝对路径!

解 使用相对路径

require_once('../core/file.php');