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)

The Advantages of OOP


The power of OOP lies in its three main characteristics: inheritance, encapsulation, and polymorphism.

Inheritance

Inheritance in OOP allows you to create new classes that inherit an existing class's behaviour (methods) and attributes (properties). Let's consider the following example. Assume that we have a class called Fruit. It is a generalized type of class for different fruits, and its common attributes are color and weight. In OOP, we can subclass Fruit to create new classes Apple and Banana. Both these classes (being subclasses of Fruit) will have the same properties: weight and color. (Note we are speaking about properties as such, not about their values). An apple can have a green color, while a Banana can have a yellow color. But any code that interacts with Apple or Banana class instances does not need to know what kind of fruit it is communicating with.

Let's put this example into code:

class Fruit
{
public $color;
public $weight;
}
class Apple extends Fruit
{
function __construct()
{
$this->color = 'green';
$this->weight = 200;
}
}
class Banana extends Fruit
{
function __construct()
{
$this->color = 'yellow';
$this->weight = 250;
}
}
$a[] = new Apple();
$a[] = new Banana();
foreach($a as $f)
{
echo $f->color, "\t", $f->weight, "\n";
}

As you can see, in this small application we have one Apple object and one Banana object. We iterate over them in a loop, but access their properties regardless of their type, since both classes use the same property names. But these properties carry different values for each fruit.

Inheritance also allows to extend or completely override the behavior of the parent classes. Let's assume that our Fruit class has one more characteristic—price per kg. It also has a new method—getPrice() that just multiplies the weight (which we have in grams) by the price:

class Fruit
{
public $color;
public $weight;
public $price;
function getPrice()
{
return $this->weight / 1000 * $this->price;
}
}

Now we can use this method in the subclasses:

class Apple extends Fruit
{
function __construct()
{
$this->color = 'green';
$this->weight = 200;
$this->price = 2;
}
}
class Banana extends Fruit
{
function __construct()
{
$this->color = 'yellow';
$this->weight = 250;
$this->price = 3;
}
}
$a[] = new Apple();
$a[] = new Banana();
foreach($a as $f)
{
echo $f->getPrice(), "\n";
}

Next, we will assume that the Banana class has another method for calculating price so that a discount is applied:

class Banana extends Fruit
{
function __construct()
{
$this->color = 'yellow';
$this->weight = 250;
$this->price = 3;
}
function getPrice()
{
return $this->weight / 1000 * $this->price * 0.9;
}
}

As you can see, we changed the method in the Banana class so that the code calling the Banana class's implementation of the getPrice() method will get discounted price, while the Apple class's getPrice() method returns full price.

On the other hand, we could reuse the Fruit class's implementation of the getPrice() method in the Banana class (so that we don't have to duplicate the code contained in the base class):

function getPrice()
{
return parent::getPrice() * 0.9;
}

Encapsulation

Encapsulation (sometimes called information hiding) is a more theoretical concept. It involves defining methods in a class in such a way that we hide the implementation details from the client code. We have already seen this when we redefined the price calculation in the Banana class. From the application's point of view, nothing changed: we still call the getPrice() method, but we don't know how this calculation is performed.

In other words, classes are accessible through their methods, which have the same names so that, even if the code behind these names changes, the names themselves do not change. This ensures that existing code does not need to be changed to work with new versions of methods.

We can do more to hide implementation details from client code, PHP5, like other object-oriented languages, supports visibility modifiers for methods and properties. For example, we could add a private property, which will be hidden from the rest of the application, to the Banana class:

class Banana extends Fruit
{
private $mySecretProperty;

function __construct()
{
$this->color = 'yellow';
$this->weight = 250;
$this->price = 3;
}
function getPrice()
{
return parent::getPrice() * 0.9;
}
}

The $mySecretProperty property is only accessible (or visible) in the Banana class; an attempt to access it from outside the Banana class's methods would trigger a run-time error. (In a compiled language, this would lead to a compilation error.)

In PHP5, there exist two more modifiers: public (which we have already used), and protected. Public method or property is accessible from all the application, while protected is accessible inside the class and its subclasses only.

Polymorphism

Polymorphism is a feature of OOP that allows us to write code that will work with objects belonging to different classes provided that these classes have the same base class. We have already seen polymorphism in action in the above example when we were accessing properties and methods of different objects using their names but returning different values and taking different actions.

The subclasses implement all the properties and methods belonging to the base class, and all future subclasses of the base class are guaranteed to implement these properties and methods so that the existing code can work even with subclasses which do not yet exist.

PHP5 supports interfaces. An interface is a construct that describes certain behaviour in different classes and class hierarchies. For example, let’s consider a Tradeable interface that has a single method, isImported():

interface Tradeable
{
public isImported();
}

Now, we can declare in the definition of the Fruit class that it implements the Tradeable interface:

class Fruit implements Tradeable

{
public $color;
public $weight;
public $price;
function getPrice()
{
return $this->weight / 1000 * $this->price;
}
function isImported()
{
return false;
}
}

We have made Fruit objects and all objects belonging to its subclasses (Apple and Banans) non-imported by default. Now we can make bananas imported while leaving apples domestic:

class Banana extends Fruit
{
function __construct()
{
$this->color = 'yellow';
$this->weight = 250;
$this->price = 3;
}
function getPrice()
{
return parent::getPrice() * 0.9;
}
function isImported()
{
return true;
}
}

Next we will create an imaginary Car class that implements the Tradeable interface:

class Car implements Tradeable
{
public $year;
public $make;
public $model;
function isImported()
{
return true;
}
}

Note that Car does not extend Fruit, but it still has the isImported() method. Now we can call this method from the application:

$a[] = new Apple();
$a[] = new Banana();
$a[] = new Car();
foreach($a as $item)
{
echo $item->isImported();
}

This small example shows how objects from different class hierarchies can be treated in the same way by giving them a common interface. By doing this, objects that normally have quite different meanings can be manipulated in the same way, and this makes them polymorphic.