我的Android应用程序通过PHP在许多活动中多次连接到数据库。在PHP中,我有这段代码来连接数据库
class db_connect
{
protected $db_conn;
protected $db_name = "database";
protected $db_user;
protected $password;
protected $db_host ="localhost";
function __construct($username,$pass) {
$this->db_user = $username;
$this->password = $pass;
}
function connect(){
$this->db_conn = new PDO("mysql:host=$this->db_host;
dbname=$this->db_name",$this->db_user,$this->password);
$this->db_conn->exec("set names utf8");
return $this->db_conn;
}
function disconnect()
{
$this->db_conn = null;
}
function __destruct() {
}
}
因此,当我需要从其他类连接数据库时,只需执行以下操作:
$dbconnect = new db_connect($user,$pass);
$connection = $dbconnect->connect();
然后执行后,我将断开连接为$ dbconnect-> disconnect();
我的Php5.ini具有:(我不想更改它)。
; Default timeout for socket based streams (seconds)
default_socket_timeout = 60
但是问题是,当我尝试连接数据库时,它会在4/5秒内回复“ request time out”消息。然后,如果我再试一次,通常它会连接起来。有人可以建议我,我做错了什么吗?为什么即使我设置了60秒的超时,它也会在5秒内发送请求超时消息。
我不确定您的问题是什么(可能会重新打开未关闭的连接),但是我建议对您的连接类使用单例模式。
它像这样
final class PdoWrapper{
protected static $_instance;
protected $_conn;
protected $db_name = "database";
protected $db_user = "user";
protected $password = "pass";
protected $db_host ="localhost";
private funciton __construct(){
$this->_conn = new PDO("mysql:host=$this->db_host;dbname=$this->db_name",$this->db_user,$this->password);
$this->_conn->exec("set names utf8");
}
private function __clone(){}
public static getInstance(){
if( !self::$_instance ){
self::$_instance = new self();
}
return self::$_instance;
}
public function getConnection(){
return $this->_conn;
}
}
你会这样使用它
$conn = PdoWrapper::getInstance()->getConnection();
要做的是,这将保持您的连接,因此您始终只需通过调用getInstance
方法就可以使用相同的连接。需要注意的是,该类是最终的,而constructor
andclone
函数是私有的,以防止此类和数据库连接的重复。
进一步说明,您不必断开与数据库的连接,因为脚本结束时PHP会自动执行此操作。通常,连接到数据库需要时间,因此从长远来看,最好保持单个连接打开,然后再关闭和打开一个或打开多个连接。
重播让连接类接受输入作为连接参数。
虽然这乍一看是很合理的事情,并且很容易实现,但这还是有些幼稚的观点。为了解释这一点,会产生复杂性,因为一旦您允许输入到类中,就违反了“单一”模式的本质,“单一”模式是具有统一访问点的单个实例,基本上是一个不变的类实例(初始化后不能更改)。防止突变的原因是该类被标记为final(不能扩展)并且具有私有__construct
和__clone
方法的原因。
解释此问题的最佳方法是说,您将通过传递连接详细信息来优先考虑创建单例的时间。因此,您始终必须使用相同的连接详细信息来创建它,或者首先使用它进行初始连接,然后才能使用它。要进一步使它复杂化,您可以打开它以传递不同的连接详细信息,并且没有明确的方法来知道在任何给定时间使用了哪些凭据集或它拥有什么连接。您还会遇到一个问题,即确定是否使用该数据启动了类(连接),或者是否需要使用新的连接详细信息重新连接该类(连接)。
幸运的是,我们可以通过创建所谓的“多单身”来解决所有这些问题,这本身就是一种矛盾。无论如何,为此,您将需要2个文件,其中1个用于连接信息(一个配置文件),因为您实际上并不希望数据库连接详细信息散布在整个应用程序中。试想一下您要更新数据库密码并必须在所有代码中搜索其副本的日子。
因此,我们将从该文件(dbconf.php)开始
<?php
$conf = array();
$conf['database1'] = array(
'host' => 'localhost',
'user' => 'user1',
'pass' => 'pass1'
);
$conf['database2'] = array(
'host' => 'localhost',
'user' => 'user2',
'pass' => 'pass2'
);
在此文件中,我们有一个多维数组,其顶级键与数据库名称匹配,而其他数据是该数据库的连接详细信息。
然后,对上述类进行一些小的更改。(这尚未经过测试,但应显示总体思路)
<?php
final class PdoWrapper{
protected static $_instances = array();
protected static $_dbconf;
protected $_conn;
private funciton __construct( $database ){
if( !self::$_dbconf ){
require 'dbconf.php';
self::$_dbconf = $conf;
}
if( !isset( self::$_dbconf[$database] ) ){
die( 'Unknown database in '.__FILE__.' on '.__LINE__ );
}
$this->_conn = new PDO(
"mysql:host=" . self::_dbconf[$database]['host'] . ";dbname=$database",
self::_dbconf[$database]['user'],
self::_dbconf[$database]['pass']
);
$this->_conn->exec("set names utf8");
}
private function __clone(){}
public static getInstance( $database ){
if( !self::$_instance[$database] ){
self::$_instance[$database] = new self($database);
}
return self::$_instance[$database];
}
public function getConnection(){
return $this->_conn;
}
}
此处发生的变化是配置文件的导入,以及告诉类要使用哪个数据库实例的方法。现在,通过这些更改,您可以像这样调用类。
$Conn1 = PdoWrapper::getInstance( 'database1' )->getConnection();
$Conn2 = PdoWrapper::getInstance( 'database2' )->getConnection();
因此,如您现在所见,您可以有多个Singleton,每个Singleton恰好拥有与一个数据库的一个连接。使用此方法时,不会将对首个类的调用设置为首选项。无需进行初始连接。另外,您不必在各处复制数据库连接详细信息。
我要做的最后一个修改是添加一个像这样的快捷功能
public static function getInstanceConnection( $database ){
$I = self::getInstance( $database );
return $I->getConnection();
}
尽管这不是必需的,但它使您可以拨打电话,并且可以从课堂之外阅读一些内容。因此,要复制上面的初始化代码,您可以在添加该方法之后执行此操作。
$Conn1 = PdoWrapper::getInstanceConnection( 'database1' );
$Conn2 = PdoWrapper::getInstanceConnection( 'database2' );
不仅仅是从getInstance
方法中返回连接的原因(除了命名的明确性)是,您可能想向后者添加一些其他功能,在这种情况下,您将需要访问Singleton实例本身。一个简单的例子就是添加一个方法来查看是否存在这样的表。
public function tableExists( $table ){
$stmt = $this->_conn->prepare('SHOW TABLES LIKE :table');
$stmt->execute( array( ':table' => $table ) );
return $stmt->rowCount() ? true : false;
}
然后,您将需要获取实例来调用它。
$I = PdoWrapper::getInstance( 'database1' );
$I->tableExists( 'table' );
//or with method chaining you can do this.
PdoWrapper::getInstance( 'database1' )->tableExists( 'table' );
您永远都不知道要添加哪些功能,因此请始终将这些选项保持打开状态。
本质上,这是一个Singleton模式与Factory模式合并。有关编程模式的更多详细信息,请参见此Wiki文章。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句