CHAPTER 4 ■ ADVANCED FEATURES
$row['playlength'] );
} else {
$product = new ShopProduct(
$row['title'],
$row['firstname'],
$row['mainname'],
$row['price'] );
}
$product->setId( $row['id'] );
$product->setDiscount( $row['discount'] );
return $product;
}
//...
As you can see, the getInstance() method returns a ShopProduct object and, based on a type flag, is
smart enough to work out the precise specialization it should instantiate. I have omitted any error
handling to keep the example compact. In a real-world version of this, for example, I would not be so
trusting as to assume that the provided PDO object was initialized to talk to the correct database. In fact, I
probably wrap the PDO with a class that would guarantee this behavior. You can read more about object-
oriented coding and databases in Chapter 13.
This method is more useful in a class context than an object context. It lets us convert raw data from
the database into an object easily without requiring that I have a ShopProduct object to start with. The
method does not use any instance properties or methods, so there is no reason why it should not be
declared static. Given a valid PDO object, I can invoke the method from anywhere in an application:
$dsn = "sqlite://home/bob/projects/products.db";
$pdo = new PDO( $dsn, null, null );
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$obj = ShopProduct::getInstance( 1, $pdo );
Methods like this act as “factories” in that they take raw materials (such as row data, for example, or
configuration information) and use them to produce objects. The term factory is applied to code
designed to generate object instances. You will encounter factory examples again in future chapters.
Constant Properties
Some properties should not be changed. The Answer to Life, the Universe, and Everything is 42, and you
want it to stay that way. Error and status flags will often be hard-coded into your classes. Although they
should be publicly and statically available, client code should not be able to change them.
PHP 5 allows us to define constant properties within a class. Like global constants, class constants
cannot be changed once they are set. A constant property is declared with the const keyword. Constants
are not prefixed with a dollar sign like regular properties. By convention, they are often named using
only uppercase characters, like this:
class ShopProduct {
const AVAILABLE = 0;
const OUT_OF_STOCK = 1;
// ...
Constant properties can contain only primitive values. You cannot assign an object to a constant.
Like static properties, constant properties are accessed via the class and not an instance. Just as you
define a constant without a dollar sign, no leading symbol is required when you refer to one: