我已经自动加载了一个正确命名空间和PSR-0的类。我把它放在app / lib / CI中,类和它的文件名是相同的“DB”。类文件本身包含实际类之前的配置文件:
require( 'config.php' );
class DB {
// ...
}
该类显然是自动加载的,因为当我调用静态方法connect时,它会显示来自:: connect()内部的错误消息。问题是,包含的config.php中的全局变量在class :: method中不可用。
因此,要清楚,数组$ connection_settings在config.php中,但即使使用:
global $connection_settings;
$ connect_settings未在connect方法中设置。
有趣的是,即使该类是自动加载的,如果我在routes.php文件的顶部包含该类,一切正常。那么,我不能正确地按照我认为“正常”的方式进行自动加载?
答案 0 :(得分:8)
这是Composer而不是Laravel的问题。 Composer尽一切努力在自动加载期间不污染全局范围(在#1297中简要讨论)。如果你想强制全局变量,那么你应该在配置文件中以及使用它们的任何函数中将它们声明为全局变量。
在函数外部使用全局关键字不是错误。如果文件包含在函数内部,则可以使用它。
以下代码适用于我(使用PHP 5.4.13上的Laravel 4b4)。删除全局行会破坏代码(以不同的方式)。
global $connection_settings;
$connection_settings = array(/* ... */);
require 'config.php';
class DB {
static function connect()
{
global $connection_settings;
// Do something with $connection_settings
}
}
答案 1 :(得分:1)
这与Laravel 或 Composer无关,而与自动加载机制无关。 Phill Sparks' great answer已经指出了使用自动加载功能包含文件的细微但至关重要的区别,这是理解和解决问题的关键:
在函数外部使用全局关键字不是错误。如果文件包含在函数内部,则可以使用它。
当您通过spl_autoload_register()
使用自动加载功能时,include
发生在自动加载程序功能的内部。因此,在包含的文件正文中声明的所有变量不具有全局作用域,与您的config.php
vars相同。
因此,尽管您可以在DB.php
主体中访问此类var,但内部的类和函数将无法使用它们。这就是为什么在global
内使用connect()
无效的原因:因为这样的var首先并不是真正的全局变量!
因此,您需要在声明它们的相同范围内(在global
或DB.php
上使用config.php
使它们成为全局 first )和 then 使用global
内的connect()
再次访问此类变量。
一个简单的例子:
test.php
:
<?php
spl_autoload_register(function ($class) {
require(__DIR__.'/'.$class.'.php');
});
$foo = new Foo();
var_dump($foo->bar());
Foo.php
:
<?php
global $foobar;
$foobar = "just a test";
class Foo
{
function bar() {
global $foobar;
return $foobar;
}
}
它可以完美工作并打印just a test
。第一个global
放置 $foobar
在全局范围内,第二个 access 它。删除任何一个 都会破坏代码,第一个遗漏是“邪恶的”,因为它将无错误地打印NULL
。