Object Oriented Concepts In PHP5 (Part 2)
1.DESTRUCTORS
Destructor functions
are the opposite of constructors. They are called when the object is being destroyed (for example, when there are no more references to the object). As PHP makes sure all resources are freed at the end of each request, the importance of destructors is limited. However, they can still be useful for performing certain actions, such as flushing a resource or logging information on object destruction. There are two situations where your destructor might be called: during your script’s execution when all references to an object are destroyed, or when the end of the script is reached and PHP.ends the request. The latter situation is delicate because you are relying on
some objects that might already have had their destructors called and are not accessible anymore. So, use it with care, and don’t rely on other objects in your destructors.
Defining a destructor is as simple as adding a __destruct() method to your class:
class MyClass {
function __destruct()
{
print "An object of type MyClass is being destroyed\n";
}
}
$obj = new MyClass();
$obj = NULL;
This script prints
An object of type MyClass is being destroyed
In this example, when
$obj = NULL;
is reached, the only handle to the object is destroyed, and therefore the destructor is called, and the object itself is destroyed. Even without the last line, the destructor would be called, but it would be at the end of the request during the execution engine’s shutdown.
2. ACCESSING METHODS AND PROPERTIES USING THE $this VARIABLE
During the execution of an object’s method, a special variable called $this is automatically defined, which denotes a reference to the object itself. By using this variable and the -> notation, the object’s methods and properties can be further referenced. For example, you can access the $name property by using $this->name (note that you don’t use a $ before the name of the property). An object’s methods can be accessed in the same way; for example, from inside one of person’s methods, you could call getName() by writing $this->getName().
2.1 A public, protected, and private Properties
A key paradigm in OOP is encapsulation and access protection of object properties
(also referred to as member variables). Most common OO languages have three main access restriction keywords: public, protected, and private.When defining a class member in the class definition, the developer
needs to specify one of these three access modifiers before declaring the member
itself. In case you are familiar with PHP 3 or 4’s object model, all class
members were defined with the var keyword, which is equivalent to public in PHP 5. var has been kept for backward compatibility, but it is deprecated, thus, you are encouraged to convert your scripts to the new keywords:
class MyClass {
public $publicMember = "Public member";
protected $protectedMember = "Protected member";
private $privateMember = "Private member";
function myMethod(){
// ...
}
}
$obj = new MyClass();
This example will be built upon to demonstrate the use of these access
modifiers.First, the more boring definitions of each access modifier:
private:Private members are similar to protected members because they can be accessed only from within an object’s method. However, they are also inaccessible from a derived object’s methods. Because private properties aren’t visible from inheriting classes, two related classes may declare the same private properties. Each class will see its own private copy, which are unrelated.
protected:Protected members can be accessed only from within an object’s method—for example, $this->protectedMember. If another class inherits a protected member, the same rules apply, and it can be accessed from within the derived object’s methods via the special $this variable.
public:Public members can be accessed both from outside an object by using $obj->publicMember and by accessing it from inside the myMethod method via the special $this variable (for example, $this->publicMember). If another class inherits a public member, the same rules apply, and it can be accessed both from outside the derived class’s objects and from within its methods.
Usually, you would use public for members you want to be accessible
from outside the object’s scope (i.e., its methods), and private for members who
are internal to the object’s logic. Use protected for members who are internal
to the object’s logic, but where it might make sense for inheriting classes to
override them:
class MyDbConnectionClass {
public $queryResult;
protected $dbHostname = "localhost";
private $connectionHandle;
// ...
}
class MyFooDotComDbConnectionClass extends MyDbConnectionClass {
protected $dbHostname = "foo.com";
}
This incomplete example shows typical use of each of the three access
modifiers. This class manages a database connection including queries made
to the database:
☞ The connection handle to the database is held in a private member,because it is used by the class’s internal logic and shouldn’t be accessible to the user of this class.
☞ In this example, the database hostname isn’t exposed to the user of theclass MyDbConnectionClass. To override it, the developer may inherit from the initial class and change the value.
☞ The query result itself should be accessible to the developer and has, therefore, been declared as public.
Note that access modifiers are designed so that classes (or more specifically,
their interfaces to the outer world) always keep an is-a relationship during
inheritance. Therefore, if a parent declares a member as public, the
inheriting child must also declare it as public. Otherwise, the child would not
have an is-a relationship with the parent, which means that anything you can
do with the parent can also be done with the child.
2.2 public, protected, and private Methods
Access modifiers may also be used in conjunction with object methods, and the rules are the same:
☞ public methods can be called from any scope.
☞ protected methods can only be called from within one of its class methods or from within an inheriting class.
☞ private methods can only be called from within one of its class methods and not from an inheriting class. As with properties, private methods may be redeclared by inheriting classes. Each class will see its own version of the method:
class MyDbConnectionClass {
public function connect()
{
$conn = $this->createDbConnection();
$this->setDbConnection($conn);
return $conn;
}
protected function createDbConnection()
{
return mysql_connect("localhost");
}
private function setDbConnection($conn)
{
$this->dbConnection = $conn;
}
private $dbConnection;
}
class MyFooDotComDbConnectionClass extends MyDbConnectionClass {
protected function createDbConnection()
{
return mysql_connect("foo.com");
}
}
This skeleton code example could be used for a database connection class. The connect() method is meant to be called by outside code. The createDbConnection() method is an internal method but enables you to inherit from the class and change it; thus, it is marked as protected. The setDbConnection() method is completely internal to the class and is therefore marked as private.
2.3 Static Properties
As you know by now, classes can declare properties. Each instance of the class (i.e., object) has its own copy of these properties. However, a class can also contain static properties. Unlike regular properties, these belong to the class itself and not to any instance of it. Therefore, they are often called class properties as opposed to object or instance properties. You can also think of static properties as global variables that sit inside a class but are accessible from anywhere via the class.
Static properties are defined by using the static keyword:
class MyClass {
static $myStaticVariable;
static $myInitializedStaticVariable = 0;
}
To access static properties, you have to qualify the property name with the class it sits in
MyClass::$myInitializedStaticVariable++;
print MyClass::$myInitializedStaticVariable;
This example prints the number 1.
If you’re accessing the member from inside one of the class methods, you may also refer to the property by prefixing it with the special class name self, which is short for the class to which the method belongs:
class MyClass {
static $myInitializedStaticVariable = 0;
function myMethod()
{
print self::$myInitializedStaticVariable;
}
}
$obj = new MyClass();
$obj->myMethod();
This example prints the number 0.
You are probably asking yourself if this whole static business is really useful.
One example of using it is to assign a unique id to all instances of a class:
class MyUniqueIdClass {
static $idCounter = 0;
public $uniqueId;
function __construct()
{
self::$idCounter++;
$this->uniqueId = self::$idCounter;
}
}
$obj1 = new MyUniqueIdClass();
print $obj1->uniqueId . "\n";
$obj2 = new MyUniqueIdClass();
print $obj2->uniqueId . "\n";
This prints
1
2
The first object’s $uniqueId property variable equals 1 and the latter object equals 2.
2.4 Static Methods
Similar to static properties, PHP supports declaring methods as static. What this means is that your static methods are part of the class and are not bound to any specific object instance and its properties. Therefore, $this isn’t accessible in these methods, but the class itself is by using self to access it. Because static methods aren’t bound to any specific object, you can call them without
creating an object instance by using the class_name::method() syntax. You may also call them from an object instance using $this->method(), but $this won’t be defined in the called method. For clarity, you should use self::method()
instead of $this->method().
Here’s an example:
class PrettyPrinter {
static function printHelloWorld()
{
print "Hello, World";
self::printNewline();
}
static function printNewline()
{
print "\n";
}
}
PrettyPrinter::printHelloWorld();
The example prints the string "Hello, World" followed by a newline. Although it is a useless example, you can see that printHelloWorld() can be called on the class without creating an object instance using the class name, and the static method itself can call another static method of the class print- Newline() using the self:: notation. You may call a parent’s static method by using the parent:: notationn which will be covered later in next post.