PHP OOP Factory Pattern

PHP OOP Tutorial – Factory Pattern

Here I am providing an example on how to build up an PHP object oriented programming project, using the factory design pattern.  In this example, Factory class contains one static function to create a new class and return reference to the constructed object.
The idea is to construct each object only once. Account class contains two functions to register and login users. After user logon, a User object will be constructed and returned. This pattern can be used in almost all scenarios by adding an object through the parent class, and that object can be a parent for another class as well. Imagine Account can be an Stock object and User can be a Product class. Our User class can become a parent of another Order class as well and so on.

First of all, lets create the Factory class which contains one static method to construct other instances from our classes:
Factory.class.php
<?php
class Factory
{
// Holds references to the class instances
private static $instances = array();/*
* Returns a reference to a class instance,
* create if it doesn’t already exist.
*
* @static
* @access public
* @param    string    $class        Class name
* @param    array    $options    Class arguments
*
* @return refrence to the class instance
*/
public static function &getClass($class, $options = array())
{
// Createa unique signature for every class with its arguments
$signature = serialize(array(
“className” => $class,
“options” => $options
));// Construct the instance if the instance is not exists
if (empty(Factory::$instances[$signature]))

        {
// Get the class path
$class_path = “”;
switch ($class)
            {
case “Account”:
$class_path = “Account.class.php”;
break;case “Database”:
$class_path = “Database.class.php”;
break;
            }// Check if the class path is valid, die with an error
if ($class_path == “” || !is_file($class_path))
            {
die(” There was an error loading the : ” . $class . ” class”);
}// Require the class path only once
require_once $class_path;Factory::$instances[$signature] = new $class($options);
}

// Return the previously constructed class
return Factory::$instances[$signature];
}
}
?>


Now lets create our Account class which contains two simple register and login public functions.

Account.class.php
<?php// Include the User class
require_once “User.class.php”;class Account
{
/**
* Register a new user
*
* @access public
* @param    string  $name        full name
* @param    string    $username    username
* @param    string    $password    password
*/
public function register($name, $username, $password)
{
// Validate inputs
if ($name == “”)

        {
throw new Exception(“Name is required”);
}if ($username == “”)
        {
throw new Exception(“Username is required”);
}if ($password == “”)
        {
throw new Exception(“Password is required”);
}// Get the database object
$db = Factory::getClass(“Database”);// Insert Query
$query = “insert into users ( name , username , password ) ” .

                ” values ( ” . $db->escape($name) . “‘,'” .
                $db->escape($username) . “‘,'” .
                $db->escape(md5($password)) . “‘)”;// Run the query
$db->query($query);}

/**
* Login the user
*
* @access public
* @param    string    $username    username
* @param    string    $password    password
* @return   User
*/
public function login($username, $password)
{
// Get the database object
$db = Factory::getClass(“Database”);

$query = “select * from users where username = ‘” .

                    $db->escape($username) . “‘ and password = ‘” .
                    $db->escape(md5($password)) . “‘”;// Retrieve the result
$result = $db->query($query);// Throw an error if result was empty
if (empty($result))

        {
throw new Exception(“Invalid username or password”);
}// construct a new User object and return it
return new User( $result[0);
    }
}
?>

Here is our User class which will be constructed through its parent class (Account).

User.class.php
<?phpclass User
{
private $id = “”;
private $name = “”;
private $username = “”;
private $password = “”;/**
* Default constructor
*
* @access public
* @param    integer    $id    user id
*/
function __construct( $record = array() )
{

        $this->id = $record[“id”];
        $this->name = $record[“name”];
        $this->username = $record[“username”];
        $this->password = $record[“password”];
    }

/**
* Get the user id
*
* @access public
* @return integer
*/
public function getId()
{
return $this->id;
}

/**
* Get the full name
*
* @access public
* @return string
*/
public function getName()
{
return $this->name;
}

/**
* Change the full name
*
* @access public
* @param    string    $name    full name
*/
public function setName($name)
{
$this->name = $name;
}

/**
* Returns the username
*
* @access public
* @return    string
*/
public function getUsername()
{
return $this->username;
}

/**
* Change the password
*
* @access public
*/
public function setPassword($password)
{
$this->password = md5($password);
}

/**
* Save the changes
*
* @access public
*/
public function save()
{

        // Get the database object
        $db = Factory::getClass(“Database”);
        // Update query
        $query = “update users set name='”.
                    $db->escape( $this->name ).”‘ and password='”.
                    $db->escape( $this->password ).”‘”.
             ” where id = ‘” . $db->escape($this->id) . “‘”;
        
        // Run the query
$db->query($query);

}

/**
* Delete the user
*
* @access public
*/
public function delete()
{
// Get the database object
$db = Factory::getClass(“Database”);

$query = “delete from users where id = ‘” .

            $db->escape($this->id) . “‘”;// Run the query
$db->query($query);
}
}
?>

And finally a test file to use the above classes:
test.php
<?php// Include the Factory class
require_once “Factory.class.php”;$account = Factory::getClass(“Account”);

try

{
// Register
$account->register(“Majid Khosravi”, “majid”, “mypassword”);// Login
$user = $account->login(“majid”, “mypassword”);
echo $user->getName();
}
catch ( Exception $ex )
{
  echo $ex->getMessage();
}?>

About majid

Software engineer, Web developer and IT graduate. Profile: View My Profile
This entry was posted in Scripts. Bookmark the permalink.