在函数内部访问配置的最佳实践是什么?

4
<?php
define('ABSPATH', dirname(__FILE__)); //Absolute path to index

/*
* Method 1
* Dependency Injection
*/
class Config{

    private $_config = NULL;
    private $_filepath = NULL;

    public function __construct($filepath){
        $this->_filepath = $filepath;
        $this->load();
    }

    private function load(){
        if ($this->_config === NULL){
            if (!file_exists($this->_filepath)){
                throw new Exception('Configuration file not found');
            }else{
                $this->_config = parse_ini_file($this->_filepath);
            }
        }
    }

    public function get($key){
        if ($this->_config === NULL){
            throw new Exception('Configuration file is not loaded');
        }
        if (isset($this->_config[$key])){
            return $this->_config[$key];
        }else{
            throw new Exception('Variable ' . $key . ' does not exist in configuration file');
        }
    }
}

function getLost($where, $why, $who){
    //do smth
}

try{
    $config = new Config(ABSPATH . '/app/config.ini');
    getLost('here', 'because', $config->get('who'));    
}catch(Exception $e){
    echo $e->getMessage();
}
?>

<?php
/*
* Method 2
* Config is accessed via static class
*/

class Config{

    private static $_config = NULL;
    private static $_filepath = NULL;

    public static function load($filepath){
        if (self::$_config === NULL){
            self::$_filepath = $filepath;
            if (!file_exists(self::$_filepath)){
                throw new Exception('Configuration file not found');
            }else{
                self::$_config = parse_ini_file(self::$_filepath);
            }
        }
    }

    public static function get($key){
        if (self::$_config !== NULL){
            throw new Exception('Configuration file is not loaded');
        }
        if (isset(self::$_config[$key])){
            return self::$_config[$key];
        }else{
            throw new Exception('Variable ' . $key . ' does not exist in configuration file');
        }
    }
}

function getLost($where, $why){
    $who = Config::get('who');
}

try{
    Config::load(ABSPATH . '/app/config.ini');
    getLost('here', 'because');    
}catch(Exception $e){
    echo $e->getMessage();
}
?>

<?php
/**
* Method 3
* Config variable needed is passed as function parameter
*/
$config = parse_ini_file(ABSPATH . '/app/config.ini');

function getLost($where, $why, $who){
    //do smth
}

getLost('here', 'because', $config['who']);
?>

<?php
/*
* Mathod 4
* Config is accessed inside a function via global
*/
$config = parse_ini_file(ABSPATH . '/app/config.ini');

function getLost($where, $why){
    global $config;
    $who = $config['who'];
}

getLost('here', 'because');
?>

哪个方案最符合最佳实践?如果没有,请提供您的方案。
2个回答

2
我认为第一种情况更好,如果你将$config替换为$onlyTheStuffThatMattersToThatFunction。

1
不是回答问题,但我必须+1,因为你说得很对,这是目前唯一明智的答案 :) - user895378

2
我会选择第一种方式(依赖注入)。
第二种方式使用了静态方法,就像之前所说的另一种全局方法。我们都知道这是不好的,对吧?对吧?
第三种方式并不是我最喜欢的,因为它不够面向对象;但是认真地考虑一下:如果您(或使用您代码的人)想要更改配置文件的格式怎么办?
第四种方式:全局...
因此,我的问题基本上是:可测试性、紧密耦合、全局。
所以我选择第一种方式。我还会为配置类创建一个接口,这样您可以在以后添加一个不同的类来处理配置信息。例如,您(或别人)想要使用 XML 文件来进行配置。
另一件我会改变的事情是私有变量的定义。如果有人想要扩展这个类,他/她将无法访问到这些变量。我的原则是(虽然不确定每个人是否都同意):只有当你想让别人访问它们时(例如,它们将在某些时候被更改),才将变量定义为私有。使用私有的危险是,人们可以通过黑客技术绕过它以实现他们想要的功能。
阅读更多关于SOLID的内容,并查看 Google clean code 的演讲以获取更多信息。

Just my 2 cents.


2
我并不完全同意一概而论地立即放弃“private”的说法。并非所有算法都应自动受到子类修改的影响。组合通常比继承更可取。明智地使用“protected”可以在很大程度上保持黑盒的“黑色”。话虽如此,点赞+1 :) - user895378

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接