[RESOLVED] Creating user.class and using singletone pattern for PDO
Hi guys :wave:
I'm creating a user class with methods like login, registration, etc.. I'm going to use PDO instead of using the standard mysql functions.
My question is, do I have to declare a new object of PDO globally in the beginning or to use something like a separate class for it with single tone pattern ?
I found this link saying about it : http://php.net/manual/en/language.oop5.patterns.php
As you are the professionals, I would like to know the professional approach when using PDO.
Thanks :wave:
Re: Creating user.class and using singletone pattern for PDO
Typically, I use a static variable pointing to the PDO object.
I find the singleton pattern singularly useless and prefer to use static classes/class members instead. Remember that the lifetime of a PHP script is limited to a particular HTTP request; there is no such thing as application state. In fact one can further argue that the only purpose of static classes in PHP is organisation of code.
Re: Creating user.class and using singletone pattern for PDO
Quote:
Originally Posted by
penagate
Typically, I use a static variable pointing to the PDO object.
I find the singleton pattern singularly useless and prefer to use static classes/class members instead. Remember that the lifetime of a PHP script is limited to a particular HTTP request; there is no such thing as application state.
Thanks :wave:
I'm thinking about creating an object of PDO in the beginning, then pass it as an argument to the class objects I create(in the constructor). What do you think ? A good approach ?
Re: Creating user.class and using singletone pattern for PDO
Let's talk about abstraction.
PDO is a data access library. It's also a database abstraction layer, because it abstracts away the dependency on a particular database system. Using PDO, you can use the same code to access a MySQL database as you would Postgres or MS SQL, as long as you stick to standard SQL.
The main reason you would create a database class is to abstract away the data access library, so that your application can use different libraries — such as MySQLi, or php_mysql, or php_pgsql — without the dependency on a particular library's API throughout your code. You could use PDO this way as well, and possibly even make use of its built in abstraction, so that your queries could possibly be running through pdo_mysql or pdo_mssql or MySQLi or lib_mssql or so on and so forth, all depending on what was installed on the host system.
In reality this is all super overkill, unless you are writing an application that can be run on as many different server configurations as possible. Even then, I'd prefer to simply introduce a dependency on PDO, and save yourself the headache of having umpteen different code paths depending on the environment.
If you do that, it's easy. You need two files:
/includes/config:
PHP Code:
<?php
class Config
{
public static const DB_CONNECTION_STRING = 'mysql:localhost;dbname=foobar';
public static const DB_USERNAME = 'CaptainPeacock';
public static const DB_PASSWORD = 'AreYouFree?';
}
?>
/includes/database
PHP Code:
<?php
require_once 'config';
$dbh = new PDO(Config::DB_CONNECTION_STRING, Config::DB_USERNAME, Config::DB_PASSWORD);
?>
And in any other class file which needs database access:
PHP Code:
require_once 'includes/database';
This gives you a global $dbh object.
If you're fussy about not using global variables, you can put it into a static class variable instead (which is the same thing really, but with an extra layer of clothing on):
PHP Code:
class Database
{
public static var $dbh = new PDO(
Config::DB_CONNECTION_STRING,
Config::DB_USERNAME,
Config::DB_PASSWORD
);
}
This gives you Database::$dbh.
If you're super fussy, you might find that ugly, and prefer something like this:
PHP Code:
class Database
{
public static var $dbh = new PDO(
Config::DB_CONNECTION_STRING,
Config::DB_USERNAME,
Config::DB_PASSWORD
);
public static function exec($statement)
{
return self::$dbh->exec($statement);
}
public static function prepare($statement)
{
return self::$dbh->prepare($statement);
}
# etc...
}
That gives you Database::exec, Database::prepare, and so on. And then you're on the way to creating a database abstraction layer, anyway, and you need to think about whether it's all really worth the bother, or if you're just writing code for the sake of writing code. Abstraction costs time and effort; don't be fooled into thinking it'll make your life any easier.
All up to you...
Re: Creating user.class and using singletone pattern for PDO
Thanks for explaining about the abstraction :thumb:
I think I could go with the global variable approach. As you mentioned, I have created the PDO object. Then included in the page. Now I have a class for members. The functions of class would be login and register.
So, how would I access this global PDO object inside the class ? Using global ?
In the 6th comment on this page, keith tyler is saying that sometimes, the global variable wouldn't be available inside the class ! :confused:
includes/config:
PHP Code:
<?php
class Config
{
public static const DB_CONNECTION_STRING = 'mysql:localhost;dbname=foobar';
public static const DB_USERNAME = 'CaptainPeacock';
public static const DB_PASSWORD = 'AreYouFree?';
}
?>
includes/database:
PHP Code:
<?php
require_once 'config';
$dbh = new PDO(Config::DB_CONNECTION_STRING, Config::DB_USERNAME, Config::DB_PASSWORD);
?>
includes/members.php
PHP Code:
<?php
class Member
{
global $dbh;
var $name = '';
var $email = '';
//.....
public function login($username , $password)
{
$dbh->prepare("SELECT username , email, password FROM table_members WHERE username = ? AND password = ?")
//... bind the data
//... execute the query
//... if count of resultset is greater than 0, success. Assign SESSION and return true. Else return FALSE.
}
//... methods for Register and the rest
}
?>
login.php
PHP Code:
require_once('includes/database.php');
require_once('includes/members.php');
$user = new Member;
$uname = $_POST['username'];
$password = $_POST['password'];
//do some regex validation on the username and password
$result = $user->login($uname , $password);
if($result == true)
echo 'Success'; //and redirect
else
echo 'Error. Please try again';
//close PDO object
Is this the correct way ? Do I have to move the regex into the Member class ? Or in a separate class ?
Re: Creating user.class and using singletone pattern for PDO
You must declare global $dbh in each function.
If you use the static class variable approach, as in my second example, you won't have to do that. I prefer static variables for that reason. (They also offer better options for organisation.)
Also, the database connection will be closed implicitly when the script terminates.
Re: Creating user.class and using singletone pattern for PDO
Thanks :wave:
I'll follow your method. :thumb:
PHP Code:
class Database
{
public static var $dbh = new PDO(
Config::DB_CONNECTION_STRING,
Config::DB_USERNAME,
Config::DB_PASSWORD
);
}
Also, in case of chat application, don't we have to immediately terminate db connection after each polling ? I mean, when the script terminates, the garbage collector wouldn't act immediately unlike we close it explicitly. Isn't it ? Or is it the opposite way ? :confused:
Re: Creating user.class and using singletone pattern for PDO
There is no need to worry about garbage collection in PHP; the lifetime of a script is far too short. In fact, garbage collection was only recently introduced (in version 5.3).
If you poll on the server side, the database connection is re-used for each query.
If you poll from the client to the server, a new connection is opened for each script and automatically closed when the script terminates. (Unless you use connection pooling, but that's something you have to enable manually.)
Re: Creating user.class and using singletone pattern for PDO
Thanks :wave:
Really appreciate your help and your detailed explanations. :)
Re: [RESOLVED] Creating user.class and using singletone pattern for PDO
No worries!
A few more details:
There are two primary ways PHP is executed in response to a HTTP request. One is as a dynamically loaded library (php5_module in Apache), and one is as a child process using the CGI or FastCGI protocols.
In the case of the library, each PHP script is run in a thread within one of the HTTP server's worker processes. Memory allocation is per-thread, and the HTTP server is responsible for cleaning up its threads (and worker processes, if it is using a process pool).
In the case of CGI or FastCGI, the HTTP server forks a child process for each instance of PHP. This process is killed after the script concludes and the operating system is responsible for cleaning up.
In either case, the only time you need to worry about memory management is if your script runs for a very long time, and usually the HTTP server will impose some sort of time limit which determines how long you can twiddle your thumbs before sending the response.
Re: [RESOLVED] Creating user.class and using singletone pattern for PDO
Thanks for the additional info :thumb:
:wave:
Re: Creating user.class and using singletone pattern for PDO
Quote:
Originally Posted by
penagate
If you're fussy about not using global variables, you can put it into a static class variable instead (which is the same thing really, but with an extra layer of clothing on):
PHP Code:
class Database
{
public static var $dbh = new PDO(
Config::DB_CONNECTION_STRING,
Config::DB_USERNAME,
Config::DB_PASSWORD
);
}
This gives you Database::$dbh.
Hi again,
I have a small doubt: Is there a need of that "var" when declaring that member variable ? Or does it provide any other functionality. :confused:
I just googled and found that, it's depreciated in PHP 5.
Thanks :wave:
Re: [RESOLVED] Creating user.class and using singletone pattern for PDO
I don't think it's deprecated, but it's not necessary. I wrote it out of habit because I've been writing too much ActionScript.
Re: [RESOLVED] Creating user.class and using singletone pattern for PDO
Quote:
Originally Posted by
penagate
I don't think it's deprecated, but it's not necessary. I wrote it out of habit because I've been writing too much ActionScript.
ok. Thanks for clarifying it. :wave: