Abstraction for the rest of us

Millions of web developers, from those just starting out with sparkling ampersands in their eyes to hardened veterans with ‘ ’ burned to the back of their retinas, have found a love for PHP and its possibilities but still talk in hushed whispers about the mystery and intrigue of Object Oriented Programming (OOP) in PHP.

This tutorial aims to remove some of the curly-brace-filled haze that often surrounds OOP and by the end of this lesson you will have created a class, instantiated an object, given inheritance to some children and come to understand why OOP is such a powerful tool to have at your disposal. If you have no idea what any of the above means but are shaking with a desire to find out, read on as we look at Abstraction for the rest of us.

What is OOP and why would I use it?

OOP is the process of abstracting (removing and isolating) variables and the actions required to manipulate them. By grouping the code together in a logical manner you are able to create objects – self contained areas of code that will perform the necessary actions allowing you to deal with results separately to the actions that generate them.

Using the Procedural Approach (the name given to a program that runs from top to bottom following a designated procedure), if you wanted to write a script in which you kick a ball and find out where it lands, you would need to create variables (or an array) for the ball, its position, the speed it was kicked etc.. You would then need to write the functions that process these variables and all of this would be included into and/or intermingled with the code that works with outputting or storing results.

In any script that you wanted to kick a ball and see where it lands, the variables would need to be created and the functions to manipulate them would need to be included.

Using the Object Oriented Approach, instead of creating all these variables and functions (which have no explicit ties to each other), you would create a ball object. The ball object would contain variables pertaining only to it (properties) and functions that deal almost exclusively with these properties (methods). You would not have to worry about including the right functions or the scope of your variables, you would only have to tell the ball what you want it to do -- be kicked -- and ask it what you need to know -- where did you land?--.

When dealing with the variables of objects, we call them properties as although they behave exactly the same way as variables, they relate specifically to that object.

Similarly, when dealing with objects, functions become methods – objects have methods to access and alter properties

Each time you wanted to perform these actions, it would simply be a matter of creating the ball object and asking it what you want it to do. This is where the power of OOP starts to emerge, the flexibility of Abstraction. By grouping the properties and methods together logically, they are isolated and can be included where needed functioning almost like self-contained programs that can be slotted together like blocks of Lego.

OOP allows for flexible, easily expandable and graceful programs.

Okay, how do I do this in PHP?

To create an object, you first need to create a blueprint for the object. The blueprint outlines what properties (variables) the object should possess and what methods (functions) the object should be able to perform. This blueprint is called a class and is best looked at like a cookie cutter. A cookie cutter defines the shape of the cookie and can be used to punch out as many cookies as needed. A class defines the shape of an object and can be used to create as many objects as needed.

DEFINING A CLASS

To create a class in PHP, you use the class keyword and give it a name – similar to way you would declare a function. The class definition is surrounded by curly braces.

class className { // Class definition goes here }

BUILDING AN OBJECT

Now that you have a blueprint (however useless it is in its present form) you can create an object. This process is called instantiation.

To instantiate an object it’s time to use another PHP keyword that you may not have encountered – new.

<?php class className { // Class definition here } //Instantiate the object $anObject = new className; echo ‘$anObject is now an object built from the’, get_class($anObject), ‘ class’; ?>

That’s it! Obviously this is just the shell but it is all that is required to start building objects.

GIVE YOUR OBJECT SOME IDENTITY

Now it’s time to get your hands dirty and learn how to build objects with properties and methods.

A common task that performed by PHP is to maintain state for a user as he/she moves around the site, the rest of this tutorial will focus on defining a class that will create ‘user’ objects, giving access to and allowing modification of a user’s preferences.

Start by defining the class:

<?php class myUser { } ?>

A user travelling around your site will have some properties that will change from user to user. Some of these properties might be:

First & Last Names

User Name (For use on the site)

Email address

Age

Gender

To add these to your blueprint or class, you specify a Visibility Identifier followed by a normal variable declaration.

What’s that? What the hell is a visibility identifier? Good question. In PHP5 there are some special keywords called visibility identifiers that are used to define the scope a property or method of an object is available to.

Public – declaring a property as public means that it can be accessed inside or outside of an object. So any function or any other PHP code can read or set the property. Private –declaring a property or method as private restricts access and only allows that property or method to be accessed inside the object itself. Protected – declaring a property or method as protected restricts access and only allows that property or method to be accessed from within the object, or within an object that is from a child class (inheritance and children will be explained below). Static, Abstract and more – You will see more keywords appearing before properties and methods. These aren’t visibility identifiers but can be used when declaring a property or method.Declaring a property or method as static means that you can access that property or method without creating an object first. It means you can access it straight from the class without having to instantiate an object first.Abstract classes and methods are beyond the scope of this tutorial but in a nutshell, an abstract class/method defines what methods child classes should implement. The children can’t actually use that method; they have to implement it themselves.

The user class now looks like this:

<?php class myUser { public $firstName; public $lastName; public $userName; public $email; public $age; public $gender; } // Instantiate the object $user = new myUser; ?>

The object in $user now has all of the properties defined in the myUser class. Knowing that $user has these properties is fine, but you need to be able to access them.

To access a public property of an object you use the following syntax:

$user->firstName; // $Variable->propertyName

Notice that when you want the property name you drop the dollar sign and just write the name. You can assign a value to a property using the same syntax:

$user->firstName = ‘Luciano’;

An object property can hold almost any data type including other objects.

NB: Trying to read or write a private or protected property will result in a fatal error.

GET SOME ACTION – DEFINING METHODS

Now that you know how to get and set the properties of an object, you would be able to populate all the properties with values and access them, but using this technique would mean your object wouldn’t be anything more than a glorified array. It is a coding convention – and highly recommended – that you avoid accessing object properties directly, you should instead access and modify object properties using methods written for the task. These methods are usually referred to as getters and setters. One method gets the property value and another sets the value. There are many reasons this practice is preffered including but not limited to:

PHP allows you to create properties on the fly which may lead to bugs in your code. For example $user->firstNam = ‘Luciano’; would not throw and error, instead it would create a ‘firstNam’ property in $user . Later, when $user->firstName; doesn’t return the expected result, it may not be easy to find out why.

would not throw and error, instead it would create a ‘firstNam’ property in . Later, when doesn’t return the expected result, it may not be easy to find out why. Methods allow you to perform checks and tasks on data before assigning it to a property. Adding an array to the firstName property would not be very useful as people aren’t usually named in arrays. With methods you can check that the data is what the object expects before changing the property.

The code below shows how to add two methods to your user class. One will set the firstName of the user and the other will return it you can use it (eg. Echo it to the screen). As there is now a setter and a getter for the firstName property, the visibility identifier can be changed to private.

<?php class myUser { private $firstName; public $lastName; public $userName; public $email; public $age; public $gender; public function setFirstName($name) { //Check that the data is valid for use as a firstname if (ctype_alpha($name)) { $this->firstName = $name; return true; } // Return false if the data is not valid return false; } function getFirstName() { // Return the current value of firstName return $this->firstName; } } //Instantiate the user $user = new myUser; // set the user’s first name if ($user->setFirstName(‘Luciano’)) echo ‘$user now has the first name ’, $user->getFirstName(); else // If the method returns false, something is up echo ‘That first name isn’t valid’; ?>

There’s quite a bit happening in the myUser class now so let’s analyse what’s going on. Something obvious is that the only difference between declaring a method and declaring a function is that that a method is declared within a class’s curly braces. The example above declares the public visibility identifier on one function but not the other to illustrate that public is the default visibility of methods. Not declaring an identifier will mean the method is publicly accessible.

function setFirstName($name) defines the method setFirstName that will accept the argument $name , using a simple check to determine if $name contains only letters from the alphabet. If it is alphabetic, $name will be assigned to the firstName property using the special variable $this . $this refers to the current object instance that is calling the method

$this->firstName = $name;

is exactly the same as

$user->firstName = $name;

Anytime you need to refer to the current object calling your method (in the case above $user), use the $this special variable – this removes all headaches about how to address a certain object.

The next method is named getFirstName and will return the object’s current firstName property – again note that we are using the special $this variable which is really saying “Return the value of the firstName property for the $user object”.

In the code above you have now instantiated the object $user and called (invoked) the methods defined. So invoking a method is the same as calling a function except you preceed it with the variable name and ->

$user->setFirstName(‘Luciano’); //$variable->methodName($arguments)

ADDING A CONSTRUCTOR

You can now add methods that allow you to set and get all of the properties in a myUser object.

Although this has abstracted the properties and methods, it would be cumbersome to call a method and set every property each time you created an object. To fix this problem you can define what is known as a constructor method. In PHP5, the constructor function is a public method named __construct. As the name suggests, the constructor helps to build an object.

For your user class, define a constructor method to set all the properties at the same time the object is created.

<?php class myUser { private $firstName; private $lastName; private $userName; private $email; private $age; private $gender; // constructor method, accepts all properties // to be assigned when myUser object is instantiated function __construct($firstName, $lastName, $userName, $email, $age, $gender) { $this->firstName = $firstName; $this->lastName = $lastName; $this->userName = $userName; $this->email = $email; $this->age = $age; $this->gender = $gender; } //………………………………..further methods } //Instantiate the object using the contructor $user = new myUser(‘Luciano’, ‘Dinglini’, ‘Rakuli’, ‘rakuli@example.com’, 23, ‘Male’); echo ‘$user->firstName was set to ’, $user->getFirstName(), ‘ by a constructor method’; ?>

You will see from the above code that the only change to creating the object is to add the arguments accepted by the myUser constructor method – just like a function call only preceded by the new keyword. All of the properties are now set when the object is created.

In the example above, the constructor requires all values to be given when invoked. A user visiting a site might not want to give an email address or their age – you can overcome this by making some or all of the arguments for the constructor optional. By doing this, you can still create an object but fill the properties with default values until set later with methods.

When a user first arrives at your site, you might instantiate a user object from a constructor method that looks like

function __construct($userName = 'Guest', $firstName = '', $lastName = '') { $this->firstName = $firstName; $this->lastName = $lastName; $this->userName = $userName; }

This would allow set the userName property as ‘Guest’ if you didn’t include it when creating the object. Later, you could set the user name with a method that might be $user->setUserName(‘Rakuli’);

FLEXING YOUR PROPERTIES

That’s it! The basics of OOP in PHP, with what you know now you can create all of the methods for setting and getting your user’s properties.

The class could now look like this:

<?php class myUser { private $firstName; private $lastName; private $userName; private $email; private $age; private $gender; // myUser - constructor method, accepts all properties // to be assigned when object is instantiated function __construct($userName = 'Guest', $firstName = false, $lastName = false) { // delegate the setting of the properties to the defined methods $this->setUserName($userName); $this->setFirstName($firstName); $this->setLastName($lastName); } function setFirstName($name) { //Check that the data is valid for use as a firstname if (ctype_alpha($name)) { $this->firstName = $name; return true; } // Return false if the data is not valid return false; } function setLastName($name) { //Check that the data is valid for use as a lastName // We'll let them get away with having 1 hyphen and 1 apostrophe only if (substr_count($name, '-') > 1 || substr_count($name, ''') > 1) { // Sorry Mr O'reilly-O'brien I know you may be out there but // I'm keeping it simple for now return false; } if (ctype_alpha(str_replace(''', '', str_replace('-', '', $name)))) { $this->lastName = $name; return true; } // Return false if the data is not valid return false; } function setUserName($name) { //Check that the data is valid for use as a userName if (ctype_alpha($name)) { $this->userName = $name; return true; } // Return false if the data is not valid return false; } function setEmail($email) { // Very simple regex to check email validity if (preg_match("/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/", $email)) { $this->email = $email; return true; } // Bad email address return false; } function setAge($age) { // We'll make sure they're not still in diapers or trying to set a guiness world age records if (is_numeric($age) &amp;&amp; $age &gt; 5 &amp;&amp; $age < 120) { $this->age = (int) $age; return true; } // Lying about your age? return false; } function setGender($gender) { // Run a quick switch -- allows for a few methods of declaring your gender identity switch(strtoupper($gender)) { case 'MALE' : case 'M' : case 'MAN' : $this->gender = 'M'; return true; break; case 'FEMALE' : case 'F' : case 'WOMAN' : $this->gender = 'F'; return true; break; } // Gender remains ambiguous return false; } function getFirstName() { // Return the current value of firstName return $this->firstName; } function getLastName() { return $this->lastName; } function getUserName() { return $this->userName; } function getEmail() { return $this->email; } function getAge() { return $this->age; } function getGender() { return $this->gender; } } ?>

I can hear you saying now – but this is still only an array that validates data types it allows me to store and retrieve data but I can’t do anything with it. In its present form? Yes, but now you can get creative and start defining methods utilising the variables.

Try creating a method to say hello to your user:

/ This method will return a welcome message for the user function helloUser() { $message = ' '; $message .= 'Hello' . $this->userName; // If userName wasn’t given, this will show ‘Guest’ // If we have first and last names, we'll show those in brackets if ($this->firstName || $this->lastName) $message .= ' <span style="font-size: xx-small;">(' . ($this->firstName ? $this->;firstName : '') . ($this->lastName ? ' ' . $this->lastName : '') . ')</span>'; $message .= ' '; // Make a remark about their age? if ($this->age) $message .= ' It's nice to have a ' . $this->age . ' year old on this site! '; // return the message return $message; }

Now you can see that this method will deal with the context for you. It will display a nice hello and also the user’s real name -- but only if it’s set. This is the Abstraction that OOP allows. Once you have created this class all you ever have to worry about is $user->helloUser() and you will be returned a result without having to worry what’s going on in the object.

Using the ball analogy from earlier, you don’t have to worry about what’s affecting it, you just kick it and it’ll see where it lands – how it gets there is for the ball to sort out.

Now that you have the basics of OOP down you can build objects and work with the properties in any way you like and the beauty is that when you want the result, you never have to do more than $user->askForIt()

PASS THE OBJECT TO YOUR LEFT

Now that you can define classes, build objects and work with the object’s methods you may wonder how you would go about maintaining state as promised above. You can do this using two of PHP’s most useful functions.

serialize() and unserialize()

After instantiating an object and working with the methods to flesh out its properties, you can pass the object through serialize to convert the object – and all of its properties -- to a string. This is nothing more than a normal string that you can pass it from page to page with $_SESSION or even store in a database. When you want to use the object again, you can revive it using unserialize.

PHP5 also has a couple of special methods that you can define that will be run when you serialize and unserialize objects.

__sleep – When you serialize an object, __sleep will be run on your object. You can use it to clean up properties or data that doesn’t need to persist. For example, you might disconnect from a database or release resource handles.

– When you serialize an object, __sleep will be run on your object. You can use it to clean up properties or data that doesn’t need to persist. For example, you might disconnect from a database or release resource handles. __wakeup – When you unserialize an object (or wake it up as it may be), you can use this function to restore properties or data lost when sleeping. You may reconnect to a database or grab hold of those resource handles again.

NB: In order to unserialize an object, you must have the class that it was created from included or defined in the current script. This is achieved by simply creating your class in a separate .php file that can be included when needed.

IT RUNS IN THE FAMILY

Inheritance is one of the most powerful philosophies of Object Oriented Programming. The ideological roots are founded in the evolution of the human race.

When a child is born, it inherits various features (properties) and behaviours (methods) from its parent. It isn’t a carbon copy of the parent though. It may behave slightly differently and will have some different features. This child may then have children of its own, with features and behavior slightly different again.

In OOP, the premise is exactly the same. There are parent classes, these can then be extended by child classes. The child class inherits most of the properties and methods from the parent but can also re-declare them so they behave differently to the parent.

The concept can be quite obscure initially so an example may be best. Take your myUser class and change the declared properties to protected . (Remember that protected properties can be accessed within an object instance and also within child object instances.)

It’s now time to create a child class that will extend the parent class:

<?php class myChildUser extends myUser { //myChildUser extends myUser so there is no need to declare // all the properties again, just declare properties that are unique to the child class private $petsName; private $twitterName; // Child constructor will also call parent constructor function __construct($petsName, $twitterName, $firstName, $lastName, $userName, $email, $age, $gender) { $this-&gt;petsName = $petsName; $this-&gt;twitterName = $twitterName; //use the parent constructor to set the remaining properties parent::__construct($firstName, $lastName, $userName, $email, $age, $gender); } // override the getLastName function to return pet name instead (sneaky) function getLastName() { return $this-&gt;petsName; } //………………………………..further methods } //Instantiate the child object $user = new myChildUser(‘Luciano’, ‘Dinglini’, ‘Rakuli’, ‘rakuli@example.com’, 23, ‘Male’); echo ‘$user->firstName was set to ’, $user->getFirstName(), ‘ by even though the logic to do so is not in this class’; ?>

On initial inspection, this class looks just like the others that have been created so far but the differences are important to note.

The first is the way the class is declared. The declaration is normal at first you will notice that there is the additional extends myUser . The keyword extends means that this class extends (or inherits properties and methods from) the class myUser . So without anything more than this class declaration and some curly braces, you would have a full working class that does everything the parent myUser class does.

A child class that simply mimics its parent isn’t entirely useful though. The next part in this class declaration defines some properties that are private to the child. $petsName and $twitterName will only be available to instances of myChildUser . These properties will not be available in instances of the parent class.

You’re probably wondering what the deal is with the next part of the class declaration. Normally, PHP does not allow two functions to have the same name but myChildUser is declaring __construct after myUser already declared it. This very powerful concept is known as overriding a parent method. It allows you to have a child class with identical method names, just different results. For example, if you were getting the age from myChildObject , you may wish to convert years to months if the child is young enough. This processing isn’t required by the myUser class because you know all instances are of adults.

The final noteworthy difference from the simple child class above is shown inside the __construct method. It comes in the form of another PHP keyword parent . Just like the $this special variable, parent is only available inside an object instance of a class. parent allows you to run methods of the parent, including methods that are overridden in the child. The __construct method in myChildUser runs the parent::__construct method meaning that the one act of instantiating the myChildUser class, also achieves the effects of instantiating a myUser obj.

Inheritance will be one of the most revolutionary discoveries you will make in programming so I suggest playing with objects and inheritance, trying overrides and multiple generations of inheritance (where you create a child class of a child class) to show just how useful the concept is.

Popular PHP frameworks like CakePHP, use inheritance with almost all classes inheriting from one base class.

STATIC ELECTRICITY

One last concept to look at with the possibilities introduced by PHP5 objects is the use of static properties and methods to implement namespaces . (This is not true namespace support as found in other languages but a means to achieve a similar effect.)

What’s a namespace you ask? Think of a namespace as a library. The library has a name “Uptown Public Library” and inside it there is a book called “Special Book”. One town over, there is a library called “Downtown Library”, it also has a book called “Special Book”. Each library has a different edition of the book and they are very different in all but name. “Special Book” from one library would be very different to “Special Book” from another.

This is the concept of namespaces. You can have functions and variables with the same name, except they are part of a different namespace.

Again, this is an abstract idea at first and an example will help.

<? php class namespace1 { static $val = 1; static function method () { return 1; } } class namespace2 { static $val = 2; static function method () { return 2; } } echo namespace1::$val, namespace1::method(); echo namespace2::$val, namespace2::method(); // Output will be 1122 ?>

So by defining static properties and methods of classes, you can treat them just like variables and functions in procedural programming. To access a class’s static properties and methods you use the class name two colons plus the property or variable name. classname::$staticprop classname::staticmethod()

You cannot use the parent or $this keywords inside static properties because they are not attached to an object instance. Trying to use these keywords will result in a PHP error.

Using classes as namespaces means you can define multiple variables and functions that have the same name. You can then use them by calling them statically through their class name.

Okay, better recap

So to sum up what we have covered in this basic introduction to OOP.

Why Use It?

OOP allows you to create individual blocks of self maintained code. The objects can take care of the processing and context, leaving you to work with the results.

How Do I Use It?

In PHP you use the class keyword to define the blueprint – or cookie cutter – and fill this class with properties (using the Visibility Identifiers to define where the property or method can be accessed from) and methods (defined just like normal functions) that your object will contain. When you’re ready to create an object, you use the new keyword with your class name.

If you want a method to be invoked when instantiating an object, you define a constructor method using the special __construct method name, you can then pass arguments that will be attached to variables or used for other actions when creating an object.

Another look at a class definition:

<? php class className { // Although it's not advisible, I can access and change this property // Using the following syntax on the variable that holds my object // $myObject->property = 'Setting the value'; // $value = $myObject->property . ' getting the value'; public $property; function __construct() { // This will be run when I create an object // I put the object in a variable using the new keyword // $myObject = new className(); } function method() { // I can use this method with the syntax // $variable->method(); } } ?>

Won’t you think of the children?

You can create a class that extends another, inheriting its properties by using the extends keyword. Inside of a child class, you can add new properties and methods, as well as overriding methods defined in the parent class. If you want to access a method found in the parent, you can use the parent keyword to call it. parent::methodname()

Statically Speaking

Using classes full of static properties and methods gives you a way of grouping data by namespace (where the name is the name of the class)

Anything Else I Should Know?

To store your objects as a string to move around in the $_SESSION superglobal or save to a database you can use the serialize function.

$string = serialize($myObject);

$myObject = unserialize($string);

You need to make sure PHP can find the class definition when using unserialize.

That concludes this quick overview of Abstraction For The Rest of us. Using the tools above, you should be able to take advantage of the logical programming OOP allows.

Glossary of OOP terms