Php 如何使用从一个类到另一个类的连接

Php 如何使用从一个类到另一个类的连接,php,mysql,mysqli,pdo,connection,Php,Mysql,Mysqli,Pdo,Connection,现在在每个需要数据库连接的类中 class Database { public $isConn; private static $_instance = null; private $datab; // connect to db public function __construct($username = "root", $password = "", $host = "localhost", $dbname = "market", $option

现在在每个需要数据库连接的类中

class Database {

    public $isConn;
    private static $_instance = null;
    private $datab;

    // connect to db
    public function __construct($username = "root", $password = "", $host = "localhost", $dbname = "market", $options = []) {
        $this->isConn = TRUE;
        try {
            $this->datab = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
            $this->datab->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->datab->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            throw new Exception($e->getMessage());
        }
    }

    public static function getInstance() {
        if (!isset(self::$_instance)) {
            self::$_instance = new Database();
        }
        return self::$_instance;
    }
现在它给我一个错误,说不能使用$this,那么我如何使用self::?? }


现在我如何在静态函数和非静态函数中同时使用它

我在我的应用程序中已经这样做了很长时间了。虽然对所选数据库驱动程序的yes调用实际上也是简单的函数——它们是具有大量重复参数(login/db info/etc)的函数

我使用的是sqlsrv,但同样的技术可以根据需要进行修改

db.class.php:

class test {

    private $_db = null;

    public function __construct() {
        $this->_db = Database::getInstance();
    }

    public function test(){
       return $this->_db->getRow("SELECT * FROM users", PDO::FETCH_ASSOC, []);
    }

   public static function testStatic(){
        return $this->_db->getRow("SELECT * FROM users", PDO::FETCH_ASSOC, []);
        }
然后,无论我在哪里需要数据库句柄: somefile.php:

class db{
    private static $_server='my.database.server';
    private static $_config=[ 
                  'UID'                  => 'username',
                  'PWD'                  => 'password',
                  'Database'             => 'myDatabase',
                  'CharacterSet'         => 'UTF-8',
                  'ApplicationIntent'    => 'ReadWrite',
                  'TransactionIsolation' => SQLSRV_TXN_READ_COMMITTED,
                  'APP'                  => 'MyWebApplication",
                  'ConnectionPooling'    => 1,
                  'LoginTimeout'         => 60,
                  'ReturnDatesAsStrings' => 0,
                  'WSID'                 => 'MyWebServer'
              ];

    public static function getDatabaseHandle(){
      return sqlsrv_connect(self::$_server, self::$_config);
    }
}
请注意,这几乎可以是应用程序中的任何地方—在另一个函数或另一个类中—只要您通过静态include或更好地为db.class.php文件提供了可视性,这实际上并不重要

。。。或者从类内,例如:

$db = db::getDatabaseHandle();

$myQuery = sqlsrv_query($db, $tsql, $params);
...

我喜欢@WOLFF给出的直截了当的答案,但我想帮助您解释错误,以便您将来在类似情况下理解

说:

当从对象上下文中调用方法时,伪变量
$this
可用
$this
是对调用对象的引用

但是您试图在静态函数中使用
$this
,因此没有对调用对象的引用。因此,伪变量
$this
未定义

因为不能在静态方法中使用
$this
,所以不能使用任何对象属性,如私有
$this->\u db
。只能在静态方法中使用静态类属性

PHP没有任何自动初始化类的静态属性的方法。唯一的方法是在尝试使用任何其他静态方法之前调用该类的静态初始化方法

class Register {

private static $_db;
public static function checkUserName(){
    if(!self::$_db){
        self::$_db = \db::getDatabaseHandle();
    }
    /**
     * Do database stuff with self::$_db as your database handle
     */

}
我在上面的例子中展示的
init()
静态方法没有什么神奇之处。您可以根据需要命名该方法。在使用依赖于它初始化的东西的其他静态方法之前,您只需要记住自己调用它

那么为什么PHP没有任何神奇的方法来初始化一个类呢?有一个草案建议在PHP中添加一个静态类“构造函数”,但它仍然只是一个草案。它还没有在PHP的任何发布版本中实现。没有办法知道它何时或是否会被实施


PS:FWIW、Python和Java都是具有静态类初始化特性的语言示例

请参见本问题中Python中的示例:

请参见本问题中的Java示例:


我知道您使用的是PHP而不是其他语言,我只是指出这是可能的。

在需要时获取数据库实例

class test {

    private static $_staticDb = null;
    private $_db = null;

    public static function init() {
        self::$_staticDb = Database::getInstance();
    }

    public function __construct() {
        $this->_db = Database::getInstance();
    }

    public function test(){
       return $this->_db->getRow("SELECT * FROM users", PDO::FETCH_ASSOC, []);
    }

   public static function testStatic(){
        return self::$_staticDb->getRow("SELECT * FROM users", PDO::FETCH_ASSOC, []);
    }

}

test::init();
print_r(test::testStatic());

$test = new test();
print_r($test->test());

将其作为参数传递。对于非静态方法,您可以使用依赖项注入:将实例传递给
Register
的构造函数,并设置一个以后可以使用的属性。此解决方案不符合OOP的目的,它将创建大量连接并杀死您的数据库server@YourCommonSense-请详细说明您对这如何击败OOP的评论?它满足简化db连接的OPs问题。这难道不是一个函数的主要目的吗?简化和/或标准化重复的代码块(?)就像杀死DB服务器一样-虽然这当然会根据代码使用的数据库/DB驱动程序而改变-在我的例子(IIS/PHPsqlsrvSQLServer)中-驱动程序正确地池/重用/删除记录的连接。正如所写的那样,句柄可以在php脚本中反复使用,并且在脚本完成后就会消失……我使用这种技术的另一个原因——在我的例子中,db.class.php在web根目录之外——创建一个“带外”中心位置来管理db服务器的服务器/登录/密码。它可能不是在每种情况下都是完美的,但在我们的情况下它肯定很有效。YMMV1。使用db类就像使用全局变量一样。而不是
$db=db::getDatabaseHandle()
您只需执行
全局$db
。去告诉我是OOP。2.即使您的驱动程序允许使用这种肮脏的代码,它仍然在做无用的工作,每次都试图连接。更不用说OP使用的是PDO,而不是不推荐的sqlsrv函数,你的方法对他来说将是一场灾难。如果我继续这样做,它不会创建太多连接吗?不,你有一个实例和一个连接。每次只能得到指向它的指针。
class test {

    public function test(){
       return Database::getInstance()->getRow("SELECT * FROM users", PDO::FETCH_ASSOC, []);
    }

   public static function testStatic(){
        return Database::getInstance()->getRow("SELECT * FROM users", PDO::FETCH_ASSOC, []);
    }
}