PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1
CHAPTER 12 ■ ENTERPRISE PATTERNS

// we now have a command name in $cmd
// turn it into a Command object
$cmd_obj = $this->resolveCommand( $cmd );
if (! $cmd_obj ) {
throw new \woo\base\AppException( "couldn't resolve '$cmd'" );
}


$cmd_class = get_class( $cmd_obj );
if ( isset( $this->invoked[$cmd_class] ) ) {
throw new \woo\base\AppException( "circular forwarding" );
}


$this->invoked[$cmd_class]=1;
// return the Command object
return $cmd_obj;
}


function resolveCommand( $cmd ) {
$classroot = $this->controllerMap->getClassroot( $cmd );
$filepath = "woo/command/$classroot.php";
$classname = "\woo\command\{$classroot}";
if ( file_exists( $filepath ) ) {
require_once( "$filepath" );
if ( class_exists( $classname) ) {
$cmd_class = new ReflectionClass($classname);
if ( $cmd_class->isSubClassOf( self::$base_cmd ) ) {
return $cmd_class->newInstance();
}
}
}
return null;
}
}


The getResource() method implements the search for both forwarding and view selection. It is
called by getView() and getForward(), respectively. Notice how it searches from the most specific
combination of command string and status flag to the most generic.
getCommand() is responsible for returning as many commands as have been configured into a
forwarding chain. It works like this: when the initial request is received, there should be a cmd property
available, and no record of a previous Command having been run in this request. The Request object stores
this information. If the cmd request property has not been set, then the method uses default, and returns
the default Command class. The $cmd string variable is passed to resolveCommand(), which uses it to acquire
a Command object.
When getCommand() is called for the second time in the request, the Request object will be holding a
reference to the Command previously run. getCommand() then checks to see if any forwarding is set for the
combination of that Command and its status flag (by calling getForward()). If getForward() finds a match, it
returns a string that can be resolved to a Command and returned to the Controller.
Another thing to note in getCommand() is the essential check I impose to prevent circular forwarding.
I maintain an array indexed by Command class names. If an element is already present when I come to add
it, I know that this command has been retrieved previously. This puts us at risk of falling into an infinite
loop, which is something I really don’t want, so I throw an exception if this happens.

Free download pdf