Friday, February 27, 2015

Storing Objects as Strings

Objects that we create in PHP are stored as binary data in memory. Although we can pass objects around using PHP variables, functions, and methods, sometimes its useful to be able to pass objects to other applications, or via fields in Web forms, for example.

PHP provides two functions to help us with this:

    serialize() converts an object — properties, methods, and all — into a string of text
    unserialize() takes a string created by serialize() and turns it back into a usable object

The following example shows these two functions in action:

 class Person
 {
   public $age;
 }
 
 $harry = new Person();
 $harry->age = 28;
 $harryString = serialize( $harry );
 echo "Harry is now serialized in the following string: '$harryString'<br />";
 echo "Converting '$harryString' back to an object...<br />";
 $obj = unserialize( $harryString );
 echo "Harry's age is: $obj->age<br />";


This code creates a simple Person class with one property, $age. It then creates a new Person object, $harry, and sets its $age property to 28. It calls serialize() to convert the object to a string, which it displays. Finally, it converts the string back into a new object, $obj, then displays its $obj->age property (28). Here's the result of running the script:

 Harry is now serialized in the following string: 'O:6:"Person":1:{s:3:"age";i:28;}'
 Converting 'O:6:"Person":1:{s:3:"age";i:28;}' back to an object...Harry's age is: 28

We can actually use serialize() and unserialize() on any PHP value, not just objects. However, it's especially useful with objects and arrays, because these structures can be quite complex and it's not easy to convert them to strings in any other way.

What's more, when we serialize an object, PHP attempts to call a method with the name __sleep() inside the object. We can use this method to do anything that's required before the object is serialized. Similarly, We can create a __wakeup() method that is called when the object is unserialized.

__sleep() is useful for cleaning up an object prior to serializing it, in the same way that we might clean up in a destructor method. For example, we might need to close database handles, files, and so on. In addition, __sleep() has another trick up its sleeve. PHP expects our __sleep() method to return an array of names of properties to preserve in the serialized string. We can use this fact to limit the number of properties stored in the string — very useful if our object contains a lot of properties that we don't need to store.

Here's an example:

class User {
   public $username;
   public $password;
   public $loginsToday;
 
   public function __sleep() {
     // (Clean up; close database handles, etc)
     return array( "username", "password" );
   }
 }
 
 $user = new User;
 $user->username = "harry";
 $user->password = "monkey";
 $user->loginsToday = 3;
 echo "The original user object:<br />";
 print_r( $user );
 echo "<br /><br />";
 echo "Serializing the object...<br /><br />";
 $userString = serialize( $user );
 echo "The user is now serialized in the following string:<br />";
 echo "$userString<br /><br />";
 echo "Converting the string back to an object...<br /><br />";
 $obj = unserialize( $userString );
 echo "The unserialized object:<br />";
 print_r( $obj );
 echo "<br />";


This code outputs the following:

 The original user object:
 User Object ( [username] => harry [password] => monkey [loginsToday] => 3 )
 
 Serializing the object...
 
 The user is now serialized in the following string:
 O:4:"User":2:{s:8:"username";s:5:"harry";s:8:"password";s:6:"monkey";}
 
 Converting the string back to an object...
 
 The unserialized object:
 User Object ( [username] => harry [password] => monkey [loginsToday] => )


In this example, we don't care about preserving the number of times the user has logged in today, so the __sleep() method only returns the "username" and "password" property names. Notice that the serialized string doesn't contain the $loginsToday property. Furthermore, when the object is restored from the string, the $loginsToday property is empty.

In a real-world situation, We make sure that we don't transmit sensitive information such as usernames as passwords as plain text strings if there's a chance that the data might be intercepted or read by untrusted third parties.

If we do need to preserve all our object's properties, we can use the built-in get_object_vars() function to get an associative array of all the properties in the object, then we use the array_keys() function to get just the property names as an array, which we can then return from our __sleep() method:

class User {
   public $username;
   public $password;
   public $loginsToday;
 
   public function __sleep() {
     // (Clean up; close database handles, etc)

     return array_keys( get_object_vars( $this ) );

   }
 }


Finally, here's an example that shows the __wakeup() method in action:

 class User
 {
   public function __wakeup()
 {
     echo "Yawn... what's for breakfast?<br />";
   }
 }
 
 $user = new User;
 $userString = serialize( $user );
 $obj = unserialize( $userString );  // Displays "Yawn... what's for breakfast?"

Friday, February 20, 2015

PHP : Automatically Loading Class Files

Generally it's a good idea to keep our classes in separate script files, one class per file. It also helps to name each class file after the class it contains. For example, we might create a class called Person and store it in a file called Person.php inside a classes folder (so that we know that Person.php contains a class). Or if we have created a class called Fruit, we might store it in a file called class.Fruit.php.

Then, when our script needs to create a Person object, it can include the Person.php file to create the class, then go ahead and create an object from the class:

 <?php
 require_once( "classes/Person.php" );
 $p = new Person();
 ?>

require_once() lets us include one PHP script file inside another, which means we can break up our PHP application into small, manageable script files. Not only does this good practice help to keep our scripts organized and maintainable, but it lets us take advantage of a nifty feature of PHP: class autoloading.

With autoloading, we create an __autoload() function somewhere in our script. This function should accept a class name as an argument. Then, whenever another part of our script attempts to create a new object from a nonexistent class, __autoload() is automatically called, passing in the class name. This gives our __autoload() function a chance to find and include the class file, thereby allowing the PHP engine to carry on and create the object.

Here's an example __autoload() function:

function __autoload( $className ) {
   $className = str_replace ( "..", "", $className );
   require_once( "classes/$className.php" );
 }

This function stores the name of the nonexistent class in a $className parameter. It then filters this parameter to ensure it contains no ".." substrings (which could potentially be used by an attacker to open files or folders above the classes folder). Finally, it calls PHP's require_once() function to load the file in the classes folder with the same name as the missing class. This should cause the class to be created, allowing the object in turn to be created from the class.

For example, imagine the same script contained the following code:

$p = new Person;

When the PHP engine encounters the new Person construct, it looks to see if the Person class has been defined. If not, it calls the previously defined __autoload() function. This in turn includes and runs the file Person.php inside the classes folder, which creates the class and allows the new Person object to be created.

If the PHP engine can't find an __autoload() function, or if our __autoload() function fails to load the Person class, the script exits with a "Class 'Person' not found" error.

spl_autoload_register()

The major drawback to the __autoload() function is that we can only provide one autoloader with it. PHP 5.1.2 introduced spl_autoload() which allows us to register multiple autoloader functions, and in the future the __autoload() function will be deprecated.

The introduction of spl_autoload_register() gave us (programmers) the ability to create an autoload chain, a series of functions that can be called to try and load a class or interface. For example:

<?php
function autoloadRegister($className) {
    $filename = "class/register/" . $className . ".php";
    if (is_readable($filename)) {
        require $filename;
    }
}

function autoloadPerson($className) {
    $filename = "class/person/" . $className . ".php";
    if (is_readable($filename)) {
        require $filename;
    }
}

spl_autoload_register("autoloadRegister");
spl_autoload_register("autoloadPerson");

Generally the functions are called in the order they’re registered, but the order can also be affected by additional arguments passed to spl_autoload_register(). It’s important to remember that once a function has been registered with spl_autoload_register(), the __autoload() function will no longer be called. If we have an __autoload() function we want to run as part of our autoloader chain, then we’ll have to register it with spl_autoload_register().

Friday, February 13, 2015

Php's Constructors and Destructors

Constructors and Destructors

When creating a new object, often it's useful to set up certain aspects of the object at the same time. For example, we might want to set some properties to initial values, fetch some information from a database to populate the object, or register the object in some way.

Similarly, when it's time for an object to disappear, it can be useful to tidy up aspects of the object, such as closing any related open files and database connections, or unsetting other related objects.

Like most OOP languages, PHP provides us with two special methods to help with these tasks. An object's constructor method is called just after the object is created, and its destructor method is called just before the object is freed from memory.

In the following sections we learn how to create and use constructors and destructors.

Setting Up New Objects with Constructors

Normally, when we create a new object based on a class, all that happens is that the object is brought into existence. (Usually we then assign the object to a variable or pass it to a function.) By creating a constructor method in our class, however, we can cause other actions to be triggered when the object is created.

To create a constructor, simply we add a method with the special name __construct() to our class. (That's two underscores, followed by the word "construct," followed by parentheses.) PHP looks for this special method name when the object is created; if it finds it, it calls the method.

Here's a simple example:

 class MyClass
 {
   function __construct()
 {
     echo "Whoa! I've come into being.<br />";
   }
 }
 
 $obj = new MyClass;  // Displays "Whoa! I've come into being."


The class, MyClass, contains a very simple constructor that just displays the message. When the code then creates an object from that class, the constructor is called and the message is displayed.

We can also pass arguments to constructors, just like normal methods. This is great for setting certain properties to initial values at the time the object is created. The following example shows this principle in action:

 class Person
 {
   private $_firstName;
   private $_lastName;
   private $_age;
 
   public function __construct( $firstName, $lastName, $age )
 {
     $this->_firstName = $firstName;
     $this->_lastName = $lastName;
     $this->_age = $age;
   }
 
   public function showDetails()
 {
     echo "$this->_firstName $this->_lastName, age $this->_age<br />";
   }
 }
 
 $p = new Person( "Harry", "Walters", 28 );
 $p->showDetails();  // Displays "Harry Walters, age 28"


The Person class contains three private properties and a constructor that accepts three values, setting the three properties to those values. It also contains a showDetails() method that displays the property values. The code creates a new Person object, passing in the initial values for the three properties. These arguments get passed directly to the __construct() method, which then sets the property values accordingly. The last line then displays the property values by calling the showDetails() method.

If a class contains a constructor, it is only called if objects are created specifically from that class; if an object is created from a child class, only the child class's constructor is called. However, if necessary we can make a child class call its parent's constructor with parent::__construct().

Cleaning Up Objects with Destructors

Destructors are useful for tidying up an object before it's removed from memory. For example, if an object has a few files open, or contains data that should be written to a database, it's a good idea to close the files or write the data before the object disappears.

We create destructor methods in the same way as constructors, except that we use __destruct() rather than __construct():

  function __destruct()
 {
     // (Clean up here)
 }


Note that, unlike a constructor, a destructor can't accept arguments.

An object's destructor is called just before the object is deleted. This can happen because all references to it have disappeared (such as when the last variable containing the object is unset or goes out of scope), or when the script exits, either naturally or because of an error of some sort. In each case, the object gets a chance to clean itself up via its destructor before it vanishes.

Here's an example that shows this concept:

class Person
 {
   public function save()
 {
     echo "Saving this object to the database...<br />";
  }
 
   public function __destruct()
 {
     $this->save();
   }
 }
 
 $p = new Person;
 unset( $p );
 $p2 = new Person;
 die( "Something's gone horribly wrong!<br />");


This code displays the following output:

 Saving this object to the database...
 Something's gone horribly wrong!
 Saving this object to the database...


This Person class contains a destructor that calls the object's save() method to save the object's contents to a database before the object is destroyed. (In this example, nothing is actually saved; instead the message "Saving this object to the database..." is displayed.)

A new Person object is created and stored in the variable $p. Next, $p is removed from memory using the built-in unset() function. Doing this removes the only reference to the Person object, so it's deleted. But just before it's removed, its __destruct() method is called, displaying the message "Saving this object to the database...".

Next the code creates another Person object, storing it in the variable $p2. Finally, the code raises an error using the built-in die() function, which causes the script to end with a "Something's gone horribly wrong!" message. Just before the script finally terminates, however, the object's destructor is called, displaying the "Saving this object to the database..." message.

As with constructors, a destructor of a parent class is not called when the child object is deleted, but we can explicitly call a parent's destructor with parent::__destruct().

Friday, February 6, 2015

Using Inheritance to Extend the Power of Objects

Objects get really interesting when we start using inheritance. Using this technique, we can create classes — known as child classes — that are based on another class: the parent class. A child class inherits all the properties and methods of its parent, and it can also add additional properties and methods.

The wonderful thing about inheritance is that, if we want to create a lot of similar classes, we have to write the code that they have in common only once, in the parent class. This saves us from duplicating code. Furthermore, any outside code that can work with the parent class automatically has the ability to work with its child classes, provided the code works only with the properties and methods contained in the parent class.

Imagine that we're creating a program to deal with various regular shapes, such as circles, squares, equilateral triangles, and so on. We want to create a Shape class that can store information such as number of sides, side length, radius, and color, and that can calculate values such as the shape's area and perimeter. However, not all shapes are the same. Circles don't really have a clearly defined number of sides, and we calculate an equilateral triangle's area using a different formula than for a square. So if we wanted to handle all types of regular shapes in a single Shape class, our class's code would get quite complicated.

By using inheritance, however, we can break the problem down into simpler steps. First, we create a parent Shape class that contains just those properties and methods that are common to all shapes. Then, we can create child classes such as Circle, Square, and Triangle that inherit from the Shape class.

To create a child class that's based on a parent class, we use the extends keyword, as follows:

 class Shape
 {
   // (General Shape properties and methods here)
 }
  
 class Circle extends Shape
 {
   // (Circle-specific properties and methods here)
 }

The following script shows inheritance in action. It creates a parent Shape class, holding properties and methods common to all shapes, then creates two child classes based on Shape — Circle and Square — that contain properties and methods related to circles and squares, respectively.

  
 <?php
  
 class Shape {
   private $_color = "black";
   private $_filled = false;
  
   public function getColor() {
     return $this->_color;
   }
  
   public function setColor( $color ) {
     $this->_color = $color;
   }
  
   public function isFilled() {
     return $this->_filled;
   }
  
   public function fill() {
     $this->_filled = true;
   }
  
   public function makeHollow() {
     $this->_filled = false;
   }
 }
  
 class Circle extends Shape {
   private $_radius = 0;
  
   public function getRadius() {
     return $this->_radius;
   }
  
   public function setRadius( $radius ) {
     $this->_radius = $radius;
   }
  
   public function getArea() {
     return M_PI * pow( $this->_radius, 2 );
   }
 }
  
 class Square extends Shape {
   private $_sideLength = 0;
  
   public function getSideLength() {
     return $this->_sideLength;
   }
  
   public function setSideLength( $length ) {
     $this->_sideLength = $length;
   }
  
   public function getArea() {
     return pow( $this->_sideLength, 2 );
   }
 }
  
 $myCircle = new Circle;
 $myCircle->setColor( "red" );
 $myCircle->fill();
 $myCircle->setRadius( 4 );
 echo "<h2>My Circle</h2>";
 echo "<p>My circle has a radius of " . $myCircle->getRadius() . ".</p>";
 echo "<p>It is " . $myCircle->getColor() . " and it is " . ( $myCircle->isFilled() ? "filled" : "hollow" ) . ".</p>";
 echo "<p>The area of my circle is: " . $myCircle->getArea() . ".</p>";
 $mySquare = new Square;
 $mySquare->setColor( "green" );
 $mySquare->makeHollow();
 $mySquare->setSideLength( 3 );
 echo "<h2>My Square</h2>";
 echo "<p>My square has a side length of " . $mySquare->getSideLength() . ".</p>";
 echo "<p>It is " . $mySquare->getColor() . " and it is " . ( $mySquare->
 isFilled() ? "filled" : "hollow" ) . ".</p>";
 echo "<p>The area of my square is: " . $mySquare->getArea() . ".</p>";
 ?>

How It Works

The script first creates the parent Shape class. This class contains just the properties and methods common to all shapes. It contains private properties to store the shape's color and record whether the shape is filled or hollow, then provides public accessor methods to get and set the color, as well as fill the shape or make it hollow and retrieve the shape's fill status.

Next, the script creates a Circle class that inherits from the Shape class. Remember that a child class inherits all the properties and methods of its parent. The Circle class also adds a private property to store the circle's radius, and provides public methods to get and set the radius, as well as calculate the area from the radius using the formula πr2.

The script then creates Square, another class that inherits from Shape. This time, the class adds a private property to track the length of one side of the square, and provides methods to get and set the side length and calculate the square's area using the formula (side length)2.

Finally, the script demonstrates the use of the Circle and Square classes. First it creates a new Circle object, sets its color, fills it, and sets its radius to 4. It then displays all the properties of the circle, and calculates its area using the getArea() method of the Circle class. Notice how the script calls some methods that are in the parent Shape class, such as setColor() and isFilled(), and some methods that are in the child Circle class, such as setRadius() and getArea().

The script then repeats the process with the Square class, creating a hollow green square with a side length of 3, then displaying the square's properties and calculating its area using the Square class's getArea() method.