PHP中的全局变量无法正常工作

时间:2012-08-10 03:18:14

标签: php variables scope global-variables

我需要从函数$layers内部访问isOk($layer),但我尝试外部函数变量$layers的所有内容都可以,但在函数内部,即使使用global也返回null。

以下是代码:

$layers = array();
foreach($pcb['PcbFile'] as $file){
    if(!empty($file['layer'])){
        $layers[$file['layer']] = 'ok';
    }
}
// Prints OK!
var_dump($layers);

function isOk($layer){
    global $layers;
// Not OK! prints NULL
    var_dump($layers);
    if(array_key_exists($layer, $layers))
        return ' ok';
    return '';
}
// NOT OK
echo isOk('MD');

我总是使用面向对象,但这很简单,我用一个简单的函数制作...为什么$layers没有在函数内被“接收”?

2 个答案:

答案 0 :(得分:3)

注意这个......

HalfAssedFramework.php

<?php
class HalfAssedFramework {
    public static function run($path) {
        include $path;
    }
}

HalfAssedFramework::run('example.php');

使用example.php

<?php

$layers = array();
foreach($pcb['PcbFile'] as $file){
    if(!empty($file['layer'])){
        $layers[$file['layer']] = 'ok';
    }
}
// Prints OK!
var_dump($layers);

function isOk($layer){
    global $layers;
// Not OK! prints NULL
    var_dump($layers);
    if(array_key_exists($layer, $layers))
        return ' ok';
    return '';
}
// NOT OK
echo isOk('MD');

直接运行example.php,它应该可以运行。运行HalfAssedFramework.php,但不会。

问题在于范围。当example.php函数中包含run时,其中的所有代码都会继承函数的作用域。在该范围内,$layers默认情况下不是全局的。

要解决此问题,您可以选择以下几种方法:

  • 如果您知道example.php永远不会直接投放,您可以在文件开头说global $layers;。但是,如果脚本直接运行,我不确定这是否会起作用。
  • $layers替换为$GLOBALS['layers']无处不在。
  • $layers作为参数添加到isOk
  • 将此代码放在一个类中,如suggested by Geoffrey

答案 1 :(得分:2)

不完全回答这个问题,但您是否考虑使用全局变量 ? Globals真的不那么酷:它们使你的代码更难阅读,更难理解,因此更难维护。

考虑类似的事情:

<?php

class LayerCollection
{
    private $layers;

    public function __construct($layers)
    {
        $this->layers = $layers;
    }

    public static function fromPcbFile($data)
    {
        $layers = array();

        foreach ($data['PcbFile'] as $layer) {
            if (!empty($layer)) {
                $layers[$layer] = true;
            }
        }

        return new self($layers);
    }

    public function hasLayer($layer)
    {
        return array_key_exists($layer, $this->layers);
    }
}

$layers = LayerCollection::fromPcbFile($pcb);
var_dump($layers->hasLayer('MD'));

它看起来不是更好吗?然后,您可以继续丰富LayerCollection,因为您需要更多与图层互动的方式。这并不完美,因为有still静态方法(使测试更难,工厂更适合这项工作),但这是重构的良好开端。

更多关于全局变为邪恶的原因:https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil