PDO连接和抽象类 [英] PDO Connection and abstract class

查看:63
本文介绍了PDO连接和抽象类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在PDO中使用抽象类.我想知道是否有必要每次都使$conn变量为空,或者在脚本结束时是否为空?

I am using abstract class with PDO. I want to know if it is necessary to null the $conn variable every time, or if it does so itself when the scripts ends?

通过这种类型的结构,您还能告诉我什么是使$conn无效的最佳方法吗?

Can you also tell me, with this type of structure, what would be the best way to nullify $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自动关闭并清理脚本执行期间打开的所有资源,因此,不必担心手动关闭它.

Yes, sure, PHP automatically close and clean up all the resources that has been opened during script execution, so, don't worry to close it manually.

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

Anyway, to nullify conn, just nullify it: $this->conn = NULL;

但是与您班上的其他问题相比,这些东西完全可以忽略不计,这些问题是不安全的,效率低下的和无法使用的.

But all that stuff is utterly negligible compared to the other problems of your class, which is insecure, inefficient and unusable.

  • 首先,我不知道您为什么要使此类抽象化.抽象类是 prototype 类,曾经是其他类的源.但是数据库包装器是可以随时使用的最终类.我认为将其抽象化没有任何意义.
  • 错误报告也是多余且不一致的.向错误消息中添加"SELECT STATMENT中的错误"是完全没有用的.连接错误处理显然是错误的.相反,让PDO抛出异常并放开它.它将与您网站中的其他任何错误一样进行处理.
  • 下一个问题是安全性.由于某些原因,select()insert()函数都不支持准备好的语句,这使它们变得毫无用处:您可以改用PDO :: query(),结果完全一样.但是,您真正需要做的是通过在查询中使用占位符,同时将实际变量发送到execute()来正确使用prepare/execute.
  • 另一个问题是代码重复:两个函数几乎相同.
  • 同时,这两个函数都不可靠:select()函数仅限于一种类型的结果集,而insert()根本不返回任何结果.相反,您可以仅使用单个函数来运行所有查询,并使它返回该语句,这将非常有用.它将让您以PDO支持的多种格式获取返回的数据,甚至还可以从DML查询中获取受影响的行数.
  • First of all, I have no idea why would you want to make this class abstract. Abstract classes are prototype classes, used to be source of other classes. But a database wrapper is rather a ready to use final class. I see no point in making it abstract.
  • Error reporting is also superfluous and inconsistent. Adding "Error In SELECT STATMENT" to the error message is quite useless. While connection error handling is plainly wrong. Instead, let PDO to throw an exception and just let it go. It will be handled the same way as any other error in your site.
  • Next problem is security. For some reason neither select() not insert() function supports prepared statements, which renders them quite useless: you can use PDO::query() instead, with exactly the same outcome. But what you really have to is to use prepare/execute properly, by using placeholders in the query while sending actual variables to execute();
  • Another problem is duplicated code: both functions are pretty much the same.
  • And at the same time both function are quite unreliable: select() function is limited to only one type of result set, while insert() doesn't return anything at all. Instead, you can use just single function to run all your queries, and make it return the statement, which will be extremely useful. It will let you to get the returned data in dozens different formats supported by PDO, and even let you to get the number of affected rows from DML queries.

让我为您推荐另一种方法,一个简单的PDO包装器,可以让您以最简单,最安全的方式使用PDO:

Let me suggest you another approach, a simple PDO wrapper that can let you to use PDO most simple and secure way:

<?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;
    }
}

它非常强大,安全并且易于使用.

It's extremely powerful, secure, and easy to use.

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

You can use any PDO function by simply adding it's call after DB:: prefix:

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

因此,首先,它是一个 PDO包装器,它可以通过使用魔术方法__call()来运行任何PDO方法.我添加的唯一功能是run().

So, in the first place, it's a PDO wrapper, which is able to run any PDO method by means of using magic __call() method. The only function I added is run().

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

Instead of your own insecure and unreliable select() and insert() methods let me suggest you to use one universal run() method, which is nothing more than a shorthand to these three lines:

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

因此,您可以将其编写为整齐的单行代码:

So, instead you can write it as a neat one-liner:

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

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

Note that it can run a query of any kind and return the result in any format that PDO supports.

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

I wrote an article about this simple wrapper, where you can find some usage examples. All the example code can be run as is, just copy and paste it in your script and set up credentials: http://phpdelusions.net/pdo/pdo_wrapper#samples

这篇关于PDO连接和抽象类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆