PHP:在singleton类中使用MySQL连接
我有一个PHP web服务,它使用单例API类来调用我的web服务方法。我的应用程序中的每个模块都有特定的类:Posts、Users、Login等。我的API类类似于: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
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在一个线程中处理所有请求。因此,使用singletonDataBase
类将创建一个请求队列,其中每个查询都应等待前一个查询运行。DataBase calls块,PHP不是多线程的。您应该仔细考虑依赖项注入。单例是一个很好的教育练习,但在使代码更松散耦合方面没有什么价值。而且,你这里也没有单身汉。您需要将构造函数设置为私有,以确保实例化的唯一方法是通过静态方法。不要使用单例。使用适当的依赖项注入:将数据库的实例传递给用户和Post
的构造函数。