Pro PHP- Patterns, Frameworks, Testing and More

(vip2019) #1
CHAPTER 7 ■ REFLECTION API^77

This doesn’t make a lot of sense, because you’ve added function bodies for a bunch
of methods you won’t use in order to satisfy the interface. Imagine if there were hundreds of
methods in your API. It just doesn’t work.
Now, you might be thinking you could split each method into its own interface, but the
same problem occurs. You have a class implementing hundreds of interfaces and hundreds
of interface declarations. This isn’t practical either. Is there a better way?
Some languages are event-driven and offer the ability to delegate methods to receive events
from the host application, but PHP doesn’t have native delegate support. As a result, a lot of
frameworks have developed complicated sets of “hook” functions that require the plug-in to
register its capabilities during some sort of initialization. This initialization and registration API
makes it more difficult to create plug-ins, so fewer plug-ins are developed.
The reflection API offers a solution. In this approach, you use the get_declared_classes()
function to get all the currently loaded classes and determine which implement a single-method
IPlugin “marking” interface. This interface will be significantly simpler than the entire API that
is available, but will contain a getName()function, which all plug-ins must have.
As an example, we will walk through the steps of building a very basic web page as a plug-
in–based system. The page will contain a menu, sidebars, and articles. Via reflection, the appli-
cation will detect which facilities each plug-in supports and will execute the appropriate method
only if it’s available. This example is extremely simple, and is not designed as an entire applica-
tion, but it does demonstrate how to use reflection to load plug-ins.
First, create the interface that all plug-ins must follow, called IPlugin, as shown in Listing 7-3.

Listing 7-3. Creating the IPlugin Interface

interface IPlugin {
public static function getName();
}

This interface is simple. It just defines a mandatory method that must be implemented by
all plug-ins.
Next, you need to create a subroutine to detect all the currently included plug-ins. To do
this, you just use get_declared_classes() and ReflectionClass, as shown in Listing 7-4.

Listing 7-4. Finding Plug-ins with Reflection

function findPlugins() {
$plugins = array();
foreach(get_declared_classes() as $class) {
$reflectionClass = new ReflectionClass($class);
if($reflectionClass->implementsInterface('IPlugin')) {
$plugins[] = $reflectionClass;
}
}
return $plugins;
}

The code in Listing 7-4 uses the implementsInterface() method of ReflectionClass to
determine if the class implements IPlugin. This method does precisely what its name suggests:
it checks if the class implements the interface. Unlike the instanceof operator (introduced in

McArthur_819-9C07.fm Page 77 Friday, February 22, 2008 8:59 AM

Free download pdf