PHP 中的全局变量不起作用


Global variable in PHP is not working

我需要从函数isOk($layer)内部访问$layers,但是我尝试的所有外部函数变量都可以$layers,但是在函数内部,即使使用全局也返回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在函数内部没有被"接收"?

看这个...

半屁股框架.php

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

示例.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;。 不过,如果直接运行脚本,我不确定这是否有效。
  • 随处$GLOBALS['layers']替换$layers
  • $layers作为参数添加到 isOk
  • 按照 Geoffrey 的建议,将此代码放在类中。

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

考虑这样的事情:

<?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