SitePoint Sponsor |
|
User Tag List
Results 1 to 25 of 51
Thread: Design Patterns Catalogue
Hybrid View
-
Mar 31, 2005, 07:53 #1
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Design Patterns Catalogue
Hello, I got thinking today that with all the discussion about patterns, that what we need is a catelog of patterns that us PHP developers use day to day, so I've started this thread.
The idea is that members who use a pattern, any will do I suppose so long as the posted example works, has the revalant underlying script, etc and is PHP, will be as kind to post it to this thread?
Then, whenever someone reads about a particular pattern, or even post, they can start a thread about it, to discuss their issue(s) further in regards to that pattern. The idea is that this thread will be a catelog of pattern examples, with no discussion, so to avoid bloating this thread.
SweatJe is about to publish a new book later this year (summer) on PHP patterns, and I get the idea that this thread could be a supplement to that book, so what someone can't find in SweatJe's book, they'll maybe find it here, in this thread...
Anyways, I'll kick things off with two examples
Decorator
---------
Purpose of this pattern is to add extra functionality to the decorated class at run time. So you are not altering the class(es) that are to be decorated, thus you are extending the life of the said class(es).
PHP Code:abstract class AbstractRating {
protected $decoratable;
public function __construct( $decoratable ) {
$this -> decoratable = $decoratable;
}
abstract public function getRating();
}
class PoorRating extends AbstractRating {
protected $rating = 1;
public function __construct( $decoratable ) {
parent::__construct( $decoratable );
}
public function getRating() {
return $this -> decoratable -> getRating() + $this -> rating;
}
}
class AverageRating extends AbstractRating {
protected $rating = 2;
public function __construct( $decoratable ) {
parent::__construct( $decoratable );
}
public function getRating() {
return $this -> decoratable -> getRating() + $this -> rating;
}
}
class GoodRating extends AbstractRating {
protected $rating = 3;
public function __construct( $decoratable ) {
parent::__construct( $decoratable );
}
public function getRating() {
return $this -> decoratable -> getRating() + $this -> rating;
}
}
class Ratings {
private $rating = 3;
public function __construct() {
}
public function getRating() {
return $this -> rating; // typeof integer
}
}
$rating = new GoodRating( new AverageRating( new Ratings ) );
// we are decorating the Ratings object
echo( $rating -> getRating() );
----------
Purpose of this pattern is to separate functionality away from the View. The important point of using this pattern is to remember to separate the domain from the presentation, as I have done.
For example you'd use if you wanted to output tabular data with alternating rows of colour. In this case, the Template class would have the presentational HTML for this, with the ListHelper class having the logic to decide which HTML to use, from the Template class.
PHP Code:// controller
$helper = new ListHelper( 'list.template.tpl' );
$helper -> run( $data );
...
$view = new ExampleView( 'template.tpl' );
$view -> add( 'list', $helper -> toHtml() );
...
PHP Code:class ListHelper {
private $Template;
public function __construct( $filename ) {
$this -> template = new Template( $filename );
}
public function run( $resultset ) {
$html = '';
foreach( $resultset as $row ) {
$id = $row['id'];
$firstname = $row['firstname'];
$lastname = $row['lastname'];
$html .= $this -> template -> parse( $id, $firstname, $lastname );
}
$this -> template -> setHtml( $html );
}
public function toHtml() {
return $this -> template -> getHtml();
}
}
class Template {
private $html = '';
private $fragment;
public function __construct( $filename ) {
$this -> fragment = @file_get_contents( $filename );
}
public function setHtml( $html ) {
$this -> html = $html;
}
public function getHtml() {
return $this -> html;
}
public function parse( $id, $firstname, $lastname ) {
$temp = ereg_replace( '<id />', $id, $this -> fragment );
$temp = ereg_replace( '<firstname />', $firstname, $temp );
$temp = ereg_replace( '<lastname />', $lastname, $temp );
return $temp;
}
}
Last edited by Dr Livingston; Apr 2, 2005 at 03:11. Reason: Add the purpose of each pattern
-
Mar 31, 2005, 07:58 #2
- Join Date
- Jun 2004
- Location
- Copenhagen, Denmark
- Posts
- 6,157
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
It would probably be better to use a wiki for that ?
-
Mar 31, 2005, 08:01 #3
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Yep, but I have no available web space at the moment
-
Mar 31, 2005, 09:52 #4
- Join Date
- Jan 2005
- Location
- Rome
- Posts
- 77
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I can donate! I'd be happy to help you with a few Mb!
-
Mar 31, 2005, 11:17 #5
- Join Date
- Oct 2004
- Location
- naperville
- Posts
- 189
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I'd be interested in this as well, webspace and all. I'll set up a wiki on philbrodeur.com if no one minds the domain name
If it actually gets going I can set it up as phpwiki.com or whatever.
-
Mar 31, 2005, 11:29 #6
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Well, was hoping to keep it to these forums, if the idea took off, and I hope it does, it'd be a sticky thread
I just thought the forums were the best options, from the point of view of topical discussions of these blighters
-
Mar 31, 2005, 12:28 #7
- Join Date
- Aug 2001
- Location
- London
- Posts
- 2,475
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
What happened to phppatterns.com, it seems short lived. It would be nice to have a Wiki there (relevant domain), where people can contribute freely, however Harry seems to have disappeared lately?
-
Mar 31, 2005, 12:44 #8
- Join Date
- Nov 2003
- Location
- Los Angeles, CA
- Posts
- 460
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by Andrew-J2000
I've emailed him a couple times but haven't heard anything back and haven't seen anything from him in a while.My-Bic - Easiest AJAX/PHP Framework Around
Now Debug PHP scripts with Firebug!
-
Mar 31, 2005, 12:40 #9
why don't you use http://www.wiki.cc/php/Main_Page ?
-
Mar 31, 2005, 13:07 #10
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
PHP Patterns is still there as far as I know, but there has been no fresh content for a long time. Not sure what has happened to Harry but hope it's nothing serious.
As for a Wiki, I hope it doesn't go the same way as PHP Patterns. But where ever this catelog ends up, it has to be easily accessable for everyone, and allow discussions as I see it, as without the discussions, it's all pointless really.
-
Mar 31, 2005, 14:33 #11
- Join Date
- Oct 2004
- Location
- naperville
- Posts
- 189
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
The only thing wrong with forums is orginization - each pattern really should have its own thread and then we would need a "master thread".
Edit - I'm not convinced the ratings example is so hot; you're not adding functionality but rather a different type of rating. Is this really the general purpose of the pattern? No offense; I'm still learning some of this stuff.
-
Mar 31, 2005, 14:57 #12
- Join Date
- Jun 2004
- Location
- London
- Posts
- 66
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Hi all,
A while back not to long ago i created a sourceforge project. http://sourceforge.net/projects/standardpattern/
With a simular idea in mind patterns with class examples and unit tests using "Open Source" programming languages php, python, ruby ...
Never actually done anything with the project.
Something along the lines of http://patternshare.org/ would be nice.
This is a cool view of all the patterns at patternshare.org http://patternshare.org/default.aspx...rganizingTable
Note: patternshare.org smells of Microsoft. http://toolbar.netcraft.com/site_rep...tternshare.orgLast edited by davro; Mar 31, 2005 at 15:33.
-
Mar 31, 2005, 15:21 #13
- Join Date
- Aug 2004
- Location
- Canada
- Posts
- 1,280
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Obligatory spelling correction:
Catalog.GamesLib.com - the slickest, most complete and
easily navigatible flash games site on the web.
-
Apr 1, 2005, 01:51 #14
Obligatory obligatory spelling correction:
Catalogue
-
Apr 1, 2005, 07:56 #15
Originally Posted by melancholic
Catalog is the US spelling so could probably be considered acceptable.
-
Apr 1, 2005, 05:12 #16
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I'm not convinced the ratings example is so hot;
I was actually looking forwards to a lot more enthusiasm for this, and now I'm disappointed that no one else has contributed
Come on gurus, don't be shy, give up your patterns...
-
Apr 1, 2005, 07:50 #17
- Join Date
- Mar 2004
- Location
- Sweden
- Posts
- 180
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Ok, here goes nothing:
Data Mapper
PHP Code:// Base class
class DataMapper
{
var $dbh;
function insert($data)
{
trigger_error("Abstract call...");
}
function delete($id)
{
trigger_error("Abstract call...");
}
function update($data)
{
trigger_error("Abstract call...");
}
}
class ProductMapper extends DataMapper
{
function ProductMapper(&$dbh)
{
$this->dbh =& $dbh;
}
function insert($data)
{
/* Application specific, but for example:
$this->dbh->query("INSERT INTO users VALUE(" . $data['username'] . ", " . $data['password']); */
}
function delete($data)
{
/* Application specific, e.g:
$this->dbh->query("DELETE FROM users WHERE id = " . (int) $id); */
}
function update($data)
{
/* Application specific, e.g:
$this->dbh->query("UPDATE users SET username = " . $data . " WHERE id = " . $data['id']); */
}
// Maybe some other functions too...
function getAll() {...}
function findById($id) {...}
function findByFoo($bar) {...}
}
-
Apr 1, 2005, 14:25 #18
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Chain Of Responsibility
---------------------
Using a SWITCH to delegate a decision has it's drawbacks, for example you need to change the script to add another decicion. With the CoR you do not need to change anything, you just add a new handler, provided you adhere to the interface.
Btw, this is the 'classic' GoF (Group of Four) pattern I've posted.
PHP Code:// generic handlers
$h1 = new Handler1;
$h2 = new Handler2;
// handle a given request
$h1 -> setHandler( $h2 );
$h1 -> handleRequest( $request );
abstract class Handler {
protected $successor;
public function __construct() {
}
public function setHandler( Handler $successor ) {
$this -> successor = $successor;
}
abstract public function handleRequest( $request );
}
class Handler1 extends Handler {
public function __construct() {
parent::__construct();
}
public function handleRequest( $request ) {
if( $request == 'add' ) {
// do add
} else {
if( $this -> successor != NULL ) {
$this -> successor -> handleRequest( $request );
}
}
}
}
class Handler2 extends Handler {
public function __construct() {
parent::__construct();
}
public function handleRequest( $request ) {
if( $request == 'view' ) {
// do view
} else {
if( $this -> successor != NULL ) {
$this -> successor -> handleRequest( $request );
}
}
}
}
PHP Code:class AdminController extends ActionChainController {
public $view;
public function __construct() {
parent::__construct( 'Create' );
parent::attach( 'Modify' );
parent::attach( 'Remove' );
parent::attach( 'Index' );
}
public function getView() {
return $this -> view;
}
public function execute( HttpRequest $req, HttpResponse $res ) {
$request = $req -> getParameter( 'cmd' );
if( empty( $request ) ) {
$request = 'index';
}
$this -> process( $request );
}
}
PHP Code:interface IAction {
public function isSecure();
public function getView();
}
interface IActionChain {
public function attach( $handler );
public function process( $request );
}
abstract class Action implements IAction {
protected $view;
public function __construct() {
}
public function isSecure() {
return true;
}
public function getView() {
return $this -> view;
}
abstract public function execute( HttpRequest $req, HttpResponse $res );
}
abstract class ActionChain implements IAction, IActionChain {
protected $view;
protected $count = -1;
protected $handlers = array();
public function __construct( $handler ) {
$this -> handlers[++$this -> count] = new $handler( $this );
}
public function attach( $handler ) {
$this -> doAttach( new $handler( $this ) );
}
public function process( $request ) {
$handle = $this -> handlers[0];
$handle -> handleRequest( $request );
}
public function isSecure() {
return true;
}
public function getView() {
return $this -> view;
}
abstract public function execute( HttpRequest $req, HttpResponse $res );
private function doAttach( $handler ) {
$temp = $this -> handlers[$this -> count];
$temp -> setHandler( $handler );
$this -> handlers[++$this -> count] = $handler;
}
}
Last edited by Dr Livingston; Apr 2, 2005 at 12:06. Reason: Add the purpose of this pattern
-
Apr 1, 2005, 15:19 #19
- Join Date
- Jun 2004
- Location
- London
- Posts
- 66
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Basic Patterns:
HttpRequest
FrontController
Controller
---------------------
PHP Code:class HttpRequest
{
function HttpRequest() { }
function doGet() {
return $_GET;
}
function doPost() {
return $_POST;
}
}
PHP Code:class FrontController extends Controller
{
function FrontController() {
$Http = new HttpRequest();
$this->setListMerge($Http->doGet(), $Http->doPost());
}
}
PHP Code:class Controller
{
var $data = array();
function Controller() { }
function setList($array) {
$this->data = $array;
}
function setListMerge($array1, $array2) {
$this->setList(array_merge($array1, $array2));
}
function getList() {
return $this->data;
}
function getListItem($item) {
return $this->data[$item];
}
function getListItemByNotation($item, $notation, $rid) {
$note = array();
$note = explode('.', $this->getListItem($item));
return $note[$rid];
}
function isEmpty() {
if (count($this->data) <= 0) {
return true;
} else {
return false;
}
}
}
Last edited by davro; Apr 1, 2005 at 16:49.
-
Apr 1, 2005, 17:40 #20
- Join Date
- Jul 2000
- Location
- Perth Australia
- Posts
- 1,717
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
sorry dudes, but without an explanation ( goals, raison d`etre ) of each pattern ... its just gibberish to the uneducated viewer ... & if educated then they dont need the example
-
Apr 2, 2005, 09:11 #21
just a suggestion, if you want to do a pattern repository, you might want to include both php4 + php5 examples if possible. alot of people still have to stay within the php4 realm because of shared hosting or other reasons. plus that might add to appeal and help people migrate over to php5 in the long run as well.
and a second suggestion, keep the thread alive, but also maybe use a wiki or repository somewhere else or even another forum attached to this one. that sums up the discussion here, but keep the discussion here cause you never know who might show up with something good to add.
i love the idea Dr. L cause idiots like me have to read books like head first design patterns and professional php5
-
Apr 2, 2005, 10:49 #22
- Join Date
- Aug 2004
- Location
- California
- Posts
- 1,672
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I certainly like to see code so appreciate the postings. I also to agree firepages that without the simple description, explaining the problem and describing how it works the are not much help. Patterns are not implementations and showing implementations without context reduces the communication value of patterns.
I also have some questions about the patterns listed and I think it is the discussion if the ideas of the pattern that are of value.
For instance, overrunner's Data Mapper look a lot like the Table Data Gateway pattern to me. Table Data Gateway is a fairly simple pattern to describe and give examples of. Data Mapper is considerably more complex and is often implemented used a combination of patterns. In fact several different combinations are possible.
Dr Livingston's is a good example of Chain Of Responsibility. I would be interested in seeing other examples. There was a discussion recently that for the request the Intercepting Filter is a better choice, but for controllers Chain Of Responsibility is the way to go. So showing Chain Of Responsibility combined with the Command pattern would be of interest.
Of davro's patterns only Front Controller is a pattern that I know. I do not think HTTP Request and Controller are patterns (correct me if I'm wrong). And the Front Controller as shown does not seem to dispatch which is a central function of the Front Controller pattern. Though I like the idea of having a base Controller class for Front, Page and Application Controllers.Christopher
-
Apr 2, 2005, 12:16 #23
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
So showing Chain Of Responsibility combined with the Command pattern would be of interest.
PHP Code:// ...
$helper = new RequestHelper( $this -> req ); // pass Request object
$command = $helper -> getCommand();
...
PHP Code:class RequestHelper {
private $req;
public function __construct( HttpRequest $req ) {
$this -> req = $req;
}
public function getCommand() {
// here you verify command requested, etc
// and return an instance of the class to be executed, as
// in an action
}
private function isCommandFile( $command ) {
if( empty( $command ) ) {
$command = 'default';
}
return 'commands/'.$command.'.php';
}
}
-
Apr 3, 2005, 05:33 #24
- Join Date
- Jun 2004
- Location
- London
- Posts
- 66
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Hi all,
Sorry i can see how my last post might have added some entropy to the domain.
Hopefully this post might help things a little, or maybe not.
Abstract Controller Patterns:
FrontController http://www.martinfowler.com/eaaCatal...ontroller.html
ApplicationController http://www.martinfowler.com/eaaCatal...ontroller.html
PageController http://www.martinfowler.com/eaaCatal...ontroller.html
---------------------
PHP Code:class FrontController extends Controller
{
function FrontController() {
$Http = new HttpRequest();
$this->setListMerge($Http->doGet(), $Http->doPost());
}
}
class ApplicationController
{
function ApplicationController() {
$Request = new FrontController();
// do-main
}
}
class PageController
{
function PageController() {
$Request = new FrontController();
// do-main
}
}
PHP Code:class Controller
{
var $data = array();
function Controller() { }
function setList($array) {
$this->data = $array;
}
function setListMerge($array1, $array2) {
$this->setList(array_merge($array1, $array2));
}
function getList() {
return $this->data;
}
function getListItem($item) {
return $this->data[$item];
}
function getListItemByNotation($item, $notation, $rid) {
$note = array();
$note = explode($notation, $this->getListItem($item));
return $note[$rid];
}
function isEmpty() {
if (count($this->data) <= 0) {
return true;
} else {
return false;
}
}
}
PHP Code:class HttpRequest
{
function HttpRequest() { }
function doGet() {
return $_GET;
}
function doPost() {
return $_POST;
}
}
Last edited by davro; Apr 3, 2005 at 09:09.
-
Apr 15, 2005, 11:51 #25
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Composite
----------
This is a useful pattern to learn where you need to construct hierarchy data structures. The example I've posted below is for an XML file, which I use to construct a web page on the fly, but the hierarchy structure could be from the database. It doesn't matter really.
First, the XML file
Code:<?xml version="1.0" encoding="utf-8"?> <fragments> <fragment> <id>page</id> <parent></parent> <controller></controller> <fragment> <id>header</id> <parent>page</parent> <controller></controller> </fragment> <fragment> <id>body</id> <parent>page</parent> <controller></controller> <fragment> <id>partition</id> <parent>body</parent> <controller></controller> </fragment> </fragment> <fragment> <id>footer</id> <parent>page</parent> <controller></controller> </fragment> </fragment> </fragments>
PHP Code:interface IWalker {
public function __construct( $children );
public function walk( IParser $parser );
}
class XmlWalker implements IWalker {
private $children;
public function __construct( $children ) {
if( !$children instanceof DomNodeList ) {
throw new IllegalParameterException( 'thrown exception on, expected parameter(s) not found.' );
break;
}
$this -> children = $children;
}
public function walk( IParser $parser ) {
foreach( $this -> children as $child ) {
if( $child instanceof DomElement ) {
$parser -> push( $child );
try {
$walker = new XmlWalker( $child -> childNodes );
$walker -> walk( $parser );
} catch( IllegalParameterException $e ) {
die( $e -> getMessage() );
}
}
}
}
}
class ApplicationFaultException extends Exception {
public function __construct( $message ) {
parent::__construct( $message );
}
}
class IllegalParameterException extends Exception {
public function __construct( $message ) {
parent::__construct( $message );
}
}
interface IParser {
public function getRoot();
public function push( $fragment ); // DomElement
}
class XmlAdaptableCompositeParser implements IParser {
private $decoratable;
public function __construct( $decoratable ) {
$this -> decoratable = $decoratable;
}
public function getRoot() {
return $this -> decoratable -> getRoot();
}
public function push( $fragment ) {
if( $fragment -> nodeName == 'fragment' ) {
return $this -> decoratable -> push( $fragment );
}
}
}
class XmlCompositeParser implements IParser {
private $root;
public function __construct( $fragment ) {
if( !$fragment instanceof DomElement ) {
throw new IllegalParameterException( 'thrown exception on, expected parameter(s) not found.' );
break;
}
$this -> root = new Composite( $fragment );
}
public function getRoot() {
return $this -> root;
}
public function push( $fragment ) {
$composite = new Composite( $fragment );
if( $tmp = $this -> traverse( $this -> getRoot(), $fragment ) ) {
$tmp -> attach( $composite );
}
}
private function traverse( $composite, $fragment ) {
$parent = $fragment -> getElementsByTagName( 'parent' );
$parent = $parent -> item( 0 ) -> nodeValue;
if( $composite -> getId() == $parent ) {
return $composite;
} else {
if( $composite -> hasChildren() ) {
$children = $composite -> getChildren();
foreach( $children as $child ) {
$c = new Composite( $fragment );
if( $tmp = $this -> traverse( $child, $fragment ) ) {
$tmp -> attach( $c );
}
}
}
}
}
}
class Composite extends Component {
public function __construct( $fragment ) {
if( !$fragment instanceof DomElement ) {
throw new IllegalParameterException( 'throw exception on, expected parameter(s) not found.' );
break;
}
parent::__construct( $fragment );
}
}
abstract class Component {
protected $id;
protected $parent;
protected $template;
protected $children = array();
protected $controller;
public function __construct( $fragment ) {
$this -> fragment = $fragment;
$this -> id = $this -> getNode( 'id' );
$this -> controller = $this -> getNode( 'controller' );
}
public function hasChildren() {
return count( $this -> children );
}
public function getChildren() {
return $this -> children;
}
public function getNode( $node ) {
$items = $this -> fragment -> getElementsByTagName( $node );
return $items -> item( 0 ) -> nodeValue;
}
public function setTemplate( $template ) {
$this -> template = $template;
}
public function getTemplate() {
return $this -> template;
}
public function getController() {
return $this -> controller;
}
public function getId() {
return $this -> id;
}
public function attach( $composite ) {
$this -> children[] = $composite;
}
}
PHP Code:$dom = new DomDocument;
$dom -> load( 'test.xml' );
$fragment = $dom -> documentElement -> childNodes;
$walker = new XmlWalker( $fragment -> item( 1 ) -> childNodes );
// require a decorator to filter tags by the name of 'fragment'
$parser = new XmlAdaptableCompositeParser( new XmlCompositeParser( $fragment -> item( 1 ) ) );
$walker -> walk( $parser );
echo( '<pre>' ); print_r( $parser -> getRoot() ); echo( '</pre>' );
EDIT: 22/01/06
If you find that you want to apply a number of filters prior to the controller, via a number of decorators, then you could take a what changes I made later;
Note that there is no controller node as such from earlier examples, as the controller it's self is applied as a filter as well.
Code:... <fragment> <id>header</id> <parent>page</parent> <filters> <filter name="PageController" pathname="pathname/to/file" /> <filter name="FilterOneController" pathname="pathname/to/file" /> <filter name="FilterTwoController" pathname="pathname/to/file" /> </filters> </fragment> ...
ush( $fragment ); you would need to do the following before you add the composite to the composite structure, it's self;
PHP Code:// ...
$filters = $fragment -> getElementsByTagName( 'filters' );
$filters = $filters -> item( 0 );
$tmp = array();
if( $filters instanceof DomElement ) {
foreach( $filters -> childNodes as $filter ) {
if( $filter instanceof DomElement ) {
$name = $filter -> getAttribute( 'name' );
$pathname = $filter -> getAttribute( 'pathname' );
include_once( $pathname.strtolower( $name ).'.php' );
$tmp[] = $name;
}
}
}
$temp = array();
$cl = array_shift( $tmp );
$temp[] = $cl;
foreach( $tmp as $class ) {
$temp[] = new $class( array_shift( $temp ) );
}
$composite = array_shift( $temp ); // holds newly generated decorators
if( $tmp = $this -> traverse( $this -> getRoot(), $fragment ) ) {
$tmp -> attach( $composite );
}
Code:... <filters> <filter name="Controller" pathname="controllers/" /> <filter name="ThirdController" pathname="controllers/" /> <filter name="SecondController" pathname="controllers/" /> <filter name="FirstController" pathname="controllers/" /> </filters> ...
Code:Array ( [0] => FirstController Object ( [decorated:private] => SecondController Object ( [decorated:private] => ThirdController Object ( [decorated:private] => Controller ) ) ) )
PHP Code:class Controller {
private $decorated;
public function __construct() {
}
}
class FirstController {
private $decorated;
public function __construct( $decorated ) {
$this -> decorated = $decorated;
}
}
class SecondController {
private $decorated;
public function __construct( $decorated ) {
$this -> decorated = $decorated;
}
}
class ThirdController {
private $decorated;
public function __construct( $decorated ) {
$this -> decorated = $decorated;
}
}
Yours, Dr LivingstonLast edited by Dr Livingston; Jan 22, 2006 at 13:44.
Bookmarks