【问题标题】:Variable scope: require_once doesn't load my variable, but require does变量范围:require_once 不会加载我的变量,但 require 会
【发布时间】:2016-05-23 22:45:59
【问题描述】:

我知道这很愚蠢,但我想不通。 我在 MVC 框架的上下文中发现了一些类似的questions。 这也是我的情况,因为我正在使用 CodeIgniter。

我有一个文件questions.php(包含在视图中):

require_once '../site_init.php';

var_dump($siteVars);
// shows null and a Notice: Undefined variable: siteVars
// but the ABSPATH constant is showing as defined!
var_dump(ABSPATH);
// shows string 'c:\wamp\www\sitename'

require '../site_init.php';
var_dump($siteVars);
// correctly dumps the content of siteVars array

还有一个文件site_init.php 应该包含在任何地方,因为它包含我的站点范围的配置值:

if ( !defined('ABSPATH') )
        define('ABSPATH', dirname(__FILE__) . '/');

/** Site-wide sitevars */
$siteVars = array();

// set to true in develop environment
$siteVars['debug'] == false;

我知道The require_once statement is identical to require except PHP will check if the file has already been included, and if so, not include (require) it again 但是,当我使用require_once 时,我收到一条通知说Undefined variable: siteVars,而使用require 时,一切正常。但是,正如您在上面的代码中看到的那样,常量显示为已定义,尽管它们都定义在同一个文件中。 PHP manual:Like superglobals, the scope of a constant is global. You can access constants anywhere in your script without regard to scope.

print_r(get_included_files()); 表明 site_init.php 在 require_once 之前包含,所以我不必再 require(_once) 它。

它必须与变量范围有关。如果我使用global $siteVars,它可以工作,不需要再次require 文件,但是有人可以解释为什么会发生这种情况吗?我是 CodeIgniter 的新手。我可以看到只有一个入口点(主 index.php 文件),那就是基本文件($_SERVER['PHP_SELF'])。

理想情况下,我还想知道如何在不使用globalrequire 的情况下解决此问题。

更新: 文件结构似乎如下(这是一个我只是在做的项目,我不是最初的开发者):

  • 控制器 welcome.php 在 CodeIgniter 应用程序文件夹结构(CI 应用程序是更大站点的管理部分)之外加载(包含一次)文件 X。

  • 文件 X 包含一次 site_init.php 文件

  • 控制器welcome.php加载视图$this->load->view('template', $data);

  • 差不多就是这样。希望这是解决问题的关键。

【问题讨论】:

  • stackoverflow.com/a/2418514/3599549。该页面之前是否已包含在内?
  • 奇怪,我在这里测试了 2 个文件,使用了 require 和 require_once,两次都成功了。我能够打印变量的内容。
  • 你的 php 版本是多少?我觉得codeigniter与此无关。似乎是命名空间问题,但这样说很奇怪......
  • 我在问题中链接到的问题解释说它与范围有关,@​​987654343@ 解决了这个问题的事实证明这是一个范围问题。你是如何测试的,你有codeigniter安装吗?我也应该给你我的文件夹结构,这样你就可以复制了。
  • imo,很明显你的site_init.php 被执行在错误的地方。它需要在顶级脚本(index.php?)上执行,而不是从 CI 中的任何地方执行。目前$siteVars 变量是going out of scope 并在创建后不久被删除;-/ 如何解决它。 1)将脚本移动到顶层; 2) 将SiteVars 声明为singleton 类。 3) 将其分配为 CI 框架的属性?即$this->siteVars = array();等。

标签: php codeigniter


【解决方案1】:

在 CodeIgniter 中,视图中唯一可访问的变量是从控制器传递给它的。绝不应该有理由在 COdeIgniter 中以这种方式包含任何内容

控制器:

$d['title'] = 'title';    
$this->load->view('main',$d);

查看:

<?php print $title;?>

请参阅 Config Class http://www.codeigniter.com/user_guide/libraries/config.html 了解自定义配置值,然后可以在控制器中访问这些值并传递给视图

【讨论】:

  • 谢谢马特,我认为您的回答是解决问题的关键。如果我能做到,我会更新。
  • 嗨,马特,我用更多信息更新了这个问题,你能看一下,也许它可以帮助你更确定问题是什么?
  • @bg17aw I 所以你确实可以访问控制器welcome.php中的变量,但不能访问视图?
  • 是的,既然你问了。它们在控制器中可用。我对 CI 没有太多经验。
  • @bg17aw 加载视图时,第二个参数是将值或变量传递到视图的数组:在控制器中 $d['siteVars'] = $siteVars; $this->load->view('viewname',$d);现在可见 $siteVars 将可用
【解决方案2】:

这是一个逻辑问题,范围只是帮助你看到它。这是它的关键:

print_r(get_included_files()); 表明 site_init.php 在 require_once 之前包含,所以我不必再次 require(_once) 它。

这表示您之前已经包含了该文件,因此当您再次尝试时,require_once() 不会执行任何操作。不是require_once()“不加载你的变量”,它只是做了它应该做的——避免包含你已经加载的文件。
显然,require() 不关心这种情况,它重新包含脚本,因此在您当前的范围内导入所述变量。

无论如何,一次又一次地包含脚本是一种将数据放入当前范围的可怕方法。您应该学习如何使用函数参数传递数据。

【讨论】:

  • 您只是在重新制定我自己的陈述,我已经知道我完全知道该文件已包含在内,并且 require_once 没有做任何事情。但是,我不认为包含站点范围的初始化文件是一个坏主意,这一次,初始化文件包含debug 开关、根路径和类似的东西。就像 WordPress 中的 wp-config.php 文件。
  • 你不是在问为什么它什么都没做吗?我就是这么解释的。
  • 我可能遗漏了一些东西,我看不出你是如何回答这个问题的。如果您阅读了我链接到的类似问题的答案,那么有一个正确的方向,因为这与 MVC 框架结构有关。
  • 嗯,我不太清楚你不明白什么,所以我无法进一步澄清。但有一件事是肯定的——它与 MVC 无关,也与 CodeIgniter 无关。
  • 我不明白你为什么认为发生了一些“可怕的”事情,你还认为我不知道如何使用参数传递数据,而你的回答在任何方面都没有建设性。您还说“肯定不是 MVC 框架”,经验丰富的编码器/stackoverflow 用户可能会使用“我非常怀疑”这样的东西。永远不要把话说绝了。我更新了问题以更好地表明在同一文件中定义的常量是可以的,它只是显示为未定义的变量。请停止假设。
猜你喜欢
  • 1970-01-01
  • 2016-05-12
  • 2012-02-08
  • 2018-04-25
  • 2015-12-25
  • 2017-09-28
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多