3

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?

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());
        }
    }

}

1 Answer 1

6

or if it does so itself when the scripts ends?

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.

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.

  • 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.

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.

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

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

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().

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();

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

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

3
  • 1. Why did not you use abstract class? 2. If you are not allowing direct access to public static function run($sql, $args = []); so why don't you use this as protected or private why public? 3. __callStatic($method, $args); will be called to call run() and other local functions of this class? 4. And also tell me this is good way to nullify $conn in public static function __destruct(); 5. Tell me how it is to use exception handling using you'r class. Commented Oct 13, 2015 at 6:53
  • Thanks! Understand your points. Now i need to build User class Using exactly same PDO class and i have codded User class and surely need your comments on that but unable to post here where should i post that please suggest. Commented Oct 16, 2015 at 9:39
  • Your understanding about abstract class is good. In fact I was also thought of implementing database wrapper using abstract one. Can you explain when to use abstract class?
    – astrosixer
    Commented Nov 19, 2019 at 17:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.