Object Oriented Programming in PHP
Object Oriented Programming in PHP
This article introduces Object Oriented Programming (OOP) in PHP. Luis shows you
how to code less and better by using some OOP concepts and PHP tricks.Object
Oriented Programming in any language is the use of objects to represent functional
parts of an application and real life entities. For example you may have a Person
object to hold the data related to a person and even provide some functionality that
this person may be capable of.
Object Oriented Programming has long been used in games to represent the
objects such as a User or an Enemy, or even a Weapon. This amazing way of
programming has proven just as useful in software and web development.
In my opinion any OOP language should have:
• Abstract data types and information hiding
• Inheritance
• Polymorphism
This can all be done using PHP classes:
<?php
class Something {
// In OOP classes are usually named starting with a cap letter.
var $x;
function setX($v) {
// Methods start in lowercase then use lowercase to separate
// words in the method name example getValueOfArea()
$this->x=$v;
}
function getX() {
return $this->x;
}
}
?>
Of course you can use your own nomenclature but having a standardized one is
useful.
$obj=new Something;
Then you can use member functions like:
$obj->setX(5);
$see=$obj->getX();
The setX member function assigns 5 to the x data member in the object obj (not
in the class), then getX returns its value; 5 in this case.
You can access the data members from the object reference using for example:
$obj->x=6. However, this is not a very good OOP practice.
I encourage you to set data members by defining methods to set them and
access the data members by using retrieving methods.
You'll be a good OOP programmer if you consider data members inaccessible and
only use methods from the object handler. Unfortunately PHP doesn't have a way to
declare a data member private so bad code is allowed.
Inheritance
Inheritance is easy in PHP using the extends keyword:
<?php
function getY() {
return $this->y;
}
}
?>
Objects of the class "Another" now have all the data members and methods of the
parent class (Something) plus its own data members and methods.
You can use:
$obj2=new Something;
$obj2->setX(6);
$obj2->setY(7);
Constructors
You might define constructors in your classes; constructors are methods with the
same name as the class and are called when you create an object of the class, for
example:
<?php
class Something {
var $x;
function Something($y) {
$this->x=$y;
}
function setX($v) {
$this->x=$v;
}
function getX() {
return $this->x;
}
}
?>
$obj=new Something(6);
function Something($x="3",$y="5");
Then:
Default arguments are used in the C++ way so you can't pass a value to Y and let
X take the default value. Arguments are assigned from left to right and when no more
arguments are found if the function expected more they take the default values.
When an object of a derived class is created only its constructor is called the
constructor of the Parent class is not called.
This is a gotcha of PHP because constructor chaining is a classic feature of OOP, if
you want to call the base class constructor you have to do it explicitly from the
derived class constructor.
It works because all methods of the parent class are available at the derived class
due to inheritance.
<?php
function Another() {
$this->y=5;
$this->Something(); //explicit call to base class constructor.
}
?>
Abstract Classes
A nice mechanism in OOP is the use of Abstract Classes; abstract classes are
classes that cannot be instantiated and the only purpose is to define an interface for
its derived classes.
Designers often use Abstract classes to force programmers to derive classes from
certain base classes, so they can be certain that the new classes have some desired
functionality.
There's no standard way to do that in PHP but, if you do need this feature, just
define the base class and put a "die" call in its constructor so you can be sure that
the base class is never instantiated.
Now define the methods (interface) putting "die" statements in each one so if in a
derived class a programmer doesn't override the method then an error is raised.
Furthermore you might need to be sure, since PHP has no types, that some object
is from a class derived from your base class, then add a method in the base class to
identify the class (return "some id") and verify this when you receive an object as an
argument.
Of course this doesn't work if the evil programmer overrides the method in the
derived class but generally the problem is dealing with lazy programmers not evil
ones! Of course it’s better to keep the base class unreachable from the programmers,
just print the interface and make them work!
There're no destructors in PHP.
Overloading
Overloading (which is different from overriding) is not supported in PHP. In OOP
you "overload" a method when you define two/more methods with the same name
but different number or type of parameters (depending upon the language).
PHP is a loosely typed language so overloading by types won't work, however
overloading by number of parameters doesn't work either.
It's very nice sometimes in OOP to overload constructors so you can build the
object in different ways (passing different number of arguments). A trick to do
something like that in PHP is:
<?php
class Myclass {
function Myclass() {
$name="Myclass".func_num_args();
$this->$name();
//Note that $this->$name() is usually wrong but here
//$name is a string with the name of the method to call.
}
function Myclass1($x) {
code;
}
function Myclass2($x,$y) {
code;
}
}
?>
With this extra working in the class the use of the class is transparent to the user:
Polymorphism
Polymorphism is defined as the ability of an object to determine which method to
invoke for an object passed as argument in runtime time. For example if you have a
class figure which defines a method draw and derived classes circle and rectangle,
where you override the method draw you might have a function which expects an
argument x and then call $x->draw().
If you have polymorphism the method draw called depends of the type of object
you pass to the function.
Polymorphism is very easy and natural in interpreted languages as PHP (try to
imagine a C++ compiler generating code for this case, which method do you call?
You don't know yet which type of object you have! OK, this is not the point).
So PHP happily supports polymorphism.
<?php
function niceDrawing($x) {
//Supose this is a method of the class Board.
$x->draw();
}
$obj=new Circle(3,187);
$obj2=new Rectangle(4,5);
?>
Serialization
PHP doesn't support persistent objects; in OOP persistent objects are objects that
keep its state and functionality across multiple invocations of the application. This
means having the ability to save the object to a file or database and then load the
object back. The mechanism is known as serialization.
PHP has a serialize method which can be called for objects, the serialize method
returns a string representation of the object. However serialize saves the data
members of the object but not the methods.
In PHP4 if you serialize the object to string $s, then destroy the object, then
unserialize the object to $obj you might still access the object methods! I don't
recommend this because:
1. The documentation doesn't guarantee this behaviour so in future versions it
might not work.
2. This might lead to 'illusions' if you save the serialized version to disk and exit
the script. In future runs of the script you can't unserialize the string to an
object and expect the methods to be there because the string representation
doesn't have the methods.
You can serialize associative arrays and arrays to save them to disk too.
Example:
<?php
$obj=new Classfoo();
$str=serialize($obj);
// Save $str to disk
?>
You have the data members recovered but not the methods (according to the
documentation). This leads to $obj2->x as the only way to access the data members
(you have no methods) so don't try this at home.
There're some ways to fix the problem but I leave it up to you because they are
too dirty for this neat article. Full serialization is a feature I'd gladly welcome in PHP.
$obj=new $type();
$obj->action();
?>
This is a very nice feature of PHP, you might then call the display method of $obj
or any other method regardless the type of object you have.
With this technique you don't have to touch the processing script when you add a
new type of object, just add a class to handle it. This is quite powerful, just define the
methods all objects regardless of its type should have, implement them in different
ways in different classes and use them for any type of object in the main script, no
ifs, no 2 programmers in the same file, eternal happiness.
Do you agree programming is easy, maintenance is cheaper and reusability is real
now?
If you command a group of programmers it's easy to divide the tasks, each one
might be responsible for a type of object and the class that handles it.
Internationalization can be done using this technique, apply the proper class
according to a language field selected by the user, etc.
$herring=serialize($obj);
$vec=explode(':',$herring);
$nam=str_replace("\"",'',$vec[2]);
?>
So suppose you create a class "Universe" and force that all classes must extend
universe, you can define a method clone in Universe as:
<?php
class Universe {
function clone() {
$herring=serialize($this);
$vec=explode(':',$herring);
$nam=str_replace("\"",'',$vec[2]);
$ret=new $nam;
return $ret;
}
}
Then:
$obj=new Something();
//Something extends Universe !!
$other=$obj->clone();
?>
What you get is a new object of class Something created the same way as using
new; the constructor is called, etc. I don't know if this is useful for you but the
Universe class which knows the name of the derived class is a nice concept to
experiment with. The only limit is your imagination.
Note: I'm using PHP4, some of these examples may not work in PHP3.
As you can see Object Oriented Programming is very powerful and in many
situations the best way to build applications in PHP and other OO capable languages.
I hope this helps you with your development and good luck with it.