Building Interpreter Classes with PHP 5

If you have ever written an application that primarily parses commands — and who hasn’t? — keep reading. As is often the case, pattern-based programming makes this task easier. In this first part of a three-part article series, you’ll learn the basic concepts surrounding the Interpreter pattern, with plenty of hands-on examples.

Introduction

In the vast and fascinating terrain of web development, working with applications whose primary task is to parse commands happens very frequently. Only think about this concept for a moment, and you’ll quickly realize that every day you’re dealing with some kind of parser, ranging from your own browser that interprets (X)HTML, CSS, XML, JavaScript code, etc. to your loyal PHP module that parses your neatly-crafted web applications.

Actually, the concept of a parser is VERY old, but the impressive advance of technology has brought it to us in a variety of applications that sometimes exceed our imagination. However, it’s not my intention to discuss here the influence of parsers on mankind, since it’d be rather irrelevant to the purposes of this article, and possibly it’d also be boring to you.

Instead, I’d like analyze this interesting topic from a practical point of view, and ask you the following question: how many times have you found yourself developing a web application that was intended to interpret a certain number of predefined commands? Certainly, the answer might be dozens, even hundreds of times.

But, what if I extend this concept one step further and tell you that it’s possible to apply it in the context of pattern-based programming with PHP? Yes, you guessed right. Among the numerous design patterns available out there, there’s one called "Interpreter." As its name suggests, it has the capacity to parse specific commands to perform a set of predefined tasks.

Does this sound a bit confusing? Fear not, because building an interpreter class with PHP is a no-brainer process that can be achieved with only minor efforts. In plain terms, when the interpreter pattern is applied, on one hand there’s a class that defines a set of commands that will be parsed, while on the other hand, there are some additional classes that are responsible for sending these commands to the interpreter. Now, the concept sounds much simpler, right?

Naturally, if you’re anything like me and want to see different hands-on examples on how to create interpreter classes with PHP, then I’ve got good news for you. In this series, which is comprised of three articles, I’ll provide you with numerous code samples showing how to implement this useful pattern, ranging from building a simple application for managing user information to creating a decent blogger.

Now, having introduced the subject of this series, let’s start learning together how to build interpreter classes with PHP 5. It’s going to be a truly instructive experience!

{mospagebreak title=The basics of implementing the interpreter pattern}

According to the concepts deployed in the introduction, in this first article of the series I’m going to demonstrate how to build an interpreter class by developing a simple user managing system. It will perform some useful tasks, such as adding new users to the system in question and displaying basic information associated with them, including their full names and their postal and email addresses.

Next, I’m going to create an interpreter class, which will be responsible for parsing a set of predefined commands. These commands will come in handy for showing the aforementioned user-related information. However, as you’ll see shortly, this process will be sent through the corresponding interpreter, in this way implementing the programmatic model imposed by the homonymous pattern.

All right, having said that, please take a look at the signature of the following "User" class, which will be useful for handling different users as a bunch of objects. Its definition is listed below:

// define ‘User’ class
class User{
  
private $name;
  
private $address;
  
private $email;
  
public function __construct($name,$address,$email){
    
if(!$name){
      
throw new Exception(‘A valid name must be supplied!.’);
    
}
    
if(!$address){
      
throw new Exception(‘A valid postal address must be
supplied!.’);
    
}
    
if(!$email){
      
throw new Exception(‘A valid email address be
supplied!.’);
    
}
    
$this->name=$name;
     
$this->address=$address;
    
$this->email=$email;
  
}
  
// get user name
  
public function getName(){
    
return $this->name;
  
}
  
// get user postal address
   
public function getAddress(){
      
return $this->address;
  
}
  
// get user email
  
public function getEmail(){
    
return $this->email;
  
}
}

As indicated above, the previous "User" class is merely a computational model that represents a typical user, where his full name and postal/email addresses are stored as class properties. Besides, you should notice that this class presents some useful accessors for retrieving the properties that I mentioned before.

So far, so good. You shouldn’t have any problems understanding the logic followed by the prior "User" class, since as you can see, it’s very easy to grasp. However, I stated previously that all these users should be stored somewhere so that they can be handled later on. So, based on this requirement, below I coded a simple class, aimed at saving objects of type "User" as an array structure.

The signature of this brand new class is as following:

// define ‘UserSaver’ class
class UserSaver{
  
private $users=array();
  
// save new user to array
  
public function save(User $user){
    
$this->users[]=$user;
  
}
  
// load specific user from array
  
public function load($userIndex){
    
if(!is_int($userIndex)&&$userIndex<0&&userIndex0>=count
($this->users)){
      
throw new Exception(‘Invalid user index!.’);
    
}
    
if(!$user=$this->users[$userIndex]){
      
throw new Exception(‘Error retrieving user object!.’);
    
}
    
return $user;
  
}
  
// load all users from array
  
public function loadAll(){
    
if(count($this->users)<1){
      
throw new Exception(‘No users were saved to array!.’);
    
}
    
return $this->users;
  
}
}

As you can see, the prior "UserSaver" class performs some useful tasks, like saving different user objects to an internal array, in addition to loading a particular user. Besides, there’s an additional method, called "loadAll()," which obviously returns to calling code all the users stored in the aforementioned array.

Now that you have learned the respective signatures for the previous two classes, it’s time to leap forward and jump into the next section, where I’m going to show you how to create a simple interpreter class. In consonance with the schema dictated by this pattern, this class will define (and parse, by the way) a set of specific commands, which will display information about the user objects that you learned previously.

To see how this interpreter class will be built, please click on the link below and keep reading.

{mospagebreak title=Parsing predefined commands}

As you might have guessed, building an interpreter class with PHP 5 is indeed a straightforward process that can be performed with minor hassles, since its main task is parsing a group of specific commands that eventually will do something useful.

In this particular case, the interpreter class that I’m about to define will be tasked with displaying information about the user objects that you saw in the previous section, by using a bunch of predefined instructions.

Here is the corresponding signature of the interpreter class in question. Take a look at it, please:

// define ‘UserInterpreter’ class
class UserInterpreter{
  
private $userSaver;
  
public function __construct(UserSaver $userSaver){
    
$this->userSaver=$userSaver;
  
}
  
// parse user command
  
public function interpret($command,$userIndex){
    
if($command!=’name’&&$command!=’address’&&$command!
=’email’&&$command!=’all’){
      
throw new Exception(‘A valid user command must be
supplied to parse user data.’);
    
}
    
// parse ‘name’ command
    
if($command==’name’){
      
$user=$this->userSaver->load($userIndex);
      
return $user->getName();
    
}
    
// parse ‘address’ command
    
elseif($command==’address’){
      
$user=$this->userSaver->load($userIndex);
      
return $user->getAddress();
    
}
    
// parse ‘email’ command
    
elseif($command==’email’){
      
$user=$this->userSaver->load($userIndex);
      
return $user->getEmail();
    
}
    
// parse ‘all’ command
    
else{
      
$users=$this->userSaver->loadAll();
      
$output=”;
      
foreach($users as $user){
        
$output.=’Name : ‘.$user->getName().’ Postal Address :
‘.$user->getAddress().’ Email : ‘.$user->getEmail().’<br />’;
      
}
      
return $output;
     
}
  
}
}

After examining the definition of the previous interpreter class, you’ll have to agree with me that it’s pretty easy to grasp. After all, all this class does is parse four specific commands, called "name," "address," "email" and "all" respectively, in order to display information associated with a specific user (hence the name "UserInterpreter").

Nonetheless, in this case it’s worth noticing that the interpreter performs all the tasks by using the methods of a "UserSaver" object, which is inputted directly into the corresponding class via its constructor.

Finally, the interpreter has the capacity to parse a command called "all." This command displays data about all the users stored by the respective "UserSaver" object. Logically, this process is very easy to follow, so I won’t spend a long time explaining how it works.

Okay, at this stage you hopefully learned how an interpreter class does its thing, therefore it’s a good time to move forward and see how this class can be used in the context of a practical example. In doing so, you’ll understand more clearly how user-related information can be displayed by using the functionality provided by the interpreter pattern.

To see how this brand new hands-on example will be developed, jump ahead and visit the next section. I’ll be there, waiting for you.

{mospagebreak title=Seeing the interpreter pattern in action}

As you’ll certainly recall from the previous section, I said that the best way to understand how the interpreter pattern works is by developing a concrete example, where all the classes that were defined previously are put to work together.

Basically, what is expected here is that the interpreter class must be capable of parsing the appropriate commands passed in to its "interpret()" method, in this way displaying information about one or more user objects.

So, considering the expectations that you may have concerning the implementation of the previous interpreter class, below I included a short script, which demonstrates the functionality of this pattern.

The corresponding code sample is as follows:

try{
  
// create some fictional users
  
$user1=new User(‘John Doe’,'Binary Avenue
1234′,’john@domain.com’);
  
$user2=new User(‘Mary Jackson’,'Port 80
Boulevard’,'mary@domain.com’);
  
$user3=new User(‘Alfred Smith’,'Scripted Street
101010′,’alfred@domain.com’);
  
// create ‘UserSaver’ object
  
$userSaver=new UserSaver();
  
// save fictional users via ‘UserSaver’ object
  
$userSaver->save($user1);
  
$userSaver->save($user2);
  
$userSaver->save($user3);
  
// create ‘UserInterpreter’ object
  
$userInt=new UserInterpreter($userSaver);
  
// display name of first user
  
echo $userInt->interpret(‘name’,0);

  
/*
  
displays the following:
  
John Doe
  
*/

   // displays postal address of first user
  
echo $userInt->interpret(‘address’,0);

   /*
  
displays the following:
  
Binary Avenue 1234
  
*/

   // display email of first user
  
echo $userInt->interpret(‘email’,0);

   /*
  
displays the following:
  
john@domain.com
  
*/

   // display name of second user
  
echo $userInt->interpret(‘name’,1);

   /*
  
displays the following:
  
Mary Jackson
  
*/

   // display postal address of second user
  
echo $userInt->interpret(‘address’,1);

   /*
  
displays the following:
  
Port 80 Boulevard
  
*/

   // display email of second user
  
echo $userInt->interpret(‘email’,1);

   /*
  
displays the following:
  
mary@domain.com
  
*/

   // display name of last user
  
echo $userInt->interpret(‘name’,2);

   /*
  
displays the following:
  
Alfred Smith
   */


  
// displays postal address of last user
  
echo $userInt->interpret(‘address’,2);

   /*
  
displays the following:
  
Scripted Street 101010
  
*/

   // display email of last user
  
echo $userInt->interpret(‘email’,2);

   /*
  
displays the following:
  
alfred@domain.com
  
*/

   // send a erroneous command to the interpreter
  
//echo $userInt->interpret(‘age’,2);

   /* throws an exception with the following message:
  
A valid user command must be supplied to parse user data.
  
*/

   // display data about all users at once
  
echo $userInt->interpret(‘all’,0);

   /*
  
displays the following:
  
Name : John Doe Postal Address : Binary Avenue 1234 Email :
john@domain.com
  
Name : Mary Jackson Postal Address : Port 80 Boulevard
Email : mary@domain.com
  
Name : Alfred Smith Postal Address : Scripted Street 101010
Email : alfred@domain.com
   */
}
catch(Exception $e){
 
echo $e->getMessage();
 
exit();
}

If you study the above example, then you’ll realize how powerful the interpreter class can be when it comes to displaying information about one or more users. As you can see, the script begins by creating some fictional users, which are saved onto an instance of the "UserSaver" class, and then uses the interpreter object to show data about each one of the stored users.

Of course, this entire process is performed by sending out to the interpreter the correct user commands. This means that this simple implementation of the pattern in question can be really helpful for building a basic abstraction layer for handling user data. Quite good, isn’t it?

As homework, try adding more users to the previous example, and see what happens when you send erroneous commands to the interpreter. Trust me, the experience can be truly fun!

Final thoughts

In this first tutorial of the series, I walked you through the basics of how to implement the interpreter pattern in PHP 5. However, this is only the beginning, because in the next part I’m going to show you how to use this handy pattern in conjunction with some string processing classes. Now that you’re warned, are you going to miss it? I hope not!

Google+ Comments

Google+ Comments