php – PDO连接和抽象类

我正在使用PDO的抽象类.我想知道是否有必要每次都清空$conn变量,或者当脚本结束时它是否自己这样做?

你能告诉我,有了这种类型的结构,取消$conn的最佳方法是什么?

abstract class DB_Connection
{
    protected static $tbl_admin = "prof_admin";
    //protected static $tbl_admin = "prof_admin";

    protected static function obj_db()
    {
        $servername = "localhost";
        $username = "root";
        $password = "";
        $dbname = "salmanshahid";
        $conn = null;

        try 
        {
            $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
            // set the PDO error mode to exception
            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $conn;
        }
        catch(PDOException $e)
        {
            echo $sql . "<br>" . $e->getMessage();
        } 
    }
    protected static function select($query)
    {
        try 
        {
            $conn = self::obj_db();
            $stmt = $conn->prepare($query);
            $stmt->execute();

            // set the resulting array to associative
            $stmt->setFetchMode(PDO::FETCH_ASSOC); 
            return $stmt->fetchAll();
        }
        catch(PDOException $e) 
        {
            throw new Exception("Error In SELECT STATMENT: " . $e->getMessage());
        }
    }
    protected static function insert($query)
    {
        try 
        {
            $conn = self::obj_db();
            $stmt = $conn->prepare($query);
            $stmt->execute();
        }
        catch(PDOException $e) 
        {
            throw new Exception("Error In INSERT STATMENT: " . $e->getMessage());
        }
    }

}
最佳答案

or if it does so itself when the scripts ends?

是的,当然,PHP会自动关闭并清理脚本执行期间打开的所有资源,因此,不必担心手动关闭它.

无论如何,要使conn无效,只需使其无效:$this-> conn = NULL;

但是,与你班级的其他问题相比,所有这些东西都是完全可以忽略不计的,这些问题是不安全,低效和无法使用的.

>首先,我不知道你为什么要把这个类抽象化.抽象类是原型类,曾经是其他类的源.但是数据库包装器是一个可以使用的最终类.我认为把它抽象化是没有意义的.
>错误报告也是多余的和不一致的.在错误消息中添加“SELECT STATMENT中的错误”是非常没用的.虽然连接错误处理显然是错误的.相反,让PDO抛出一个异常就让它走了.它的处理方式与您网站中的任何其他错误相同.
>下一个问题是安全性.由于某种原因,select()而不是insert()函数都不支持预处理语句,这使得它们变得毫无用处:你可以使用PDO :: query()来获得完全相同的结果.但你真正需要的是通过在查询中使用占位符同时将实际变量发送到execute()来正确使用prepare / execute;
>另一个问题是重复代码:两个函数几乎相同.
>同时这两个函数都非常不可靠:select()函数仅限于一种类型的结果集,而insert()根本不返回任何内容.相反,您可以使用单个函数来运行所有查询,并使其返回语句,这将非常有用.它将允许您以PDO支持的几十种不同格式获取返回的数据,甚至可以让您从DML查询中获取受影响的行数.

让我建议你另一种方法,一个简单的PDO包装器,它可以让你以最简单和最安全的方式使用PDO:

<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_CHAR', 'utf8');

class DB
{
    protected static $instance = null;

    public function __construct() {}
    public function __clone() {}

    public static function instance()
    {
        if (self::$instance === null)
        {
            $opt  = array(
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES   => TRUE,
            );
            $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR;
            self::$instance = new PDO($dsn, DB_USER, DB_PASS, $opt);
        }
        return self::$instance;
    }

    public static function __callStatic($method, $args)
    {
        return call_user_func_array(array(self::instance(), $method), $args);
    }

    public static function run($sql, $args = [])
    {
        $stmt = self::instance()->prepare($sql);
        $stmt->execute($args);
        return $stmt;
    }
}

它功能强大,安全且易于使用.

只需在DB ::前缀后添加调用即可使用任何PDO函数:

$stmt = DB::query("SELECT * FROM table WHERE foo='bar'");

所以,首先,它是一个PDO包装器,它能够通过使用magic __call()方法运行任何PDO方法.我添加的唯一功能是run().

让我建议你使用一个通用run()方法,而不是你自己的不安全和不可靠的select()和insert()方法,这只是这三行的简写:

$stmt = DB::prepare($query);
$stmt->execute($params);
$data = $stmt->fetch();

所以,你可以把它写成一个整齐的单行:

$data = DB::run($query, $params)->fetch();

请注意,它可以运行任何类型的查询,并以PDO支持的任何格式返回结果.

我写了一篇关于这个简单包装的文章,你可以在其中找到一些用法示例.所有示例代码都可以按原样运行,只需将其复制并粘贴到脚本中并设置凭据:http://phpdelusions.net/pdo/pdo_wrapper#samples

转载注明原文:php – PDO连接和抽象类 - 代码日志