创建一个单独的PDO连接方法以防止代码重复


Creating a separate PDO connect method to prevent code repetition

我的代码:

class db_mysqls
{
private $host;
private $user;
private $password;
private $db_name;
private $port;

/** Constructor sets the object of DB_MySQL*/
public function __construct($host, $port, $user, $password, $db_name)
{
    $this->host = $host;
    $this->port = $port;
    $this->user = $user;
    $this->password = $password;
    $this->db_name = $db_name;
}

/**getFromDB($statement) gets information from DB*/
public function getFromDB($query)
{
    try
    {
        $con = new PDO("mysql:host=$this->host;port=$this->port;dbname=$this->db_name", $this->user, $this->password);
        $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch (PDOException $e)
    {
        echo 'Connection failed: ' . $e->getMessage();
    }

    try
    {
        $resp = $con->query($query);
        return $resp;
    }
    catch (PDOException $e)
    {
        echo 'Connection failed: ' . $e->getMessage();
    }
}

我想在同一个类class db_mysqls中创建一个单独的方法来处理连接。

类似的东西:

private $con;
private function connect()
{
   global $con;
    try
    {
      $con = new PDO("mysql:host=$this->host;port=$this->port;dbname=$this->db_name", $this-  >user, $this->password);
    $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
     catch (PDOException $e)
    {
        echo 'Connection failed: ' . $e->getMessage();
    }
}
    /**getFromDB($statement) gets information from DB*/
public function getFromDB($query)
{
    global $con;
    connect(); //the call to the new function that handles connection.
    try
    {
        $resp = $con->query($query);
        return $resp;
    }
    catch (PDOException $e)
    {
        echo 'Connection failed: ' . $e->getMessage();
    }
}

问题是,我一离开connect()范围就断开了连接,我做错了什么?

如果要使用OOP方法,必须将数据封装在类中。观看SICP讲座2-4,其中详细解释了数据抽象。不要在类函数中使用全局变量——这会导致可怕的、混乱的代码。看看我的代码。它将连接存储在私有变量中,并且只连接一次——当在构造函数中创建对象时。

class.php

<?php
class db_mysqls
{
    private $host;
    private $user;
    private $password;
    private $db_name;
    private $port;
    private $connection;
/** Constructor sets the object of DB_MySQL*/
    public function __construct($host, $port, $user, $password, $db_name)
    {
        $this->host = $host;
        $this->port = $port;
        $this->user = $user;
        $this->password = $password;
        $this->db_name = $db_name;
        $this->connect();
    }

    private function connect()
    {
        try
        {
            $this->connection = new PDO("mysql:host=$this->host;port=$this->port;dbname=$this->db_name", $this->user, $this->password);
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        catch (PDOException $e)
        {
            echo 'Connection failed: ' . $e->getMessage();
        }
    }
    public function getFromDB($query)
    {
        try
        {
            $resp = $this->connection->query($query);
            return $resp;
        }
        catch (PDOException $e)
        {
            echo 'Connection failed: ' . $e->getMessage();
        }
    }
}

script.php

include_once('class.php);
$db = new db_mysqls("localhost", 3306, "user", "", "test");
$query = "SELECT * FROM Document";
$result = $db->getFromDB($query);
while($row = $result->fetch())
{
    var_dump($row);
}

测试数据库

DROP TABLE IF EXISTS `Document`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Document` (
  `DataID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Description` varchar(50) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`DataID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `Document`
--
LOCK TABLES `Document` WRITE;
/*!40000 ALTER TABLE `Document` DISABLE KEYS */;
INSERT INTO `Document` VALUES (1,'This is document 1');
/*!40000 ALTER TABLE `Document` ENABLE KEYS */;
UNLOCK TABLES;

运行php script.php将打印Document表中的行。事实上,我不认为创建这样一个类有任何理由——只使用PDO对象就可以了。

好的。首先,在这两个代码中,每次需要执行查询时都要连接,这确实效率很低。只需遵循PDO示例并在构造函数内部进行连接:

public function __construct($host, $port, $user, $password, $db_name) {
    $this->host = $host;
    $this->port = $port;
    $this->user = $user;
    $this->password = $password;
    $this->db_name = $db_name;
    try {
        $this->pdo = new 'PDO("mysql:host=$this->host;port=$this->port;dbname=$this->db_name", $this->user, $this->password);
        $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch ('PDOException $e) {
        // connection failed
    }
}

使用上面的代码,我们将把PDO对象保存在一个名为$pdo的类变量中,我们可以通过$this->pdo:在该类的每个实例方法中轻松检索该变量

public function getFromDB($query) {
    try {
        $resp = $this->pdo->query($query);
        return $resp;
    } catch ('PDOException $e) {
        // query failed
    }
}

其次:永远不要使用全局变量。他们很糟糕,他们已经被证明是糟糕的,你在这里肯定不需要他们。

关于类,您需要了解的是,它们有自己的"全局"变量,仅属于该类。所以,你必须使用它们。

只需将global $con更改为protected $con,并将此变量寻址为$this->con这样,您就不需要专用的connect()方法,也不需要像$host和其他无用的一次性变量,这确实可以让您避免大量代码重复。

还要避免使用try。。如果你不打算采取任何行动,就抓住它。所有其他代码都会破坏您的错误报告,而不是使其成为有用的

class db_mysqls
{
    protected $con;
    /** Constructor sets the object of DB_MySQL*/
    public function __construct($user, $password, $db_name, 
                                $host='localhost', $port = 3306, charset = 'utf8')
    {
        $dsn = "mysql:host=$host;dbname=$db_name;port=$port;charset=$charset";
        $opt = array(
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        );
        $this->con = new PDO($dsn, $user, $password, $opt);
    }
    /**getFromDB($statement) gets information from DB*/
    public function getFromDB($query)
    {
        return $this->con->query($query);
    }
}

这就是你需要的所有代码

$db = new db_mysqls("root", "", "test");
$result = $db->getFromDB("SELECT * FROM table");