-
Factory method design pattern introduced by GoF (Gang of Four) which I’ve talked about in a previous blog, has the base idea of a method that generates objects. Most implementations are “poor”, because they use a lot of hard-coding for the factory (just like me in the previous blog).
PHP 5.3 offers the possibility of a very interesting implementation using “Late static bindings“.
The classes from which the objects will be generated are:
1// abstract base class that will be inherited 2abstract class Drink { 3 4 // ingredients 5 protected $ingredients; 6 7 // public method for producing the drink 8 abstract public function MakeDrink(); 9} 10 11// a child class for tea 12class Tea_Drink extends Drink { 13 14 // ingredients for tea 15 protected $ingredients = array('tea', 'sugar', 'mink', 'water'); 16 17 // make tea 18 public function MakeDrink() { 19 20 // make tea 21 } 22} 23 24// another class for Bloody Mary 25class BloodyMary_Drink extends Drink { 26 27 // ingredients for Bloody Mary 28 protected $ingredients = array('votka', 'salt', 'tomato juice'); 29 30 // make Bloody Mary 31 public function MakeDrink() { 32 33 // make BloodyMary 34 35 } 36}The idea is to have an abstract factory class to extend as simple as possible when creating each new factory class.
PHP 5
In PHP 5 the class will look something like this:
1// abstract Factory class 2abstract class absFactory { 3 4 // name of the base class 5 static protected $base_class = ''; 6 7 // factory method 8 public static function getInstance($type) { 9 10 // name of the resulting class 11 $class_name = $type . '_' . self::$base_class; 12 13 // check if class exists 14 // here you can add an autoloader 15 if(!class_exists($class_name)) { 16 throw new Exception( 'Class ' . $class_name . ' not loaded!'); 17 } 18 19 // check to see if the class inherits the base class 20 if(!is_subclass_of($class_name, self::$base_class)) { 21 throw new Exception( 22 'Class ' . $class_name . ' is not a child of ' . self::$base_class 23 ); 24 } 25 26 // new object 27 return new $class_name; 28 29 } 30 31}Because the getInstance() method is static the property will be static too.
If we try:
1class DrinkFactory extends absFactory { 2 3 static protected $base_class = 'Drink'; 4} 5 6try { 7 8 $obj = DrinkFactory::getInstance('Tea'); 9 10} catch (Exception $e) { 11 12 echo $e->getMessage(); 13}The output will be:
1Class Tea_ not loaded!Because of the “self”, we can’t just call the method using the child class because the value of $base_class will be “” and not “Drink”, we must overwrite the getInstance() method. Which is quite “complicated”.
A working version in PHP 5 will be:
1class DrinkFactory extends absFactory { 2 3 public static function getInstance($type) { 4 5 self::$base_class = 'Drink'; 6 7 // factory method of the base factory class 8 parent::getInstance($type); 9 10 } 11 12} 13 14try { 15 16 $obj = DrinkFactory::getInstance('Tea'); 17 18} catch (Exception $e) { 19 20 echo $e->getMessage(); 21}But is not exactly “elegant”.
PHP 5.3
Here we have “Late static bindings”, which is basically introducing the work “static”.
The base factory class will look something like this:
1// abstract Factory class 2abstract class absFactory { 3 4 // name of the base class 5 static protected $base_class = ''; 6 7 // factory method 8 public static function getInstance($type) { 9 10 // name of the resulting class 11 $class_name = $type . '_' . static::$base_class; 12 13 // check if class exists 14 // here you can add an autoloader 15 if(!class_exists($class_name)) { 16 throw new Exception( 'Class ' . $class_name . ' not loaded!'); 17 } 18 19 // check to see if the class inherits the base class 20 if(!is_subclass_of($class_name, static::$base_class)) { 21 throw new Exception( 22 'Class ' . $class_name . ' is not a child of ' . static::$base_class 23 ); 24 } 25 26 // new object 27 return new $class_name; 28 29 } 30 31}A change so small allows us to create a much “nicer” factory class:
1class DrinkFactory extends absFactory { 2 3 static protected $base_class = 'Drink'; 4 5} 6 7try { 8 9 $obj = DrinkFactory::getInstance('Tea'); 10 11} catch (Exception $e) { 12 13 echo $e->getMessage(); 14}Basically in this version only the relevant property in this context is overwritten.
-
An creational design pattern, which represents an solution for generation objects without specifying the class name. Virtually all methods that generate objects are particular implementations of the Factory Method pattern.
Motivation:
A motivation for this choice is that the creation of the object is delegated to the factory method.
Diagram:

Implementation:
The classes that generates the objects, the common class to extend and the class with the factory method:1// the common class to be extended 2abstract class OutputBase { 3 // output the necessary headers 4 abstract public function header(); 5 6 // resulting body 7 abstract public function body($data); 8 9} 10 11// class for XML ouput 12class XMLOutput extends OutputBase { 13 14 // output XML header 15 public function header() { 16 header('content-type: text/xml'); 17 } 18 19 // xml document 20 public function body($data) { 21 $res = ''; 22 23 $res .= ''; 24 25 foreach ($data as $root => $item) { 26 27 $res .= ''; 28 29 foreach ($item as $key => $val) { 30 $res .= '<'.$key.'>'.$val.''; 31 } 32 33 $res .= ''; 34 } 35 36 $res .= ''; 37 38 return $res; 39 40 } 41 42} 43 44// class for CSV output 45class CSVOutput extends OutputBase { 46 47 // output CSV header 48 public function header() { 49 header("Content-type: text/plain"); 50 } 51 52 // CSV body 53 public function body($data) { 54 $res = ''; 55 56 $keys = array_keys($data[0]); 57 58 foreach ($keys as $key) { 59 $res .= '"'.$key.'";'; 60 } 61 $res .= "\r\n"; 62 63 foreach ($data as $item) { 64 foreach ($item as $val) { 65 $res .= '"'.$val.'";'; 66 } 67 68 $res .= "\r\n"; 69 } 70 71 return $res; 72 } 73} 74 75// the factory method class 76// is abstract so it wont be instantiated 77abstract class OutputFactory { 78 79 // constant for XML type 80 const XML = 1; 81 82 // constant for CSV type 83 const CSV = 2; 84 85 // static factory method 86 public static function getInstance($type) { 87 // depending which constant was received as a parameter 88 // one of the objects will be returned 89 switch ($type) { 90 case self::XML : 91 return new XMLOutput(); 92 break; 93 94 case self::CSV : 95 return new CSVOutput(); 96 break; 97 } 98 99 // if the value received as a parameter is not one of the constants 100 // an exception will be thrown 101 throw new Exception('Invalid class type!'); 102 } 103 104}Example:
1// the data 2$data = array( 3 array( 4 'a' => 1, 5 'b' => 2, 6 'c' => 3 7 ), 8 array( 9 'a' => 4, 10 'b' => 5, 11 'c' => 6 12 ) 13 ); 14 15// try-catch block in case of an exception 16try { 17 // generation the object 18 $obj = OutputFactory::getInstance(OutputFactory::XML); 19 20 // output headers 21 $obj->header(); 22 23 // display body 24 echo $obj->body($data); 25 26} catch (Exception $e) { 27 28 $e->getMessage(); 29 30} -
Another year has passed and PHP 6 is still not here…
But that’s not exactly news, is the 4-th year when this long awaited version is not released. Not for nothing is called the most awaited version.
But overall it was a good year for the community, even though we still don’t have native Unicode in a stable version now we have all other awaited features in PHP 5.3, which will probably need another few years to become used on a large scale.
Even though everyone was expecting last year for Oracle to enter in full force on medium and small database market by purchasing Sun, enlarging it’s already well established portfolio on the enterprise market. It seems that it was not to be, CE is still analyzing the deal.
However MySQL is not what it used to be 5-6 years ago, when nobody dared to use it for enterprise products. This days MySQL is a product ready to be used in both small and large products that require a lot of scalability.
But back to the year that just ended, it was a full year, even with this economic crises.
-
CodeIgniter is an open-source PHP framework, build for RAD development. This framework is continuously growing in popularity, probably especially since people realized that is much easier to use an open-source framework instead of developing an internal one, but that’s another story. The CodeIgniter 1.7 book from PacktPublishing, written by Jose Argudo Blanco and David Upton is building a big picture about the CodeIgniter 1.7 framework, as an addition to the reference manual.
After all every respectable framework has an detailed reference, with usability examples, more or less comprehensible. When it comes to learning an framework (and not only), an reference is usually not the best place to start from, because is hard to get the big picture when you can only receive atomic answers. That’s why we buy books this days, to have a general image with problems and solutions. And this is where the CodeIgniter 1.7 book comes in.
Initially, when I’ve seen that the title has the version number of the analyzed framework I was a little pessimistic, because usually when you buy a book you don’t want it to be tight up to particular version, isn’t it? Well, not exactly… I had a similar issue with Zend Framework, most books use “older versions” (ex: 1.5-1.6) and I wanted to see an approach using the new features from version 1.8 or greater. After all when you start learning something you usually want the latest version of the framework or what ever it is that you are learning, and when new features appear it will be much easier to simply look then in the reference guide since you already know the basics.
This book seams to start from the beginners level and progressively describe both basic elements as well as the most common problems the user may encounter when developing apps using the CodeIgniter framework. The sample chapter, looks pretty well structured and easy to understand, and from the table of contents it seams to approach all the important subjects. With the hope that the rest of the book will be just as well structured (I’m actually judging a book by the cover?) and a second part to this review will follow I can’t barely wait for the book.
To be continued…
-
Last week I was supposed to create a little project. Requirements were short: interoperability.Given the fact that I’ve never used Adobe AIR before, I thought it was a good opportunity to try it.
The result was a small project management app. For the server-size I’ve used PHP + SOAP + Zend Framework, and for the client I’ve used Adobe AIR with JavaScript.
I’ve created the server in a few lines:
1<?php 2// autoload class for Zend Framework 3include 'Zend/Loader/Autoloader.php'; 4 5// class that deals with SOAP requests 6include 'SOAP.class.php'; 7 8// initialize autloader 9Zend_Loader_Autoloader::getInstance(); 10 11// if it's a request for the WSDL descriptor file 12if(isset($_GET['wsdl'])) { 13 $autodiscover = new Zend_Soap_AutoDiscover(); 14 $autodiscover->setClass('test'); 15 $autodiscover->handle(); 16// if it's a SOAP request 17} else { 18 $soap = new Zend_Soap_Server("http://localhost/soap/index.php?wsdl"); 19 $soap->setClass('test'); 20 $soap->handle(); 21} 22 23?>The descriptor is build automatically using PHP Documenter type comments from the class that handles SOAP requests, if this case it’s named “test”.
This was the easy part so I’ve moved on to the Adobe AIR client following this simple steps:
- Download and install Aptana Studio
- Install Adobe AIR plug-in
- New project -> Adobe AIR
- and voila! Coding can begin!
Adobe AIR is using for a JavaScript engine Webkit. Sounds familiar? Webkit is used by Safari and Google Chrome. So the JavaScript code should only be compatible with Webkit!
Of course there is a “but” and a plus. The “but” is that there are some restrictions, for instance “eval” can only be used to decode JSON, and the text introduced directly in an element (as text) can not be executed:
1div.innerHTML = "<a onclick=\"alert('ceva')\" href=\"#\">click</a>";This link will get to the element by will not run anything on “onclick” because the parameter was send as text.
This was a pretty big disadvantage for me, but I’ve managed to figure out an alternative by building HTML elements using DOM and adding events using addEventListener.
Briefly Adobe AIR is using this formula:
1Adobe AIR = (Webkit)Web Development - security + air framework.It seems very easy for a Web Developer to develop desktop apps with Adobe AIR.
Of course is not very fast and it’s not looking like a good idea for complex apps. But if your thinking about medium and small apps, if I had to choose between Adobe AIR and PHP GTK for instance, the first option seems a lot more viable and easy to use!
In the end the project was ready in less then 3 days and the graphics were gorgeous! It didn’t even look like it was build using only HTML and JavaScript!
