Design Pattern: Adapter

The Adapter design pattern is basically a wrapper, that is a class which provides methods to access to another class.

It’s commonly used to normalize incompatibile interfaces.
It’s similar to Proxy pattern, but it’s a little different. Proxy includes an object and controls accesses to it; Adapter provides an interface to the object, usually by inheritance.


class A {
public static function sort(array $ar) { ... }
}

class B {
private $ar;
public function __construct() {}
public function sortElements() { ... };
public function returnArray() { return $ar;}
}

Now we can extend B and provide the same interface as A


class BAdapter extends B {
public static function sort(array $ar) {
$b = new B($ar);
$b->sortElements();
return $b->returnArray();
}
}

now we can use A and B2 in the same way:


print_r( A::sort(array(3,2,4)) );
print_r( BAdapter ::sort(array(3,2,4)) );

Design Pattern: Observer

The behavioural design pattern Observer allows to automatically update one-to-many dependences.

Structure: an object (Hence: $subject) contains a list of observer references, and provides a method notify() that invoke update() of every observer. Also observers have a reference to $subject, used inside update().
Commonly used to event handling (listeners) and login issues.
Implementation in PHP5:
Define a class Subject:
  • private $observersArray // array of Observer objects
  • attach(Observer $ob) and detach(Observer $ob)
    // add/remove observer $ob to/from $observersArray
  • notify() // call the method update() of every observer attached (in $observersArray)

Define one (or more) class Observer that contain(s):
  • reference (private properties) to Subject
  • __construct($subject) // assign the object to the private properties
  • update() // do sth. on referenced Subject. Automatically invoked from subjects that have this observer attached

Usage:


//instantiate subject
$s = new Subject();

//create 2 observers
$obs1 = new Observer($s, ...);
$obs2 = new Observer($s, ...);

//attach N observers to the subject
$s->attach($obs1);
$s->attach($obs2);
...
$s->attach($obsN);

//change something in $s
$s->changeSth(...);

// to update all the observers attached: only call notify()
// All the N observers will be updated.
$s->notify();

Design Pattern: Proxy

It provides a filtered controlled access to an object, without exposing it directly.

How to implement in PHP5:
Declare a class:
  • constructor: instantiates the object (only the first time) and keeps the instance into a private properties
  • – implement the methods that provide a controlled access to the internal object
    or
    – use the magic method __call($name, $value), then checks/filters the name and arguments, and may call call_user_func_array($func, $params). The $func parameter ($func) must be an array that contains the object (private property) and the function name ($name passed to __call).
For security obvious reasons, implement also the other magic methods, such as __clone(), __se()t, __get(), __toString()

Design Pattern: Factory

Factory is a creational design pattern which handles object creation.

A factory class provides the methods to create object (whit a superclass in common), but let subclasses to decide which class will be instantiated.
Basically, it contains a static method (“connect” in the example below) that accept one parameter and makes a switch on it. Depending on the parameter, a new object of different type is returned. Typical use is when we have a super class A and subclasses A1, A2, An, and we add a static method getAx($name) { … switching on $name and return a instance o A1 or A2… or An } .
Advantages: if we create a new type/subclass, we will not rewrite the code that create objects.
example:
Following, a class (factory) “DB” with a static method that returns an instance (object MySQL or postgreeSQL, that implements the same interface), in according to the argument (connection string).


class DB
{
public static connect($connString)
{
ereg("([a-z]*)://([a-z]*):([a-z]*)@([a-z]*)/([a-z]*)",$connString, $reg);
list($tmp, $driver, $user, $pass, $host, $db) = $reg;
switch($driver)
{
case "mysql": return new MySQL($host, $user, $pass, $db); break;
case "postgre": return new postgreSQL($user, $pass, $db, $host); break;
default: new Exception("connection string not valid !");
}
}
Example of use:
Now, let’s use the factory, regardless the class type

$conn1 = DB:: connect("mysql://user:pass@localhost/db");
$conn2 = DB:: connect("postgre://user:pass@localhost/db");

//$conn1 and $conn will only use method of the common superclass/interface, ex: query()

Design Pattern: Value

Consider a class Val which contains a value, and a method add() which add another value with the same type.


class Val {
private
$value;
public function
__construct($value=0) {$this->value = $value; }

public function get() { return $this->value; }

public function add($newVal) {
//(1) WRONG:
//$this->addV += $value; //WRONG !!

// (2) RIGHT !!
return new Val($this->value + $newVal->get());
}
}


Add directly the value to the internal properties (1) is wrong!!
Suppose to have a class ValContainer, with a properties that is a reference to object Val.

Two or more instances of ValContainer should be contains references to the same instance of Val (e.g. via another class which contains a Val instance and returns it).

If one instance calls the method add() of Val, the other instances will have the new value modified !! This is not in according to OOP principles !

The second method (2) is right, it instantiates another Val object in case of add() !!

Design Pattern Singleton

Singleton is a creational pattern which ensures a class has only one instance, and provide a global pointer to access it.

The most common example is a database connection.
The idea: the class doesn’t provide a constructor, but a method to return an instance. That instance is assigned to a static properties and is instantiated only at the 1st access.

class Example
{
// Hold an instance of the class
private static $instance;

// A private constructor; prevents direct creation of object
private function __construct() { }

// The singleton method
public static function singleton()
{
if (!isset(
self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return
self::$instance;
}

// Prevent users to clone the instance
public function __clone() { trigger_error(‘Clone is not allowed.’, E_USER_ERROR); }

}

XMLWriter

the PHP5 XMLWriter class allows to easily create XML well-formed documents.


The most useful methods:
  • openURI($output) // use ‘php://output‘ as argument to stream directly
  • startDocument(‘1.0’) // add the initial tag. 1st argument : xml version
  • writeElement(‘hr’) // write the empty node [hr/]
  • writeAttribute(‘src’,’img.gif’) //write the attribute (inside the last node) and value
    e.g: [img src=”http://www.blogger.com/img.gif” /]
  • writeElement(‘b’,’content’) // write node with content “[b]content[/b]”
  • startElement(‘body’) //add the start node [body]
  • endElement() //close the last element started. e.g: [/body]
  • How to create nodes with attributes and text:
    startElement(‘textarea’)
    writeAttribute(‘name’,’area1′)
    text(‘default text’)
    endElement()

    output:
    [textarea name=”area”]default text[/textarea]
  • endDocument()
  • flush()
  • there are other methods to write comments, DTD, CData etc… view the official documentation.
Note: I used square brackets instead of “minor or greater than” because of blogspot editor limitation.

Complete Example: RSS Feed !!

@date_default_timezone_set(“GMT”);
$xml = new XMLWriter();
// Output directly to the user
$xml->openURI(‘php://output’);
$xml->startDocument(‘1.0’);
$xml->setIndent(2);
//rss
$xml->startElement(‘rss’);
$xml->writeAttribute(‘version’, ‘2.0’);
$xml->writeAttribute(‘xmlns:atom’, ‘http://www.w3.org/2005/Atom’);

//channel
$xml->startElement(“channel”);

//title, desc, link, date
$xml->writeElement(‘title’, ‘PHP news’);
$xml->writeElement(‘description’, ‘description….’);
$xml->writeElement(‘link’, ‘http://www.example.com/rss.hml’);
$xml->writeElement(‘pubDate’, date(“D, d M Y H:i:s e”));

//item !
$xml->startElement(“item”);
$xml->writeElement(‘title’, ‘news 1’);
$xml->writeElement(‘link’, ‘http://www.example.com/1.html’);
$xml->writeElement(‘description’, ‘descr 1’);
$xml->writeElement(‘pubDate’, date(“D, d M Y H:i:s e”));
//cat
$xml->startElement(‘category’);
$xml->writeAttribute(‘domain’, ‘http://www.example.com/cat1.htm’);
$xml->text(‘News’);
$xml->endElement();
//end item
$xml->endElement();
//end channel
$xml->endElement();
// end rss
$xml->endElement();
//end doc
$xml->endDocument();
//flush
$xml->flush();



output:



SPL: DirectoryIterator

foreach (new DirectoryIterator(‘.’) as $fileInfo) {
//if($fileInfo->isDot()) continue;

echo “Name: “.$fileInfo->getFilename() . “n”;
echo
“Last : “.date(“d/m/Y H:i”, $fileInfo->getCTime()) . “n”;
echo
“Size: “.$fileInfo->getSize() . ” byten”;
echo
“Type: “.$fileInfo->getType() . “n”; //dir or file
echo “Executable: “.($fileInfo->isExecutable()?“yes”:“no”) . “n”;
echo
“Readable: “.($fileInfo->isReadable()?“yes”:“no”) . “n”;
echo
“Writable: “.($fileInfo->isWritable()?“yes”:“no”) . “n”;
}

ArrayAccess: use object as an array, file manager example

ArrayAccess (PHP5) allows to treat objects as an array.
View below the interface scheme, with explanatory comments

ArrayAccess { //PHP5 built-in Interface

// returns true/false if the element in the position $offset exists/doesn’t exist
abstract public boolean offsetExists ( string $offset )

// returns the element at the position $offset
abstract public mixed offsetGet ( string $offset )
// set the element at the position $offset to the value $value
abstract public void offsetSet ( string $offset , string $value )
//delete the element at the position $offset
abstract public void offsetUnset ( string $offset )

}


minimal implementation (to copy to quickly use).

class implements ArrayAccess
{
public function
offsetExists( $offset ){}
public function
offsetGet( $offset ){}
public function
offsetSet( $offset , $value ){}
public function
offsetUnset( $offset ){}
}


An useful example !
Let’s write a class which allows to easily manage files content, like an array.

$obj[“file.txt”] = “content”; //write “content” into file.txt
$obj[“file.txt”] .= “content”; //append “content” into file.txt
print $obj[“file.txt”] ; //print the content of file.txt
unset($obj[“file.txt”]); //delete file.txt
if (isset($obj[“file.txt”])) {} ; // equivalent to file_exists(“file.txt”)


/* class to easy manage files content like an array */
class filesManager implements ArrayAccess
{

private $basePath;
private
$prefix;
private
$suffix;

public function __construct($basePath=“”, $prefix=“”, $suffix=“”){
$this->basePath = $basePath;
$this->prefix = $prefix;
$this->suffix = $suffix;
}

//get files basepath + prefix
private function path($file){
return
$this->basePath.$this->prefix.$file.$this->suffix;
}

//file exists ?
public function offsetExists( $file ){
return
file_exists($this->path($file));
}

//read file
public function offsetGet( $file ){
if (!
$this->offsetExists($file)) return “”;
$handle = fopen($this->path($file), “r”);
$contents = fread($handle, filesize($this->path($file)));
fclose($handle);
return
$contents;
}

//write new content into a file
public function offsetSet( $file , $value ){
$handle = fopen($this->path($file), “w”);
fwrite($handle, $value);
fclose($handle);
}

//delete file
public function offsetUnset( $file ){
unlink($this->path($file));
}


}




//example of use

/* the files will be read and created in
* the folder “data”, with prefix “_” and
* suffix “.txt” */
$f = new filesManager(“data/”,“_”,“.txt”);

//create the file “data/_notes.txt” and write “file start” inside !
if (!isset($f[‘notes’]))
$f[‘notes’] = “file start !”;

//append
$f[‘notes’] .= “nanother line”;

//print all the content
print $f[‘notes’];

//delete
unset($f[‘notes’]);

References are not pointer in PHP5 !

function foo(&$var)
{
$var = 2;
}
$i = 1;
foo($i);
print $i; //prints “2”
but :
function foo(&$var)
{
$i = 2;
$var = &$i;
print $var; //prints “2”
}
$i=1;
foo($i);
print $i; //prints “1” !!!

Returning reference from functions:

function &foo(&$var)
{
$i = 2;
$var = &$i;
return $var;
}
$i=1;
print foo($i); // prints “2”