Php 如何在我的类中使用$db而不是$GLOBALS[';db';]?

Php 如何在我的类中使用$db而不是$GLOBALS[';db';]?,php,oop,class,Php,Oop,Class,我需要在我的类中使用$GLOBALS['db']($db在我的index.php中定义),但我不想在必须调用它时使用$GLOBALS['db'] 我在课程开始时编写了以下代码: class ClassName { var $db; public function __construct() { $this->db = $GLOBALS['db']; } public function test() { $v

我需要在我的类中使用
$GLOBALS['db']
$db
在我的index.php中定义),但我不想在必须调用它时使用
$GLOBALS['db']

我在课程开始时编写了以下代码:

class ClassName
{
    var $db;

    public function __construct()
    {
        $this->db = $GLOBALS['db'];
    }

    public function test()
    {
        $val = $this->db->oneValue('SELECT first_name FROM users LIMIT 0, 1');
        echo $val->first_name;
    }
}

但我不喜欢这样;我更喜欢在我的代码中直接使用
$db
。是否有一种解决方案可以通过
$db
调用
$GLOBALS['db']

简单的方法,只需插入构造函数或setter方法:(我假设$db在这里是一个对象,而不是一个连接参数数组等)


正如上面的一些评论所提到的,这是一种依赖注入形式,它将使您能够在项目中重用代码(Good Thing TM)。

我更喜欢在数据库中使用单例模式

这是我在应用程序中使用的DB类

class Database {

    protected static $_dbh;
    const HOST = 'localhost';
    const DATABASE = 'dbname';
    const USERNAME = 'username';
    const PASSWORD = 'password';

    private function __construct() { }

    public static function getInstance() {
        if(!isset($_dbh)) {
            try {
                #Connection String.
                self::$_dbh = new PDO('mysql:host='.self::HOST.';dbname='.self::DATABASE,self::USERNAME,self::PASSWORD);
                self::$_dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            } catch(PDOException $e) {
                #Print Errors.
                echo $e->getMessage();
            }
        }
        return self::$_dbh;
    }
}
由于我使用的是单例模式,连接将被重新使用。您现在可以通过调用静态连接方法,即

class ClassName
{
    protected static $_dbh;

    public function __construct() {
        self::$_dbh = Database::getInstance();
    }

    public function test() {
        $sth = self::$_dbh->query('SELECT first_name FROM users LIMIT 0, 1');
        $row = $sth->fetchAll(PDO::FETCH_ASSOC);
        echo $row['first_name'];
    }
}

这完全是反模式。考虑使用IoC/DI:
公共函数uuu构造($db){$this->db=$db;}
OP并没有真正解释为什么他必须使用$GLOBAL,即使是一个全局单例也不会那么邪恶!您不喜欢coinstructor中的这个调用,或者不喜欢$this->db而不是$db?另外,
var
不推荐使用
public | private | protected
谢谢:)。还有@lawrencerone:谢谢,我会的!谢谢你这么快就回答了我的问题。我可以做一些类似于
类ClassName扩展数据库
的事情,并在
数据库
类中设置连接吗?例如,我可以通过
$this->dbOneValue()
访问我的函数。这是一个好主意吗?我个人不喜欢每次我想使用它时都通过构造函数传递参数
$dbh
。你可以让你的类扩展一个泛型DB类,但是当你创建一个新的
类名时你仍然需要显式设置
$DB
,因为PHP使用经典继承,不像Javascript那样是原型。您在泛型DB类中创建的所有函数都可以在“ClassName”类中访问。这有帮助吗?@Ibrahimazharmar,这是工厂和DI容器、服务定位器等可以派上用场的地方,但它们有点超出了问题/答案的范围。我建议在您的构造中移动
setConnection
,并通过$db by refSINGLETON反模式使用警报。。。这使您无法在不更改代码的情况下(重新)配置数据库连接,并且还将您限制为仅使用一个连接(不一定是坏事),除非您将其复制粘贴到另一个singleton类中(从而断开连接)。此外,这意味着您正在将数据库凭据放入源代码管理,这应该避免。同样,使用单例进行单元测试也是一场噩梦。@JamesButler:2011年使用单例进行单元测试不是一场噩梦;别再重复那些老掉牙的废话了。好吧,没错,在“后期静态绑定”之前的时代,这是一场噩梦,但是很多托管公司还没有超越PHP5.2,我觉得OP很可能会受到这些考虑的限制,我不确定是否有人在应用程序中使用或创建了多个数据库连接,除非他们有充分的理由这样做。我猜OP使用全局变量
$GLOBALS['db']
也是出于同样的原因。
class ClassName
{
    protected static $_dbh;

    public function __construct() {
        self::$_dbh = Database::getInstance();
    }

    public function test() {
        $sth = self::$_dbh->query('SELECT first_name FROM users LIMIT 0, 1');
        $row = $sth->fetchAll(PDO::FETCH_ASSOC);
        echo $row['first_name'];
    }
}