So I finally started to refactor the base of my PHP office app: I added new functionality to it based on a singleton PDO-class, which I was planning to deploy throughout the whole app. It is very straightforward and working (for now) as it should:
class DB {
protected static $instance;
protected function __construct() {}
public static function getInstance()
{
if( empty( self::$instance ) )
{
$dsn = 'pgsql:host=' . Config::$a .
';dbname=' . Config::$b .
';port=' . Config::$c .
';connect_timeout=15';
$db_user = Config::$d;
$db_pass = Config::$e;
try
{
self::$instance = new PDO( $dsn, $db_user, $db_pass );
self::$instance->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e )
{
new Log( 6, "DB Class failed to connect to dbase: $e" );
}
}
return self::$instance;
}
}
This afternoon I'm telling a friend of mine, who is a .NET-programmer about this singleton db-connection class, and he warns me that using a singleton to connect to a database can lead to threading-problems.
I must say that it had crossed my mind: several users will be using the app, and almost all functionality is related to (multiple) db-queries. It is not unthinkable that two users will be executing a query at the same time.
Is PDO (or PHP, or Apache (at the office), or Nginx (testing environment at home)) capable of dealing with this? Maybe a new instance is given for every user? Maybe I should use this singleton together with transactions that will lock the database for every query/update/insert/delete to avoid threading problems? Or maybe my friend is wrong and I don't have to worry?
Thx for any insights!
Do not worry about using a singleton to establish the connection.
Every php script request will have its own thread. I mean, if two simultaneous requests happen, the web server will execute your singleton in two different threads, so you finally will have two different objects dealing with the database connection.
Josh Lockhart resume it very fine at http://www.phptherightway.com/pages/Design-Patterns.html
The singleton pattern is useful when we need to make sure we only have a single instance of a class for the entire request lifecycle in a web application. This typically occurs when we have global objects (such as a Configuration class) or a shared resource (such as an event queue).
So, if you request to a script, and this script make more than one access to DB (or call another script that access the DB too), you are in advantage by using Singleton. =) Obvious, it is better to previne more than one access by request (by using stored procedures, for example).