Hi all,

I would like to get my head around how I can create a singleton db pattern.

What I have now works though, but as I know its not a singleton - My idea is this:

  • I would like a class that holds all config information and them implement that in different classes when needed --> Example here is that I am extending it, and using the config data in another class to connect.

Is this in general a good approach? Can I extend a class unlimited times to use the data in it? Or should I instead use another approach to deal with my configuration data and the way it is implemented, suggetions are welcome, as I would like to learn some better approaches..

// CONFIG DATA :
class credentials {

private static $config = array();

const DB_USER = 'root'; 
const DB_PASS = ''; 
const DB_HOST = 'localhost';    
const DB_NAME = 'dev_dcs';

public function __construct() {
    self::$config['user'] = self::DB_USER;
    self::$config['pass'] = self::DB_PASS;
    self::$config['host'] = self::DB_HOST;
    self::$config['name'] = self::DB_NAME;
}

}

// DATABASE ACCESS :    
class database extends credentials {

public function __construct()
{
    try 
    {
        if ( new MySQLi( parent::DB_HOST, parent::DB_USER, parent::DB_PASS, parent::DB_NAME ) == true ) 
        {
            echo 'DB CLASS WORKS.';
        }           
        else 
        {   
            throw new Exception( "Database connection error" );
        }           
    }
    catch( Exception $e ) 
    {
        echo $e->getMessage();
    }       
}

}

Recommended Answers

All 5 Replies

Member Avatar for diafol

Why don't you pass the credentials as parameters - perhaps in the constructor, either as an array or single values.

require "{some above root directory}/config.php"; // contains the $dbconfig array as well as your other config data
require "classes/db.php";

$db = new db($dbconfig);

That makes more sense to me than extending a class that just holds a few constants. I always think that when subclassing, the 'child' should bear some sort of 'phenotypic' relationship to the 'parent'. Like a Darwinian thing. THis may be myopic, but it helps me keep structure in my classes. You've hard-coded data like connection details into the class. This now has to be changed when your connection details change, e.g. switch host; FTPing and switching between local/remote versions; you package your app and and release it - it may be easier to tell the user, "This is the info you need to pass to me to get me to work properly", as opposed to "If you change your details, you'll need to go to line 15 in class XX and change that value then go to class YY and change line 43 to ..." It just means that you don't need to mess with the class code.

You are buying into mysqli wholesale. This setup will never be expected to run with non-mysql DBs? If you were to consider other DB formats, that's where subclassing could be useful using a common interface for each one - or you could just use PDO :)

So you reckon this is a better approach for using mysqli:

// MYSQLI DATABASE :    
class mysqli_database {

// CONNECTION PROPERTIES :
private static $db_user = 'root'; 
private static $db_pass = ''; 
private static $db_host = 'localhost';    
private static $db_name = 'dev_dcs';
// CONNECTION OBJECT :
protected static $mysqli;

// CONNECTION :
public function __construct()
{
    try 
        {
            if ( !self::$mysqli = new MySQLi( self::$db_host, self::$db_user, self::$db_pass, self::$db_name ) )
            {   
                throw new Exception( "Database connection error" );
            }           
        }
        catch( Exception $e ) 
        {
            echo $e->getMessage();
        }              
}

// CONNECT METHOD. STATIC METHOD – CAN BE ACCESSED WITHOUT INSTANTIATION :
public static function connect()
{
    // INSURE A SINGLE INSTANCE - IF NOT AVAILABLE, THEN ONE IS CREATED :
    if ( !self::$mysqli ) 
    { 
        new mysqli_database();
    }
// RETURNER CONNECTION :
return self::$mysqli;
}

}

This works as well, which is fine...Am new to OOP, so would like to learn best practise - Is this giving me one connection, and one connection only?

Not using PDO for this project :-)

Is this correct:

Could you perhaos break down how this static method is working with the class and the __construct which connect - The theory behind it, if it can be made short :-)

I understand you want to learn the singleton pattern, but IMO it's a strange concept in PHP as at the end of the script all objects are discarded. So everytime the script starts, the mysqli object is recreated. Why not use a regular object instead? This SO thread explains it nicely.

As for the explanation, the static members are always in memory, so when you call new mysqli_database (calling __construct) a new object is being constructed, but the only thing it does is it checks the static member and returns that one (perhaps after creating it).

I have read through Google about Singletons, some says its a good approach and some dont - I would like to figure out if it is for me, and if yes: then when and why? :-) If the object is discarded everytime the scripts ends, well then there is not really a point is there..?

Normally I have a database class connection without any static properties/methods - just plain connection is made, and then just using the connection object "as normally" :

 $db = new $connection();

Which is fine too i guess - So by using an object like that (my normal approach), does that also only leaves me with one connection? Cause then I cant see the reason I am concerned about the Singleton for this isue..?

Also:

Should i even care so much about having only one connection? Does it have a huge impact on performance?

I guess a lot of threads concerning this area, originates from newbies too OOP like me, that doesnt know the exact reason for creating a singleton, or not knowing WHY it is good to have just one connection open - I mean, what is the "concequences"...

This is just as "good" then - As an singleton in php for database connection?

// MYSQLI DATABASE :    
class mysqli_database {

// CONNECTION PROPERTIES :
private static $db_user = 'root'; 
private static $db_pass = ''; 
private static $db_host = 'localhost';    
private static $db_name = 'dev_dcs';
// CONNECTION OBJECT :
protected static $mysqli;

// CONNECTION :
public function __construct()
{
    try 
    {
        if ( !self::$mysqli = new MySQLi( self::$db_host, self::$db_user, self::$db_pass, self::$db_name ) )
        {   
            throw new Exception( "Database connection error: " . self::$mysqli->$connect_error );
        }           
    }
    catch( Exception $e ) 
    {
        echo $e->getMessage();
    }              
}
}

If the object is discarded everytime the scripts ends, well then there is not really a point is there..?

Correct.

So by using an object like that (my normal approach), does that also only leaves me with one connection?

Yes, if you route all queries through this object.

Should i even care so much about having only one connection?

Every connected user running your script will have one connection. Opening just one, and closing it ensures good use of the connection pool. If you don't close your connection, the connection will time out eventually, but will not be reused in the meantime, which can cause connection issues on a busy site.

Should you query the database, then run a long running calculation, and afterwards update the database again, it may be a good idea to close the connection in the meantime.

the exact reason for creating a singleton

In other languages, these classes remain in memory to be reused more easily. In those cases a singleton creates the object only once for the duration of the entire application.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.