After going through a manual that teaches the syntax of a language, coders generally find themselves capable of coding simple applications. But the jump to the next level cannot be made simply by reading a manual. It requires a coder to grasp abstract ideas. At first sight, these ideas seem immaterial, but when put together with creativity, these abstract ideas become powerful tools. PHP5's improvements in Object Oriented Programming (OOP) have made the language significantly more powerful. But, because of their apparent irrelevance, it is difficult to appreciate the power of PHP5. I hope that this article will help you understand these concepts at a level beyond the syntax, allow you to be creative with them and advance from “basic PHP”. For me, knowing “basic PHP” is being able to use 'Control Structures' like 'if', 'for', 'foreach' and 'while'; understanding the uses of functions; being able to process input from the user (using post, get, sessions and cookies); and using databases, like MySQL. In this article, we are going to look at some of the concepts in Object Oriented Programming (OOP) that PHP 5 brings. The PHP manual (www.php.net/manual/) covers these topics under a section called “Classes and Objects (PHP 5)”, so make sure you have it open as you go through this article. If you don’t have any previous experience of OOP-compatible languages, you may not find learning OOP concepts a breeze. Occasionally, you may not see the purpose of a certain “feature” in PHP. Don't worry about it. If you read the examples I give and go back to the topic, you will be able to pick up the concept without any problem! To begin with, go through the section on Classes and Objects (PHP4) in the manual. But, don't just read through it – try to imagine situations in which each one of the features will come to use. For instance, ask yourself, “Why should I extend a class? Where can I use a constructor to make a class easier to use?” Understanding where to use a particular tool is more important than learning it's syntax! When you encounter the concept of extending classes, try to visualize a core class and an extended class built around it. The core class performs generic tasks, while the extended class performs specific tasks, making it 'complete'. We will discuss this in more detail soon. The first topic you learn about in “Classes and Objects (PHP 5)” is the __autoload magic function. The double underscores (__) before a function name makes the function a magic function – a function that PHP will call (automatically) when a specific event takes place. You have seen this before: __sleep and __wakeup in PHP4, remember? They are called magic functions because you never call them, they get called automatically. If you've fooled around with classes, you may have found that it is easier to save each class in separate files and include the appropriate file when you need the class. You should then be familiar with this error: Fatal error: Class 'MyClass' not found in ...
If you haven't seen this error before, it is the error that you get when you have forgotten to include the file you saved the class in (usually the file includes/MyClass.inc.php). This is not a big issue if you have only four or five classes that you need to keep track of. But, when you start working on larger projects, you will find that including each and every class appropriately becomes a task in itself.
1
The autoload function lets you include pages when PHP cannot find a class. When you try to create an instance of the class MyClass, but have not defined it, PHP will call __autoload("MyClass");. For example: function __autoload($class_name) { require_once("includes/$class_name.inc.php");//include_once is also fine. } $instance = new MyClass; When PHP cannot find MyClass defined on your page, it will call __autoload("MyClass");. This will include includes/MyClass.inc.php and then create an instance. You no longer need to keep
track of each and every class that you use! In PHP5’s OOP you will encounter many other magic functions. Now that you are familiar with the concept of magic functions, you should be able to understand the purpose of other magic functions easily. The next section is about other magic functions: the constructors and destructors. The constructors and destructors functions are called when a class is initialized and killed respectively. When you are learning about constructors and destructors, think of what you might use them for. Think of situations where you will need to prepare a class before it is used or do some cleaning up once it is killed. (Stop and think a little before reading my example). Let us say we have a class that is managing our database connections. We just want to create an instance and start working with the database. In the constructor, we make a connection to the database to make the class ready to handle data. Since we also know that after a PHP page is executed, the classes are killed, we can use the destructor function to close the connection with the database. Life just became a lot easier, as we never have to keep track of database connections again. They are opened and closed automatically! The next topic in the manual covers “Visibility”, “Scope Resolution Operator (::)” and the “Static Keyword”. At first sight, having variables and functions that are not related to instances of classes, but to classes themselves seems pointless. However, this feature is actually very useful. The singleton is a good example of a pattern that uses this very tool to ensure that there is only one instance of a class (often you don't want two instances of a class). A static variable is made to save an instance of the class itself (i.e. you are storing an instance of the class inside the class). A new instance of the class is not allowed to be created, and only the saved instance can be used (or created if has not been created). This way, only one instance of the class can be created. Look up the “Patterns” section of the manual for the singleton pattern code. As we move on, you will notice that PHP5 helps us force certain structures in the code on ourselves. Yes, it does seem a little silly initially, “Why would I like to force myself to code in a certain way?” Whether you are coding alone, or in a group, this capability of PHP5 helps individual objects (classes) co-ordinate between themselves to achieve greater efficiency in the code. Remember extends? We had talked of building around a core object to make a complete object. Now we're not just extending classes, we are ensuring that a class is extended. By using the abstract keyword, you can make sure that an instance of the class is not created and only children of the class can be initialized. Aha! I hear you saying, “Why should I force a coder to extend a class? Should a coder want to extend a class, the coder will extend the class.” There is no better way to find the answer than trying to figure it out yourself. So, stop and think of a situation where you will need to force a class to be extended.
2
I'll give you a simple example. Say we are coding a dog and a human being. Amongst other things, we want to make them run when given a signal. They have things in common, and we would like to take advantage of that by making a core class – called animal. Both the human and the dog receive signals telling them to run. They handle signals by sending instructions to the muscles to contract and expand appropriately. But, dogs run on four legs, while humans run on two! We could not possibly have the same code for both. The animal class can be coded so that it can perform all the common tasks possible, and forces the specifics to be coded. We code the class to see, breathe, etc. But we would also like to be sure that the animal can run, without needing to know how it is going to run. When the animal class is extended, we want to ensure that the function run(); is defined. We simply add the following line in the animal class: abstract public function run();
Now, not only can we just call the function run(); without defining the function, we can be sure that it exists. Though how it will run – on two legs or four; by hopping, skipping or sprinting – will be determined by the child class. If it has a broken leg, it will cry in pain and throw an exception. (Just a joke! You will encounter exceptions later in the manual). Congratulations! You have, now, understood the abstract keyword and are also armed to use the final keyword! Now let’s go on to the next topic: Interfaces and Overloading. I hope you’ve been taking breaks, otherwise your ‘brain class’ will get ‘overloaded’! Interfaces, too, are very useful in forcing a structure on a class. Let's take the example of an animal interface. This interface will force any class that implements it to have the functions to respire, grow, feed, etc. Imagine I want to give an animal some food to eat. I can then define a function in the class me as follows: public function donate_food(animal $receiver, $amount) { ... $receiver->eat($food); }
Because I know that the animal interface requires an eat() method, I can be sure that $receiver has an eat() method. If you have not encountered type hinting before, it would be useful to know that donate_food(animal $receiver, ...) means $receiver has to implement an animal interface or extend an animal class, otherwise an error will be thrown. 'Overloading' lets you control the usage of variables and methods in a classes. This concept is a little confusing when you first encounter it. You can write magic functions that are called when an attempt to use an undefined method or variable is made. One of the first uses I found for this was the handling of dates/times. Generally, it is easy to use (Unix) timestamps (number of seconds after January 1, 1970 GMT) instead of date/times. Timestamps can be easily handled, stored and can be used to display a date in any format. We would like to convert all the dates/times a class receives into timestamps and convert them the appropriate format when required. To do it in the PHP4 way, we would make a function called set_date(); or get_date();. This would mean that we don't 'set' and 'get' the date variable like we set and get other variables: $myclass->title = "Hello!"; //Here we set 'title' like a normal variable $myclass->set_date("2 Jan 2003"); //Here we have to call a function to set the 'date' variable, and cannot do it in the conventional way. echo($myclass->title."was created on ".$myclass->get_date("j\<\s\u\p\>S\<\/\s\u\p\> F Y"));// Here, we have to get the 'date' variable using a function
3
Let's now achieve the same result by using the features of PHP5: class MyClass { public $timestamp;
public function __set($var, $val) { if($var == "date") { $this->timestamp = strtotime($val); } } public function __get($var) { if($var == date) { return date("j\<\s\u\p\>S\<\/\s\u\p\> F Y", $this->timestamp); } }
} $test = new MyClass; $test->date = "4 Jan 03"; //Here we can set the 'date' in the conventional manner. echo($test->date); //And we get the 'date' in the conventional way too 4th January 2003 echo(date("F j 'y", $test->timestamp)); //January 4 '03 //We still have the option of changing the date format (as shown above)
Now date behaves just like any other variable. But the variable date doesn't actually exist! When date is edited, the input is converted to a timestamp and saved to $timestamp. Similarly, the timestamp is converted back to the date when an attempt to 'get' date is made. Apart from uniformity, this also brings a lot of flexibility in the way dates are used. The class will accept any date format as input and can return any date format as output, without using confusing methods of getting and setting variables. Visualizing situations where you can use the concepts you are learning can be very helpful. You will be able to identify the most efficient tool, from your ever expanding toolbox, to solve the problem you are facing. Like this timestamp example, the problem could have been solved by making a function and destroying the uniformity of the code. But by using the right tool we were able to make the class more uniform and flexible. You learn to pedal a bicycle when someone is holding and balancing the bicycle for you. But, you actually learn to ride one only when the bicycle is released. I'm going to let go now (not that I was actually holding your bicycle) and hope that you can find your balance. Remember, nobody learns to cycle without scraping their knees. So make sure you are always fooling around with these features. Only then will you discover the marvelous things you can do with each one of them! Before I end, I urge you to develop two good habits. The first and possibly the most important habit for coders is to code neatly. By 'neatly' I mean keep lines of code well spaced out; use descriptive variable and function names; and make explanatory comments while coding. Another very useful habit is to make a clear plan of the structure of your project, before you begin to code. Classes are very powerful tools that hold your project together. Your plan should be for the long run – ensure that the growth of your classes in not hindered by restrictive structures within. Best of luck! Umang 4
“Advancing From Basic PHP” by Umang is licensed under a Creative Commons Attribution 3.0 Unported License.
5