PEAR_Delegator
[ class tree: PEAR_Delegator ] [ index: PEAR_Delegator ] [ all elements ]

Class: PEAR_Delegator

Source Location: /PEAR_Delegator-0.1.0/Delegator.php

Class Overview


Base class for objects that allow delegation.


Author(s):

Variables

Methods


Inherited Variables

Inherited Methods


Class Details

[line 239]
Base class for objects that allow delegation.

Introduction
It is first necessary to discuss the role of delegates in PEAR. With the advent of PHP 5, a whole host of new programming techniques were introduced. Among them were class interfaces. These interfaces provide much of the benefits of multiple inheritance (with regard to methods) without adulterating the inheritance hierarchy. That is, an object can inherit from a parent class as usual, but still possess methods that qualify it as a member of another group of objects, related by certain behavior but still exclusively separate in the hierarchy. The interfaces, however, only define the protocol to which each adopting class must adhere, but they do not define the implementation. This is very useful in many instances, but for some purposes, the implementation remains viritually the same for all adopting parties. This is where delegation enters.

A delegate is a class that defines methods which are intended to be called by an adopting object as if they were members of that object. For instance,

  1.  class Foo extends PEAR_Delegator
  2.  {
  3.      public function _construct()
  4.      {
  5.          parent::_construct();
  6.      }
  7.  
  8.      public function _destruct()
  9.      {
  10.          parent::_destruct();
  11.      }
  12.  }
  13.  
  14.  $foo = new Foo();
  15.  $foo->bar(//This results in a runtime error,
  16.              //Foo has no such method.
  17.  
  18.  //Now define a delegate
  19.  class Delegate
  20.  {
  21.      public function _construct()
  22.      {
  23.          parent::_construct();
  24.      }
  25.  
  26.      public function _destruct()
  27.      {
  28.          parent::_destruct();
  29.      }
  30.  
  31.      public function bar()
  32.      {
  33.          echo 'bar';
  34.      }
  35.  }
  36.  
  37.  foo->addDelegate(new Delegate);  //add the delegate.
  38.  foo->bar();                      //This will be called as if it
  39.                                   //were a member of Foo.

There are two types of delegates: true delegates and false delegates.

True Delegates
These delegates are designed to be used as delegates. As such, they follow an explicit delegate protocol. To simulate an actual method call, the forwarding mechanism transparently inserts a reference to the calling delgator as a the first argument. Consquently, such a delegate's method signatures must be of the form:

  1.  accesslevel function functionName($owner...);
Note:
  1. $owner can be any suitable variable name.
  2. $owner is unncessary if the method takes no variables and does not access the delegator.
  3. The user of the method need only consider those parameters that follow the $owner argument.
Delegates of this kind are the default. However, the argument true can be passed to explicitly denote the following list as a set of true delegates:
  1.  $delegator->addDelegate($delegate1$delegate2...);
  2.  //or
  3.  $delegator->addDelegate(true$delegate1$delegate2...);

False Delegates
These delegates are designed without any intention to be used as delegates. In essence, these are regular objects in themselves that would be useful as delegates. They have no knowledge of delegators and no reason to access a forwarding delegator. Consequently, such a delegate's method signatures are not guaranteed to be of the forme described above. Their signatures can be of any form, but they will not have access to the calling delegator.

Delegates of this kind must be explicitly denoted by passing a false as the preceding argument to a list of false delegates:

  1.  $delegator->addDelegate(false$delegate1$delegate2...);

Indeed, a mixed list of delegates can be called:

  1.  $delegator->addDelegate($delegate1$delegate2false$delegate3$delegate4true $delegate1 ...);

Mixed Delegates
Since delegates can themselves can be delegators, the two kinds of delegates can be mixed. This is achieved by creating a true delegate that has added to it a false delegate. Then, any delegator can make calls to true delegate methods and false delegate methods through the same delegate.\

There are two further categorizations: class delegates and instance delegates.

Class Delegates
These delegates are classes whose methods are to be called statically.

Instance Delegates
These delegates are instances of classes.

Delegate Hierarchies
One of the benefits of this scheme is the ability to have delegate hierarchies. That is, a delegator could have a delegate that is a delegator, and the PEAR_Delegator class recognizes this by viewing such delegates as subdelegates, treating such subdelegates as subclasses would be treated. This allows for such capabilities as pseudo-overriding:

  1.  //In our Foo class we could define a bar() method as follows:
  2.  public function bar()
  3.  {
  4.     $args func_get_args();
  5.  
  6.     //Note that it may be better to call $this->getDelegateForMethod()
  7.     //instead of $this->hasDelegate(), since the latter may forward
  8.     //the call to a delegate that does not respond.
  9.     if ($this->hasDelegate())
  10.       $this->forwardMethod('bar'$args);
  11.  
  12.     echo 'foobar';
  13.  }
Now, the delegate's implementation would be called as well. This of course means that you can also completely override the delegate method, and not even call it.

Traditional Delegation
In truth, this mode of delegation is unorthodox. The traditional model of delegation is that an object delegates selected methods, calling its own version unless one delegate is present. This feature is, in fact, a subset of the scheme presented here. In otherwords, you can achieve the same effect by pseudo-overriding as described above.

Implementation

  1. Performance Impact In actuality, there should be little extra overhead after the first call to a delegated method. This is due to a caching scheme: When methods are called upon a delegator, the delegator checks an associated array that contains method names as keys and the proper delegates as values. If the key (method name) is cached in this manner, then the method is immediatly invoked on the proper delegate. If it does not exist, then each delegate is searched until one that can respond is found and this relationship is cached, otherwise, a fatal error is produced. Thus no matter how many delegates a class has, all calls after the first should only have a small latency. Note: Subdelegators cache their own delegates, so calls are passed down the hiearchy until the implementing delegate handles the call.
  2. Flexibility of Errors. This is not a trouble at all. In fact, the error output of this class is more direct in many cases than PHP's own error output. It will give you the file and line of the error in user code and its messages are modeled after those of PHP.
Terminology
  1. owner : a delegator.
  2. subdelegate : A delegator that is a delegate.
  3. native delegate : A delegate that is an immediate delegate, not a delegate of a delegate.
  4. class delegate : A delegate that is simply the class.
  5. instance delegate : A delegate that is an instantiated class.



[ Top ]


Class Variables

$_addExtensions =  false

[line 265]

  • Access: protected

Type:   mixed


[ Top ]

$_delegates = array()

[line 246]

An associative array with delegate classnames as keys and objects as values.
  • Access: public

Type:   array


[ Top ]

$_delegatesFalse = array()

[line 253]

An associative array with false delegate classnames as keys and objects as values.
  • Access: public

Type:   array


[ Top ]

$_method_map = array()

[line 260]

An associative array with delegated methods as keys and delegate objects as values.
  • Access: public

Type:   array


[ Top ]



Method Detail

__construct (Constructor)   [line 270]

PEAR_Delegator __construct( )

Constructs a delegator.
  • Access: public

[ Top ]

__destruct (Destructor)   [line 283]

void __destruct( )

Destroys a delegator.

When a delegator is destroyed, it automatically removes all of the delegates, so it is unnessary for user code to do so.

  • Access: public

[ Top ]

addDelegate   [line 321]

void addDelegate( $delegate, mixed $delegate,...)

Adds delegates to the calling object.

This method takes a list of classnames or objects. If an argument is a classname, then the method determines if it is defined. If it is, the class is added as a static delegate, otherwise a fatal error is raised. If it is an object, it is stored as a delegate; thus, there are two types of delegates: static and dynamic delegates.


Parameters:

mixed   $delegate,...   —  This specifies either a classname or an object.
   $delegate   — 

[ Top ]

addExtensions   [line 295]

void addExtensions( )

Add extensions to every new delegator.

This loads the extensions and gives every new delegator the extensions. Delegators created before this call can be passed in to have the extensions added to them;

  • Access: public

[ Top ]

cacheMethod   [line 849]

void cacheMethod( string $method)

Stores the relationship between method names and delegates.

Takes a method name, searches for the delegate that can handle it, and stores the relationship in the _method_map array. This method is called when the __call() method reveives an unrecognized method. This caching of methods speeds up delegation. If the method cannot be handled by any of the adopted delegates, then an Exception is thrown.

Note: This caches the first responding delegate.

This is an internal method and should not be invoked.


Parameters:

string   $method   —  The method name that is to be cached. This must be a lowercase string.

[ Top ]

filterMethodMapWithDelegate   [line 655]

array filterMethodMapWithDelegate( object $filterDelegate)

Removes the unwanted entries from _method_map.

This method cleans the _method_map array when a call to removeDelegate*() is made.

  • Return: The method map without the $filterdelegate
  • Access: public

Parameters:

object   $filterDelegate   —  Specifies the delegate instance, whose information is is to be removed.

[ Top ]

forwardMethod   [line 872]

void forwardMethod( string $method, [string $args = array()])

This can be used by delegators for pseudo-method-overriding a method.

This is the public interface to the __call() method, and it allows for a method to be forwarded to the delegation system, so that pseudo-method-overriding can occur.


Parameters:

string   $method   —  See the PHP documentation.
string   $args   —  See the PHP documentation

[ Top ]

getAllDelegates   [line 382]

array &getAllDelegates( )

Gets the associated array of delegate classes => delegates.

Note: Cloning may not work after this.


[ Top ]

getDelegate   [line 423]

array getDelegate( class $classname1)

Gets the delegate objects that are instances of the specified class.

This method returns instances of the specified classname as well as child instances of the specified classnames, including subdelegates, which are native to the caller. That is, if one of the delegates is a delegator and it contains a delegate of the specified type, it will be returned regardless of its own class type.


Parameters:

class   $classname1   —  This specifies a delegate classname. Any number of arguments after this is acceptable.

[ Top ]

getDelegateExact   [line 479]

array getDelegateExact( class $classname1)

Gets the delegate object that is an instance of the specified class.

This method returns classes of the specified type. This does not return subdelegates. That is, it uses only the actual class structures.


Parameters:

class   $classname1   —  This specifies a delegate classname. Any number of arguments after this is acceptable.

[ Top ]

getDelegateForMethod   [line 532]

array getDelegateForMethod( $method1, string $method1,...)

Gets the native delegate objects that respond to a certain method.

The method returns delegates native to the calling delegator, which can respond to the method in question, whether it be defined in the native delegate or in a delegate deeper in the hierarchy.


Parameters:

string   $method1,...   —  This specifies the method for whose responder is searched.
   $method1   — 

[ Top ]

hasDelegate   [line 592]

bool hasDelegate( [mixed $specifier = null])

Determines whether or not the calling object adopts a particular delegate.

This returns the availability of a delegate, including subdelegates.


Parameters:

mixed   $specifier   —  This specifies a delegate classname or object. If $delegate is a string, then it adheres to the tests of getDelegate(). If $delegate is an object, the _delegates array is searched for the object. If $specifier is null, then this returns whether or not the caller has any delegates.

[ Top ]

hasDelegateExact   [line 564]

bool hasDelegateExact( [class $specifier = null])

Determines whether or not the calling object adopts a particular delegate.

This returns the availability of a delegate not including subdelegates. Note: This should be used for delegates that don't use hierarchies.


Parameters:

class   $specifier   —  This specifies a delegate classname.

[ Top ]

is_a   [line 745]

bool is_a( mixed $specifier, class $classname)

Determines if a class or instance object is of the given type.

This method is an extension of the is_aExact() method. It also handles subdelegates, so it returns true if a delegator is passed in and has a delegate of type $classname, whether or not the delegator is of type $classname.


Parameters:

mixed   $specifier   —  Specifies the delegate with either a class or instantiated object.
class   $classname   —  The classname type to check against.

[ Top ]

is_aExact   [line 717]

bool is_aExact( mixed $specifier, class $classname)

Determines if a class or instance object is of the given type.

This method is analogous to the is_a() method of PHP. However, it handles classes too.


Parameters:

mixed   $specifier   —  Specifies the delegate with either a class or instantiated object.
class   $classname   —  The classname type to check against.

[ Top ]

method_exists   [line 797]

bool method_exists( mixed $specifier, $method, class $classname)

Determines if a class or instance object responds to a method.

This method is an extension of the method_existsExact() method. It also handles subdelegates, so it returns true if a delegator is passed in and has a delegate that can implement $method, whether or not the delegator can implement the $method.


Parameters:

mixed   $specifier   —  Specifies the delegate with either a class or instantiated object.
class   $classname   —  The method to look for.
   $method   — 

[ Top ]

method_existsExact   [line 770]

bool method_existsExact( mixed $specifier, $method, class $classname)

Determines if a class or instance object responds to a method.

This method is analogous to the method_exists() method of PHP. However, it handles classes too.


Parameters:

mixed   $specifier   —  Specifies the delegate with either a class or instantiated object.
class   $classname   —  The method to look for.
   $method   — 

[ Top ]

removeAllDelegates   [line 634]

void removeAllDelegates( )

Removes all delegates.

This completely cleans the calling object of any delegates.


[ Top ]

removeDelegate   [line 689]

void removeDelegate( $specifier, mixed $specifier,...)

Removes the specified delegate.

Takes a list of delegate classnames and delegate objects and removes them from the calling object.


Parameters:

mixed   $specifier,...   —  Specifies the delegate, whose information is is to be removed. If it is a string, then it adheres to the tests of getDelegate(). If it is an object, then it searches the for that delegate to remove.
   $specifier   — 

[ Top ]

respondsToMethod   [line 826]

bool respondsToMethod( string $method)

Finds whether or not the object or one of its delegates implements a method

Finds whether or not the calling object can perform the given method name. The calling object can perform the given method if it or one of its delegates can do so. This means that it also searches delegates that are themselves delegators.


Parameters:

string   $method   —  The method name that is to be searched for availability.

[ Top ]

setDelegate   [line 365]

void setDelegate( mixed $delegate)

Sets the delegator's one delegate.

This method takes a classname or an object and makes it the only delegate. In actuality, it removes all of the delegates and then adds the specified delegate. This is useful for using the delegation method for the traditional delegate model.


Parameters:

mixed   $delegate   —  This specifies either a classname or an object.

[ Top ]

__call   [line 895]

mixed __call( string $method, [string $args = array(null)])

Processes unrecognized method signatures.

This checks the _method_map array for a cached relationship between the method and any delegate. If one exists, the method is immediately called and the result returned. If it does not, then it calls the cacheMethod() method to find and cache the method, after which is calls the unrecognized method on the proper delegate or kills the PHP with an error.

This is an internal method and should not be invoked.


Parameters:

string   $method   —  See the PHP documentation.
string   $args   —  See the PHP documentation.

[ Top ]


Documentation generated on Mon, 11 Mar 2019 14:31:29 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.