Oh wow, I just skimmed through that real quick. I can definitely write a better book than that. In reality that isn't a PHP oriented book. It is a basic OOP book. Half of the design patterns in there they talk about as if it is a class to be designed when most of them are interfaces already provided for you to implement in your classes.
It's a novice level book for getting started in OOP. I don't suggest it to anyone beyond that because it may cause confusion if you already have an understanding of inheritance and interfaces.
Also, the Singleton design pattern. IMO it is one of the most important design patterns in any type of application that you would like to have plugins interact with them. They did it all wrong. With their implementation there is no way to have a Singleton Superclass.
In their code:
Spoiler:
PHP Code:
class InventoryConnection
{
protected static $_instance = NULL;
protected $_handle = NULL;
public static function getInstance()
{
if (!self::$_instance instanceof self) {
self::$_instance = new self;
}
return self::$_instance;
}
protected function __construct()
105
Part II: Reference Material
{
$this->_handle = mysql_connect(‘localhost’, ‘user’, ‘pass’);
mysql_select_db(‘CD’, $this->_handle);
}
public function updateQuantity($band, $title, $number)
{
$query = “update CDS set amount=amount+†. intval($number);
$query .= “ where band=’†. mysql_real_escape_string($band) . “’â€Â;
$query .= “ and title=’†. mysql_real_escape_string($title) . “’â€Â;
mysql_query($query, $this->_handle);
}
}
They have a design pattern with absolutely no setup for code reuse. That is one of the main concepts of OOP, don't duplicate code... EVER... If you find yourself looking at another class to see how you should write something, or to copy and paste, that code should be refactored elsewhere so all interested parties can take advantage of it.
I would have done this:
Spoiler:
PHP Code:
class Super_Singleton {
protected static $_instances;
/**
* Create a new instance if one does not exist.
* Store our own instance and return the reference.
* @return Super_Singleton The instance of $this.
*/
public static function getInstance() {
$me = get_called_class();
if (!isset(self::$_instances[$me])) {
$args = func_get_args();
$ref = new ReflectionClass($me);
self::$_instances[$me] = $ref->newInstanceArgs($args);
}
return self::$_instances[$me];
}
/**
* We can create a new instance if one does not exist.
* @throws Exception Attempted instantiation of an already instantiated Singleton.
*/
public function __construct() {
$me = get_class($this);
if (isset(self::$_instances[$me])) {
throw new Exception('Attempted instantiation of an already instantiated Singleton.');
} else {
self::$_instances[$me] = $this;
}
}
/**
* Disallow cloning.
*/
public function __clone() {
trigger_error("Cloning is not allowed.", E_USER_WARNING);
}
/**
* Disallow serializing.
*/
public function __wakeup() {
trigger_error("Unserializing is not allowed.", E_USER_ERROR);
}
}
class Inventory_Connection extends Super_Singleton {
protected $_handle = NULL;
public function __construct() {
parent::__construct();
$this->_handle = mysql_connect(‘localhost’, ‘user’, ‘pass’);
mysql_select_db(‘CD’, $this->_handle);
}
public function updateQuantity($band, $title, $number) {
$query = “update CDS set amount=amount+†. intval($number);
$query .= “ where band=’†. mysql_real_escape_string($band) . “’â€Â;
$query .= “ and title=’†. mysql_real_escape_string($title) . “’â€Â;
mysql_query($query, $this->_handle);
}
}
In my method, you take out the ugly design pattern code from your class and can really focus on its intention. Also, this Singleton Superclass can be used by any other Singleton you may have. Another change that I had made was the addition of the clone and wakeup magic methods to more properly follow the Singleton design pattern.