PHP:在singleton类中使用MySQL连接

PHP:在singleton类中使用MySQL连接,php,mysql,pdo,Php,Mysql,Pdo,我有一个PHP web服务,它使用单例API类来调用我的web服务方法。我的应用程序中的每个模块都有特定的类:Posts、Users、Login等。我的API类类似于: class API{ private static $api; private $database; private $post; private $user; public function __construct(){ $this->database = ne

我有一个PHP web服务,它使用单例API类来调用我的web服务方法。我的应用程序中的每个模块都有特定的类:Posts、Users、Login等。我的API类类似于:

class API{

    private static $api;
    private $database;
    private $post;
    private $user;

    public function __construct(){
        $this->database = new DataBase();
        $this->post = new Post();
        $this->user = new User();
    }

    public static function getInstance(){
        if(empty(self::$api)){
            self::$api = new API();
        }
        return self::$api;
    }
}
public function __construct() {
    try{
        $this->db = new \PDO(
                "mysql:host=$this->host;dbname=$this->base;",
                $this->user, $this->pass, 
                array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'")
        );
    }catch(\PDOException $e){
        echo "<b>Error:</b> {$e->getMessage()} in <b>{$e->getFile()}</b> on line <b>{$e->getLine()}</b>";
        die();
    }
}
public static function getDatabase(){
    $api = self::getInstance();
    return $api->database;
}
因此,为了获得我的用户帖子,我会在api类内部调用
$api->post->getPosts()
,或者在api类外部调用
api::getPosts()
。API类是一个facade。每个子类都有自己的
数据库
实例。例如,
Post
User
具有以下功能:

class User{
    private $database;

    public function __construct(){
        $this->database = new DataBase();
    }
}
我的
数据库
构造函数类似于:

class API{

    private static $api;
    private $database;
    private $post;
    private $user;

    public function __construct(){
        $this->database = new DataBase();
        $this->post = new Post();
        $this->user = new User();
    }

    public static function getInstance(){
        if(empty(self::$api)){
            self::$api = new API();
        }
        return self::$api;
    }
}
public function __construct() {
    try{
        $this->db = new \PDO(
                "mysql:host=$this->host;dbname=$this->base;",
                $this->user, $this->pass, 
                array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'")
        );
    }catch(\PDOException $e){
        echo "<b>Error:</b> {$e->getMessage()} in <b>{$e->getFile()}</b> on line <b>{$e->getLine()}</b>";
        die();
    }
}
public static function getDatabase(){
    $api = self::getInstance();
    return $api->database;
}
但是每次我从子类调用
API::getDatabase()
时,我都会得到一个MySQL过多连接错误,因为这个方法调用API
\uu construct()
并创建一个新的
数据库
实例

你知道如何回收我的
数据库
实例或连接以避免连接浪费吗


更新

正如下面所建议的,我使用依赖项注入模式将我的
数据库
对象从API facade传递给它的子对象:

    public function __construct(){
        $this->database = new DataBase();
        $this->post = new Post($this->database);
        $this->user = new User($this->database);
    }
private function __construct(){
    $this->database = new DataBase();
    $this->post = new Post($this->database);
    $this->user = new User($this->database);
}
(从“未答复”中删除此项。)

评论者建议,OP证实:

使用依赖项注入模式将数据库对象从API facade传递给其子对象:

    public function __construct(){
        $this->database = new DataBase();
        $this->post = new Post($this->database);
        $this->user = new User($this->database);
    }
private function __construct(){
    $this->database = new DataBase();
    $this->post = new Post($this->database);
    $this->user = new User($this->database);
}

(实际上,
private
是建议的,但没有得到确认。)

您已经在一个类中使用了单例。为什么不让你的DB连接也成为一个单体呢?每次执行DB操作时,很少有理由打开与DB的连接。只有两种常见的借口是连接到完全不同的db服务器,或者使用不同的凭据连接。@MarcB单例
数据库
类会降低我的请求性能吗?我会解释,我读到PHP和MySQL在一个线程中处理所有请求。因此,使用singleton
DataBase
类将创建一个请求队列,其中每个查询都应等待前一个查询运行。DataBase calls块,PHP不是多线程的。您应该仔细考虑依赖项注入。单例是一个很好的教育练习,但在使代码更松散耦合方面没有什么价值。而且,你这里也没有单身汉。您需要将构造函数设置为私有,以确保实例化的唯一方法是通过静态方法。不要使用单例。使用适当的依赖项注入:将
数据库的实例传递给
用户和
Post
的构造函数。