Laravel 4:为什么我的类自动加载但全局变量不可用

问题描述 投票:0回答:3

我已经自动加载了一个类,该类具有正确的命名空间和 PSR-0。我把它放在app/lib/CI中,类和它的文件名是相同的“DB”。类文件本身在实际类之前包含一个配置文件:

require( 'config.php' );

class DB {
  // ...
}

该类显然是自动加载的,因为当我调用静态方法 connect 时,它确实会从 ::connect() 内部显示一条错误消息。问题是,包含的 config.php 中的全局变量在 class::method 中不可用。

因此,需要明确的是,数组 $connection_settings 位于 config.php 内部,但即使使用时:

global $connection_settings;

$connection_settings 未在 connect 方法内设置。

有趣的是,即使该类是自动加载的,如果我从routes.php 文件顶部包含该类,一切都会正常工作。那么,为了让自动加载按照我认为的“正常”方式工作,我做错了什么?

laravel laravel-4
3个回答
10
投票

这是 Composer 的问题,而不是 Laravel 的问题。 Composer 尽一切努力在自动加载期间不污染全局范围(在#1297中简要讨论)。如果您想强制使用全局变量,那么您应该在配置文件以及使用它们的任何函数中将它们声明为全局变量。

PHP 手册 说:

在函数外部使用 global 关键字不是错误。如果该文件包含在函数内部,则可以使用它。

下面的代码适用于我(在 PHP 5.4.13 上使用 Laravel 4b4)。删除任一全局行都会破坏代码(以不同的方式)。

配置.php

global $connection_settings;
$connection_settings = array(/* ... */);

数据库.php

require 'config.php';
class DB {
    static function connect()
    {
        global $connection_settings;
        // Do something with $connection_settings
    }
}

5
投票

这与 Laravel Composer 没有任何关系,而是与 自动加载机制有关。 Phill Sparks 的出色答案已经指出了使用自动加载包含文件的微妙但至关重要的区别,这是理解和解决问题的关键:

PHP 手册 说:

在函数外部使用 global 关键字不是错误。如果该文件包含在函数内部,则可以使用它。

当您通过

spl_autoload_register()
使用自动加载时,
include
发生在自动加载器功能中内部。因此,在包含的文件主体中声明的任何变量都具有全局范围,对于您的
config.php
变量来说也是如此。

因此,虽然您可以在

DB.php
主体中访问此类变量,但它们在内部
其类和函数中不可用。这就是为什么在 
global
 内部使用 
connect()

不起作用:因为这样的变量首先并不是真正的全局变量!

因此,您需要先将它们“设为”全局,通过在声明它们的同一范围内使用

global
(在
DB.php
config.php
),然后然后在内部使用
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
置于全局范围内,第二个访问它。删除任一都会破坏代码,第一个遗漏更“邪恶”,因为它将打印
NULL
而没有错误。


0
投票

是的,似乎该文件包含在 PHP 函数中,因此所有定义的变量都仅限于该函数。您需要将它们重新分配到全局范围...

类似的东西

  require_once 'file.php';
  foreach ( get_defined_vars() as $k => $v) {
    $GLOBALS[$k] = $v;
  }
© www.soinside.com 2019 - 2024. All rights reserved.