The Reflection API: Working with Reflected Methods

This third part of a seven-part series explores the methods of the PHP Reflection API. You will learn how to take advantage of their functionality to retrieve useful information about the methods defined by a reflected class.

One of today’s most powerful approaches for retrieving information about the internal structure of classes and interfaces in PHP 5 is via the language’s native reflection API. What’s more, not only does this API comes packaged with a huge variety of methods that let developers perform all sorts of reverse-engineering tasks using an object-oriented approach, but it offers a flat learning curve.

In reality, knowing whether a method within a specified class is public, protected or private, or determining whether or not a declared property is static, only involves invoking the proper method provided by the API. The entire introspection process is that easy.

Naturally, if you’ve already read the two previous parts of this series, you’re now pretty familiar with using the PHP reflection API to get basic data on a simple interface and its implementing class. In those two articles I demonstrated how to retrieve, for instance, the name, the default properties and constants of a sample reflected class. I also showed how to discover a few other minor details, such as its physical location within the file system.

As I said a moment ago, however, the API provides many other helpful methods for obtaining relevant information about a specific class. These include methods that allow you to know what methods are defined by the class, and their level of visibility.

Assuming that you’re interested in learning more about this topic, in the lines to come I’m going to show you how to manipulate reflected methods in a painless way. This process will range from finding out if they’re public, protected or private, to invoking them (when possible) directly from client code.

Now it’s time to learn a few more useful things about the PHP reflection API. Let’s go!

{mospagebreak title=Review: using the PHP reflection API to retrieve information on a class}

Just in case you haven’t had the chance to look at the preceding article of the series, where I discussed using the reflection API to get miscellaneous information about an example class, I’m going to include a brief view. Below I reintroduced the definition of this class and its associated interface, along with a script that pulls out mixed data from these two structures.

Here’s the source code of the interface and its implementing class:

interface Identifier

{

    public function setId($id);

   

    public function getId();

    

}

 

 

 

/**

* A sample user class

*

* @param  id fname lname email

*/

class User implements Identifier

{

    private $id = NULL;

      private $fname = ‘Alejandro';

    private $lname = ‘Gervasio';

    private $email = ‘alejandro@domain.com';

    const HEADING = ‘Using the Reflection API in PHP 5′;

   

    // constructor (not implemented)

    public function __construct(){}

   

    //setter for id property

    public function setId($id)

    {

        if (!is_numeric($id))

        {

            throw new Exception(‘ID must be a numeric value’);

        }

        $this->id = $id;

    }

   

    // getter for id property

    public function getId()

    {

        return $this->id;

    }

       

    // setter for fname property

    public function setFirstName($fname)

    {

        if (empty($fname) OR !is_string($fname))

        {

            throw new Exception(‘First name must be a non-empty string.’);

        }

        $this->fname = $fname;

    }

   

    // getter for fname property

    public function getFirstName()

    {

        return $this->fname;

    }

   

    // setter for lname property

    public function setLastName($lname)

    {

        if (empty($fname) OR !is_string($fname))

        {

            throw new Exception(‘Last name must be a non-empty string.’);

        }

        $this->lname = $lname; 

    }

   

    // getter for lname property

    public function getLastName()

    {

        return $this->lname;

    }

   

    // setter for email property

    public function setEmail($email)

    {

        if (empty($email) OR !is_string($email) OR strpos($email, ‘@’) === FALSE)

        {

            throw new Exception(‘Email must be a well-formatted email address.’);

        }

        $this->email = $email; 

    }

   

    // getter for email property

    public function getEmail()

    {

        return $this->email;

    }         

}

As you can see, the previous "User" class and the pertinent "Identifier" interface are nothing but simple examples for putting the reflection API to work. The following code fragment shows how to use the API to get general information about that class by using a few straightforward methods. Check it out:

// create instance of ‘User’ class

$user = new User();

 

 

 

// create instance of Reflection class and pass in ‘User’ class as argument

$reflector = new ReflectionClass(‘User’);

 

 

 

// get default properties in reflected class

print_r($reflector->getDefaultProperties()); // displays Array ( [id] => [fname] => Alejandro [lname] => Gervasio [email] => alejandro@domain.com )

 

 

 

// get doc comments in reflected class

print_r($reflector->getDocComment()); // displays /** * A sample user class * * @param id fname lname email */

// get starting line number of reflected class

echo $reflector->getStartLine(); // displays ’15’

 

 

 

// get ending line number of reflected class

echo $reflector->getEndLine(); // displays ’87’

 

 

 

// get filename of reflected class

echo $reflector->getFileName(); // displays ‘C:pathtoreflection_apireflection_api.php’ 

 

 

 

// get name of implemented interfaces

print_r($reflector->getInterfaceNames()); // displays Array ( [0] => Identifier ) 

 

 

 

// get associative array of implemented interfaces

print_r($reflector->getInterfaces()); // displays Array ( [0] => Identifier ) Array ( [Identifier] => ReflectionClass Object ( [name] => Identifier ) )

Retrieving miscellaneous data about the earlier "User" class is a simple process, thanks to the use of some intuitive reflection methods. In the above example, those methods are utilized to determine the starting and ending lines of the class, and the name of its containing file.

As a bonus, the API is finally employed to get the names of the interfaces implemented by "User," which in this case is "Identifier," whose corresponding definition was shown before.

Okay, now that you know how to use the power of reflection to analyze certain internal aspects of a class, I’m going to teach you how to get relevant information about the methods defined by the "User" class. This includes the ability to check whether these methods are public, protected or private.

To learn the full details of this reflection process, click on the link below and read the section to come.

{mospagebreak title=Retrieving methods of a reflected class}

One of the most useful features of the reflection API is its ability to retrieve information about the methods defined by a selected class, to say nothing of its manipulation ability. And by manipulation, I mean the capability to invoke a reflected method with its incoming arguments.

To elaborate on this concept, say that a script needs to check whether the "getFirstName()" method of the previous "User" class is public (which is true), and then call it from client code. Performing these tasks would be as easy coding the following snippet: 

// create instance of ‘User’ class

$user = new User();

 

 

 

// create instance of Reflection class and pass in ‘User’ class as argument

$reflector = new ReflectionClass(‘User’);

 

 

 

// get a ReflectionMethod object

$method = $reflector->getMethod(‘getFirstName’);

 

 

 

// check to see if the reflected method is public, protected or private

if ($method->isPublic())

{

    echo ‘The method is public'; // displays ‘The method is public’

   // invoke the reflected method

   echo $method->invoke($user); // displays ‘Alejandro’   

}

elseif ($method->isProtected())

{

    echo ‘The method is protected';

}

elseif ($method->isPrivate())

{

    echo ‘The method is private';

}

elseif ($method->isStatic())

{

    echo ‘The method is static';

}

Undoubtedly, a few interesting things are happening here. The above script uses a brand new reflection method called "getMethod()" to retrieve the "getFirstName()" method from the "User" class. This process returns an object of type ReflectionMethod, which can be used afterward for checking the visibility of "getFirstName()" and for calling it directly from client code.

This one example should give you an excellent idea of the advantages in using reflection in PHP, and its possible applications in real-world environments. 

Having explained how to inspect and invoke a determined method within a reflected class, the last thing that I’m going to cover in this tutorial, will consist of showing how to use reflection to retrieve all of the public methods defined by that class.

Now, to learn the full details of this process, click on the link below and read the section to come.

{mospagebreak title=Getting all the public methods of a reflected class}

As I said in the section that you just read, the reflection API makes it really easy to get all of the public, protected and private methods of a class. For the sake of brevity, in this case I’m going to show how to retrieve only the public ones, but obviously a similar approach can be used to get those with a stronger visibility.

Now that I’ve clarified that, please check the following code sample. It uses another reflection method, called "getMethods()," which returns an array containing the public methods of the previous "User" class:  

// create instance of ‘User’ class

$user = new User();

 

 

 

// create instance of Reflection class and pass in ‘User’ class as argument

 

 

 

$reflector = new ReflectionClass(‘User’);

 

 

 

// get all public methods of reflected class

print_r($reflector->getMethods(ReflectionMethod::IS_PUBLIC)); // displays Array ( [0] => ReflectionMethod Object ( [name] => __construct [class] => User ) [1] => ReflectionMethod Object ( [name] => setId [class] => User ) [2] => ReflectionMethod Object ( [name] => getId [class] => User ) [3] => ReflectionMethod Object ( [name] => setFirstName [class] => User ) [4] => ReflectionMethod Object ( [name] => getFirstName [class] => User ) [5] => ReflectionMethod Object ( [name] => setLastName [class] => User ) [6] => ReflectionMethod Object ( [name] => getLastName [class] => User ) [7] => ReflectionMethod Object ( [name] => setEmail [class] => User ) [8] => ReflectionMethod Object ( [name] => getEmail [class] => User ) )

As you can see, the "IS_PUBLIC" constant of the ReflectionMethod class is inputted into "getMethods()" to get all of the public methods of "User." This outputs an array that naturally can be traversed by using a regular "foreach" construct.

In a similar way, I could have passed to "getMethods()" the "IS_PROTECTED" and "IS_PRIVATE" constants to retrieve the protected and private methods respectively, but since this process is fairly straightforward, it will be left as homework for you.

And with this last example, we’ve come to the end of this third part of the series. As usual, feel free to tweak all of the code samples included in this tutorial. Doing this will hopefully will arm yourself with a more solid background in using the PHP reflection API.

Final thoughts

That’s all for now. In this third installment of the series you learned how to take advantage of the functionality provided by the PHP reflection API to retrieve useful information about the methods defined by a reflected class.

In the examples shown, the power of reflection was used not only to get the names of those methods, but for determining their level of visibility. Of course, it’s feasible to manipulate reflected methods in many more useful ways, but this will be left as a practical exercise for you.

In the forthcoming part, I’m going to teach you how to use reflection to work with properties of a class, which will be a very juicy topic, trust me. Don’t miss the upcoming article!

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort