PHP: Basic object oriented PHP

I’m writing this article to my beloved wife who is currently struggling to understand the OOP-part of PHP programming. If you come over from Java or C# to PHP then OOP is not a problem. If you come from [INSERT NON-PROGRAMMER-JOB HERE] then OOP is a rather complex issue. To understand it you need to understand what a class is and what it represents. To do that, you need to see what benefits a class provides over a more conventional approach.

What I thought I’d do is that I’ll go through what the actual parts of a class are and what they do.
I have created a class called Person (because I am mr Original Programmer) and it looks like this:

	/**
	 *	A class representing a person. This version of a person
	 *	has but two properties that defines it; name and mood.
	 */
	class Person
	{
		public $name; 	//This property can be accessed outside the class
		private $mood;	//This property can only be accessed from within the class
		
		/**
		 *	Set the mood to one of the following:
		 *	1: Happy
		 *	2: Angry
		 *	3: Sad
		 */
		public function setMood($val)
		{
			//Check if val is one of the acceptable moods
			if($val == 1 || $val == 2 || $val == 3)
			{
				$this->mood = $val; //Allright, $val is accepted, set mood to val
			}
			else
			{
				$this->mood = -1; //-1 means something is wrong
			}
		}
		
		/**
		 *	Returns the mood of the person
		 */
		public function getMood()
		{
			switch($this->mood)
			{
				case 1:
					return "Happy";
				case 2:
					return "Angry";
				case 3:
					return "Sad";
				case -1:
				default:
					return "Not specified";
			}
		}
	}

In the code above we have created a class called Person which will represent a Person. Think of it as a blueprint, or that picture of the human body that a doctor has on his/her wall. It’s not actually a person, it’s just the information that describes it. There are a lot of different reasons for programmers to create classes and in this case we need a class that represents data. Why? Well, I’ll show you an example in two parts. First we’ll collect and output some data about people without the use of a class:

Non-OOP

	//If we don't have classes, this is how we will have to 
	//handle working with data about people:
	$person1Name = "Joe";
	$person1Mood = "Happy";
	
	$person2Name = "Andy";
	$person2Mood = "angry";
	
	$person3Name = "Emilia";
	
	echo "The mood of $person1Name is $person1Mood<br />";
	echo "The mood of $person2Name is $person2Mood<br />";
	echo "The mood of $person3Name is $person3Mood<br />";
	
	//The above will output:
	//	The mood of Joe is Happy 
	//	The mood of Andy is angry 
	//	The mood of Emilia is 
	
	//If we want to loop this out we will have to do like this:
	$people = array(
		"Person1" => array(
			"name" => $person1Name,
			"mood" => $person1Mood
		),
		"Person2" => array(
			"name" => $person2Name,
			"mood" => $person2Mood
		),
		"Person3" => array(
			"name" => $person2Name,
			"mood" => null
		)
	);
	
	foreach($people as $person)
	{
		echo "The mood of {$person['name']} is {$person['mood']}<br />";
	}
	
	//The above will output:
	//	The mood of Joe is Happy 
	//	The mood of Andy is angry 
	//	The mood of Emilia is 

Now, instead of creating a lot of variables that are only connected by naming convention we can create instances of our Person class. An instance is a manifestation of the class we created earlier. It’s like the actual building of a house as compared to the drawing of the blueprint. There is only a single blue print, but there can be endless amounts of manifestations of that blueprint, and they don’t have to have the same property values (houses can have different colors and owners even if the blueprints are the same).

OOP

	$person1 = new Person();
	$person1->name = "Joe";
	$person1->setMood(1);
	
	$person2 = new Person();
	$person2->name = "Andy";
	$person2->setMood(2);
	
	$person3 = new Person();
	$person3->name = "Emilia";
	
	echo "The mood of {$person1->name} is {$person1->getMood()} <br />";
	echo "The mood of {$person2->name} is {$person2->getMood()} <br />";
	
	//Since we didn't set any mood for person3 she will default
	//when we call the getMood method.
	echo "The mood of {$person3->name} is {$person3->getMood()} <br />";
	
	//The above will output:
	//	The mood of Joe is Happy 
	//	The mood of Andy is Angry 
	//	The mood of Emilia is Not specified 
	
	
	
	//Another benefit of using classes instead of loads of 
	//independent variables is if you want to place all this
	//data into an array and loop it out:
	$people = array($person1, $person2, $person3);
	foreach($people as $person)
	{
		echo "The mood of {$person->name} is {$person->getMood()} <br />";
	}
	
	//The above will output:
	//	The mood of Joe is Happy 
	//	The mood of Andy is Angry 
	//	The mood of Emilia is Not specified 

So, what have we gained?

  • Improved readability
  • Less variables floating around
  • Easier to work with as a collection
  • Validation

To begin with readability. It matters. Unless you will outlive the language there a chance that someone else might have to go through some of your code one day or you might have to revisit some old code you wrote a long time ago which you don’t remember anymore. Anything that can improve the readability of you code is good and the objects now referred to as $person1, $person2 and $person3 are easy to understand and identify; they contain data about a Person.

The reduced amounts of variables are not just aesthetically pleasing, it reduces the chance of mistakes and makes it easier to work with collections. A single object containing information can easily be placed within an array whereas without it we need to give the data keys and place it inside nested arrays to keep a track of it. This simplifies both the creating of the collection and the subsequent processing of that collection.

Lastly we actually gain a chance to validate our data. In our initial, non-OOP, approach we just create variables for the moods and enter anything. As we create the class we disallow the direct usage of the property mood and instead create a getter and setter for the property. We turn it private, meaning it cannot be accessed from outside the class (i.e. on an object), and then create help methods to both set its value and retrieve it. This way we guarantee that the property mood cannot be set without going through the setMood method.
When we set the value we also validate it. If the value doesn’t pass validation we skip it and set the mood to a default value. Then when we use the get method we can make sure that only valid data is returned (in a conformed way).

That’s all great, but what about that horrid $this variable inside the class!?
Yea, about that. Well, as I said earlier the class works as a blueprint. The blueprint is the same for all people but everyone of our instances differ a little bit (both name and mood). Let’s look at the following part:

		private $mood;
		
		public function setMood($val)
		{
			if($val == 1 || $val == 2 || $val == 3)
			{
				$this->mood = $val;
			}
			else
			{
				$this->mood = -1; //-1 means something is wrong
			}
		}

Since we set mood to private and we set the value in the method setMood we end up in a situation where we don’t actually know when the code inside that method will execute. This is of course true for any method/function but the problem is that this method has access to class specific data, namely mood. Mood can be set on an object, and more importantly it can be set to different values on different objects. Once we’ve created an instance of the Person class the variable mood will be unique to that instance.
What $this does is that it represent that specific instance that you created. That makes it possible to work with the data inside the individual object while you design the class. You accept that you don’t know what object you are in during the execution of your method, but you want to set the value of mood in that particular object, not in any other. So $this represents that object:

	$person1 = new Person();
	$person1->name = "Joe";
	$person1->setMood(1);	//$this now represents $person1
	
	$person2 = new Person();
	$person2->name = "Andy";
	$person2->setMood(2);	//$this now represents $person2

Is that it? Yes! No no no, it isn’t, but hopefully this will give you a bit of a start. If you have any questions either leave them as comments or, if you are married to me, come and ask me in my den.

Posted in PHP

Leave a Reply