它是不好的做法,使用全局$配置变量?

问题描述 投票:1回答:2

此刻,我使用称为$config变量,这对于像文件夹的配置,数据库连接,网址应用程序以匹配大缔含阵列设置,等等。此变量在其中得到由主文件system/config.php包括它自己的文件system/index.php定义。

分别位于即system/request.php某些系统功能使通过global $config;此全局配置变量

这是不好的做法,为什么?什么会是一个更好的方式来处理全局配置?

php configuration global-variables
2个回答
0
投票

恕我直言,只要有一个全局变量不simulatenously通过不同的工艺修改(即它是只读的所有的),它是确定有它在全球范围内。

模拟只读变量的方法是用它和一个私有变量,将返回该变量的公共方法来封装它在一个全局对象。

例:

class Config {
    private $conf = array(/*read from file?*/...);

    function getconf() {
        //AFAIK, any attempt to write into the returned array will make PHP's
        //core to duplicate it, so the original config won't be modified
        //(as long as $conf does not contain objects, which are always addressed
        //by reference)
        return $conf; 
    }
} 

0
投票

不知从何处(全局命名空间)中的变量拉不好,因为你不知道他们是如何得到他们的价值,因为每一个类或函数可以改变它们。所以,除非你使用某种形式的最后,常量的,等来保护他们,他们会打破从长远看系统,你会花时间找出他们是如何得到他们的价值观。

for循环的替代解决方案是使用一个容器和依赖注入。

$container = new Container(array(
    'x' => array(
        'a' => 8,
        'y' => array(
            'b' => 123,
            'z' => 456
        )
    )
));
$x = $container->getX();
$x->doSomething();

如果类之间的强耦合,因为你不希望他们是普通的东西,那么你可以这样做:

class Container {

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

    public function getX(){
        return new X($this->$config['x']);
    }

}

class X {
    public function __construct(array $config){
        $this->a = $config['a'];
        $this->y = new Y($config['y']);
    }

    public function doSomething(){}
}

class Y {
    public function __construct(array $config){
        $this->b = $config['b'];
        $this->z = new Z($config['z']);
    }
}

class Z {
    public function __construct($number){
        $this->number = $number;
    }
}

如果这些类是松散耦合的,但你要保持层次的配置(例如,因为你必须在不同的CONFIGS您的容器多个Y和Z的实例),那么你可以这样做:

class Container {

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

    public function getX(){
        return new X($this->$config['x']['a'], $this->getXY());
    }

    public function getXY(){
        return new Y($config['x']['y']['b'], $this->getXYZ());
    }

    public function getXYZ(){
        return new Z($config['x']['y']['z']);
    }

}

class X {
    public function __construct($a, Y $y){
        $this->a = $a;
        $this->y = $y;
    }

    public function doSomething(){}
}

class Y {
    public function __construct($b, Z $z){
        $this->b = $b;
        $this->z = $z
    }
}

class Z {
    public function __construct($number){
        $this->number = $number;
    }
}

即使你没有OOP开发,你应该把你的依赖作为参数,而不是全局变量。

function main($config){
    $x = $config['x'];
    $a = $x['a'];
    $y = $x['y'];
    doXSomething($a, $y);
}

function doXSomething($a, array $y){
    $b = $y['b'];
    $z = $y['z'];
    $p = doY($b, $z);
    // ...
}

function doY($b, $z){
    $q = doZ($z);
    // ...
}

function doZ($z){
    // ...
}


$config = array(
    'x' => array(
        'a' => 8,
        'y' => array(
            'b' => 123,
            'z' => 456
        )
    )
);
main($config);

你的代码应该只依赖于局部变量,所以你可以肯定的是,该应用程序运行时,他们没有从不同的功能改变。

使用全局变量的另一个原因是糟糕的可测试性。如果你写一个测试的功能,那么你必须设置一个配置变量。如果深度嵌套的,那么你这样做

$config = array('x' => array('y' => array('z' => 123)))`;
$result = doZ();
expect($result)->toBe(435);

如果没有全局变量,你可以做

$result = doZ(123);
expect($result)->toBe(435);

基于文件的名字,我想你当时5年前有某种的意大利面条代码。

© www.soinside.com 2019 - 2024. All rights reserved.