As we mentioned earlier, classes can contain both methods and variables (proper- ties). Methods are declared just like traditional functions:
class myClass {
function myFunction() {
echo "You called myClass::myFunction"; }
}
From outside the scope of a class, its methods are called using the indirection oper- ator->:
$obj = new myClass(); $obj->myFunction();
Naturally, the$objvariable is only valid within the scope of our small snippet of code above—which leaves us with a dilemma: how do you reference a class’ method from within the class itself? Here’s an example:
class myClass {
function myFunction() {
echo "You called myClass::myFunction"; }
function callMyFunction() {
// ???
} }
Clearly,callMyFunction()needs a way to callmyFunction()from within the object’s scope. In order to allow for this to take place, PHP defines a special variable called
$this; this variable is only defined within an object’s scope, and always points to the object itself:
class myClass {
function myFunction($data) {
echo "The value is $data"; } function callMyFunction($data) { // Call myFunction() $this->myFunction($data); } }
$obj = new myClass(); $obj->callMyFunction(123);
118 ” Object Oriented Programming in PHP
Constructors
PHP 5 introduces the concept of theunified constructor and, along with it, a new destructor for objects. The constructor and destructor are special class methods that are called, as their names suggest, on object creation and destruction, respectively. Constructors are useful for initializing an object’s properties, or for performing start- up procedures, such as, for example, connecting to a database, or opening a remote file.
The concept of the constructor is, of course, not new to PHP 5. In PHP 4, it was possible to define a class method whose name was the same as the class itself; PHP would then consider this method to be the class’ constructor and call it whenever a new instance of the class was created. This approach had several drawbacks—for example, if you decided to rename your class, you would also have to rename your constructor.
To avoid these problems, PHP 5 now uses the magic__construct()method as the constructor for any class regardless of the class’ name. This greatly simplify things, and provides you with a standard mechanism to recognize and call constructors in a consistent manner: class foo { function __construct() { echo __METHOD__; } function foo() { // PHP 4 style constructor } } new foo();
This example will displayfoo::__construct(the__METHOD__constant is replaced at compilation time with the name of the current class method). Note that, if the
__construct()method isnot found, PHP will look for the old PHP 4-style constructor (foo) and call that instead.
Destructors
In addition to the__construct()method, we also have a__destruct()method. This works like a mirror image of__construct(): it is called right before an object is de- stroyed, and is useful for performing cleanup procedures—such as disconnecting from a remote resource, or deleting temporary files:
class foo {
function __construct() {
echo __METHOD__ . PHP_EOL; } function __destruct() { echo __METHOD__; } } new foo();
This code will display:
foo::__construct foo::__destruct
Destruction occurs whenall references to an object are gone, and this may not nec- essarily take place when you expect it—or even when you want it to. In fact, while you can unset()a variable that references an object, or overwrite it with another value, the object itself may not be destroyed right away because a reference to it is held elsewhere. For example, in the following script the destructor is not called when callingunset(), because$bstill references the object:
$a = new foo(); $b = $a;
unset($a);
Even if an object still has one or more active references, the__destruct()method is called at the end of script execution—therefore, you are guaranteed that, at some
120 ” Object Oriented Programming in PHP
point, your destructor will be executed. However, there is no way to determine the order in which any two objects in your scripts will be destroyed. This can some- times cause problems when an object depends on another to perform one or more functions—for example, if one of your classes encapsulates a database connection and another class needs that connection to flush its data to the database, you should not rely on your destructors to perform a transparent flush to the database when the object is deleted: the instance of the first class that provides database connectiv- ity could, in fact, be destroyed before the second, thus making it impossible for the latter to save its data to the database.
Visibility
PHP 5 adds the notion of object method and propertyvisibility (often referred to as “PPP”), which enables you to determine the scope from which each component of your class interfaces can be accessed.
There are four levels of visibility:
public The resource can be accessed from any scope.
protected The resource can only be accessed from within the class where it is defined and its descendants.
private The resource can only be accessed from within the class where it is defined.
final The resource is accessible from any scope, but cannot be overridden in descendant classes.
i
Thefinalvisibility level only applies to methods and classes. Classes that are declared asfinalcannot be extended.Typically, you will want to make all API methods and properties public, since you will want them to be accessible from outside of your objects, while you will want to keep those used for internal operation as helpers to the API calls protected or pri- vate. Constructors and Destructors—along with all other magic methods (see be- low)—will normally be declared as public; there are, however, times when you wish
to make the constructor private—for example when using certain design patterns like Singleton or Factory.
class foo {
public $foo = ’bar’; protected $baz = ’bat’; private $qux = ’bingo’;
function __construct() {
var_dump(get_object_vars($this)); }
}
class bar extends foo { function __construct() { var_dump(get_object_vars($this)); } } class baz { function __construct() { $foo = new foo();
var_dump(get_object_vars($foo)); } } new foo(); new bar(); new baz();
The example above creates three classes,foo,bar, which extendsfooand has access to all offoo’spublicandprotectedproperties, and, finally,baz, which creates a new instance offooand can only access itspublicproperties.
The output will look like this:
// Output from "foo" itself:
array(3) { ["foo"]=> string(3) "bar"
122 ” Object Oriented Programming in PHP ["baz"]=> string(3) "bat" ["qux"]=> string(5) "bingo" }
// Output from sub-class "bar":
array(2) { ["foo"]=> string(3) "bar" ["baz"]=> string(3) "bat" }
// Output from stand-alone class "baz":
array(1) { ["foo"]=> string(3) "bar" }
Declaring and Accessing Properties
Properties are declared in PHP using one of the PPP operators, followed by their name:
class foo { public $bar; protected $baz; private $bas;
public var1 = "Test"; // String public var2 = 1.23; // Numeric value public var3 = array (1, 2, 3); }
Note that, like a normal variable, a class property can be initialized while it is be- ing declared. However, the initialization is limited to assigning values (but not by evaluating expressions). You can’t, for example, initialize a variable by calling a func-
tion—that’s something you can only do within one of the class’ methods (typically, the constructor).