Book Image

Learning PHP Data Objects

By : Dennis Popel
Book Image

Learning PHP Data Objects

By: Dennis Popel

Overview of this book

PDO is lighter, faster, and more powerful than existing PHP data abstraction interfaces. PDO is a common interface to different databases that must be used with a database-specific PDO driver to access a particular database server: the PDO extension does not provide a database abstraction by itself; it doesn't rewrite SQL, emulate missing database features, or perform any database functions using by itself. It performs the same role as other classic database abstraction layers such as ODBC and JDBC: it's a query abstraction layer that abstracts the mechanism for accessing a database and manipulating the returned records; each database driver that implements the PDO interface can also expose database-specific features as regular extension functions. ¬ PDO ships with PHP 5.1, and is available as an extension for PHP 5.0; it requires the new object-oriented features of PHP 5, and cannot run with earlier versions of PHP.This book will teach you how to use the PDO, including its advanced features. Readers need to be aware of the basics of data abstraction and should be familiar with PHP.
Table of Contents (13 chapters)

What is Object-Oriented Programming?


Object-oriented programming (OOP) is a relatively new concept, although its roots date back to 1960s. In OOP, the software works with objects that model real-life entities (such as books and authors in the Chapter 7). Whereas procedural programming involves a series of instructions, an application in OOP involves a set of objects that interact with each other.

The Syntax for Declaring Objects

An object can be viewed as a container for several variables, called properties, and for functions that act on these variables. These functions are called methods. Every object belongs to a class. In PHP, every object can belong to only one class (although some other OOP languages allow multiple inheritance), but there can be many objects, or instances, belonging to a single class. A class is a syntactic construct that allows you to describe what properties and methods the objects belonging to this class will have.

There is an analogy with species and living organisms—for example, a Dog (a species, or a class) is a generalization of all living dogs. A generalized dog has such properties as weight and age, and a method such as bark, and a real-life dog, say Lessie, which belongs to the dog species, could be described as an instance of the Dog class.

Let's see how we would model this in PHP5:

class Dog
{
public $weight;
public $age;
function bark()
{
print "woof!";
}
}
$lessie = new Dog();
$lessie->weight = 15;
$lessie->age = 3;
$lessie->bark();

In this small snippet of code, we defined a class called Dog. In PHP5, a class definition starts with the reserved word class followed by the class's name (A class's name can contain the same characters as a function's name.) All the class's properties and methods, collectively called members, are defined inside the {…} block.

As you can see, we are using the keyword, public, when we declare properties and methods. In PHP4 we would have used the var keyword instead, but this keyword is deprecated in PHP5. Besides the public keyword, we could have used the protected keyword or the private keyword, but more on this later.

As you can see in the second part of the code, we create the object with the new keyword:

$lessie = new Dog();

This line creates a new object belonging to the Dog class and assigns it to the $lessie variable. This is a very important step, since this is the only way to create objects. After the PHP processes it, the $lessie variable becomes initialized and we can access the properties and methods declared in the Dog class so that we act on the object called Lessie. We would now like to have two dogs in our application, and the second one will be called K9. To achieve that, we would have to write something like this:

$k9 = new Dog();
$k9->age = 5;
$k9->weight = 18;

Now, we can access both the $k9 and $lessie variables, if we would like to interface with each of our dogs.

In other words, before we can communicate with an instance, it first has to be created with the new keyword.

After the variable has been initialized, we can access its properties and methods. As you can see in the code, this is achieved with the -> construct, which is used with both properties and methods. Note that when accessing a class’s properties, we don’t have to write the dollar sign after the -> (but we have to use it when declaring the properties inside the class definition).

The methods are declared with the function keyword followed by the method’s name and a list of parameters. In fact, a class’s methods are declared in a similar way to that for an ordinary function, but there is one major difference. Inside the declaration of a method, there always exists implicit variable, called $this, which allows you to access the object’s properties. Let’s see how we could create a getInfo() method to return some additional information about our dogs:

<?php
class Dog
{
public $weight;
public $age;
function bark()
{
print "woof!";
}
function getInfo()
{
return 'Weight: ' . $this->weight . ' kg, age: ' . $this->age .
' years';
}

}
$lessie = new Dog();
$lessie->weight = 15;
$lessie->age = 3;
$k9 = new Dog();
$k9->age = 5;
$k9->weight = 18;
echo 'Lessie: ', $lessie->getInfo(), "\n";
echo 'K9: ', $k9->getInfo(), "\n";

This code would display the following output:

Lessie: Weight: 15 kg, age: 3 years
K9: Weight: 18 kg, age: 5 years

Constructors

Every class also has a special function (which may be implicit or explicitly declared) called a constructor. The constructor is always called when PHP encounters the new keyword, and its purpose is to perform some initialization tasks. Let's extend the Dog class so that it has a $name property. We will also change the code so as to initialize the name, weight, and age properties inside the constructor rather than in the main application:

<?php
class Dog
{
public $weight;
public $age;
public $name;
function __construct($name, $age, $weight)
{
$this->name = $name;
$this->weight = $weight;
$this->age = $age;
}

function bark()
{
print "woof!";
}
function getInfo()
{
return
'Name: ' . $this->name .
', weight: ' . $this->weight .
' kg, age: ' . $this->age .
' years';
}
}
$lessie = new Dog('Lessie', 3, 15);
$k9 = new Dog('K9', 5, 18);
echo $lessie->getInfo(), "\n";
echo $k9->getInfo(), "\n";

This application would display the following:

Name: Lessie, weight: 15 kg, age: 3 years
Name: K9, weight: 18 kg, age: 5 years

Here's a brief summary of what we did. We first declared the $name property and then the constructor for our Dog class. The constructors are declared as function with the special name of __construct (the word constructor prepended with two underscores('_'). Our constructor accepts three parameters—name, age, and weight, whose values are assigned to the object's properties. The order in which we assign values to the properties does not matter. Note that we always have to use the $this variable to denote the properties of the object. By doing this, we can differentiate the local variables $name, $age, and $weight (passed as parameters) from the object's own properties, which have the same names, inside the constructor.

We also changed the getInfo() method so that it returns the name of the dog as well. We can now instantiate objects by passing the name, the age, and the weight to the constructor. Since these properties get assigned in the constructor, we don't have to do this in the main part of the code.

It should be also noted that you can assign default values to properties in the class definition. This will ensure that every object of that class will have the default values automatically assigned. For example, we can do the following:

class Dog
{
public $weight;
public $age;
public $name;
public $hasCollar = true;
function __construct($name, $age, $weight)
{
$this->name = $name;
$this->weight = $weight;
$this->age = $age;
}
function bark()
{
print "woof!";
}
function getInfo()
{
return
'Name: ' . $this->name .
', weight: ' . $this->weight .
' kg, age: ' . $this->age .
' years, has collar: ' . ($this->hasCollar ? 'yes' : 'no');
}

}

If you run the application with this Dog class definition, then you will see the following output:

Name: Lessie, weight: 15 kg, age: 3 years, has collar: yes
Name: K9, weight: 18 kg, age: 5 years, has collar: yes

As you can now see, the default property value for hasCollar has propagated to every newly created instance (of course, it can be later changed for each object).

Destructors

There is an opposite concept to constructors, called destructors. As its name suggests, destructors are used to perform cleanup tasks (classic examples of such tasks are deleting temporary files, closing database connections, etc). In PHP5, destructor on an object is called, when there are no more references to that object (for example, by setting the variable that holds the reference to the object to null or when the application terminates), then the destructor will be called.

Destructor is a method: __destruct(). If you add that method to the class, then it will be called when the object is freed. Let’s add the destructor to the Dog class:

class Dog {
public $weight;
public $age;
public $name;
public $hasCollar = true;
function __construct($name, $age, $weight) {
$this->name = $name;
$this->weight = $weight;
$this->age = $age;
}
function bark() {
print "woof!";
}
function getInfo() {
return
'Name: ' . $this->name .
', weight: ' . $this->weight .
' kg, age: ' . $this->age .
' years, has collar: ’ . ($this->hasCollar ? 'yes’ : 'no’);
}
function __destruct() {
print "Freeing $this->name\n";
}
}

Now, if you run the code again, it will give the following output:

Name: Lessie, weight: 15 kg, age: 3 years, has collar: yes
Name: K9, weight: 18 kg, age: 5 years, has collar: yes
Freeing K9
Freeing Lessie

Note that the order in which PHP5 calls the destructors is not defined. Also, in a destructor, the code may not access other objects unless they are referenced by the object being freed. In other words, the destructor should only cleanup those resources that were created by that object.