Late static binding
One of the more annoying things about PHP before V5.3 is how static methods and members are dealt with. Up until now, static references, such as those made with self or __CLASS__, are resolved in the class scope in which the function was defined. The problem is that the reference would be incorrect if the class was extended and the call was made from the new child class. Late static binding has been added in PHP V5.3 to alleviate this problem. To better illustrate, let's create a class with a static method below.
Class Foo with static method test()
class Foo
{
protected static $name = 'Foo';
public static function test()
{
return self::$name;
}
}
Let's extend this class. We'll redefine the member $name in this child class.
Child class Bar that extends parent class Foo
class Bar extends Foo
{
protected static $name = 'Bar';
}
We make the static call below example.
Static method call test()
echo Bar::test();
What is output from that call would be the string Foo. This is because the self::$name reference made in the test() method is done with the Foo class. The binding occurs this way because this is where the function is defined.
PHP V5.3 has added the keyword static to allow you to make a reference against the current class. So you will change the Foo class above to use this keyword in next example, and we'll see that Bar will instead be output.
Using the static keyword
class Foo
{
protected static $name = 'Foo';
public static function test()
{
return static::$name;
}
}
class Bar
{
protected static $name = 'Bar';
}
echo Bar::test(); // outputs 'Bar'
One thing to note about the static keyword is that it doesn't work the same as how this works in the nonstatic context. This means that the normal inheritance rules do not apply to static calls. The static keyword will simply try to resolve the call in the current class instead of the class the function was defined in. This is an important thing to note.
Now that we have seen some enhancements with static methods and members, let's take a look at some new classes added to a very useful part of PHP V5: the Standard PHP Library.
Standard PHP Library
The Standard PHP Library (SPL) is a collection of interfaces and classes added in PHP V5 designed to solve standard problems. These problems include having an object be iterateable, letting an object behave as if it was an array, or implementing a linked list. The advantage of using these classes and methods is that they are native to PHP, which means they are faster than if they were implemented in PHP itself. They also, in many instances, allow many of the internal functions of PHP to use these objects directly, such as how the Iterator interface allows you to use the foreach construct to iterate over the object.
PHP V5.3 adds a few more classes to SPL. One we referenced earlier is the implementation of a doubly linked list in the SPL class SplDoublyLinkedList. It is used by two other new SPL classes: SplStack, which implements a stack, and SplQueue, which implements a queue.
Let's take a look at how you can use the SplStack class to implement a stack.
Using SplStack
$stack = new SplStack();
// push a few new items on the stack
$stack->push('a');
$stack->push('b');
$stack->push('c');
// see how many items are on the stack
echo count($stack); // returns 3
// iterate over the items in the stack
foreach ( $stack as $item )
echo "[$item],";
// the above outputs: [c],[b],[a]
// pop an item off the stack
echo $stack->pop(); // returns 'c'
// now see how many items are on the stack
echo count($stack); // returns 2
The SqlQueue works in a similar fashion, but it works like a queue would (first item in, first item out; instead of last item in, first item out, like the stack). In addition, a heap implementation exists (SplHeap), as well as specific queue and heap implementations for certain situations (SplMinHeap, SplMaxHeap, and SplPriorityQueue).
Another useful addition is the SplFixedArray class, which, as the name implies, is a fixed-size array implementation. It is, however, rather fast — actually so fast that it's been benchmarked to be 10-30 percent faster than the built-in array implementation in PHP. This speedup is due to the fact that the array is a fixed size, not a variable-sized one like the default PHP one is, and that non-numeric indexes are not allowed. Listing 10 shows how it's used.
SplFixedArray
$array = new SplFixedArray(3);
$array[0] = 'dog';
$array[1] = 'cat';
$array[2] = 'bird';
$a->setSize(4); // increase the size on the fly
$array[3] = 'mouse';
foreach ( $array as $value )
echo "[$value],";
Output:
[dog],[cat],[bird],[mouse]
In addition, a few new iterator classes have been added: FilesystemIterator and GlobIterator. These work the same as the other iterator classes in PHP, but they are specially designed for certain instances.
One other change with SPL is that it is always enabled now in PHP V5.3. In previous versions of PHP V5, you could disable SPL at compile time, but as of PHP V5.3, this is no longer possible.
The new additions to SPL add some useful functionality to PHP that is easy to use, as well as implementations of data structures, such as doubly linked lists, stacks, heaps, and queues. These classes can be used to replace user space implementations you may have, which will gain increased speed and better integration with various PHP functions and constructs.
Now that we have seen some new additions to SPL, let's see how OOP in PHP V5.3 has gained an important performance and memory usage improvement with the addition of circular garbage collection.
Circular garbage collection
One problem PHP developers run into from a performance standpoint is garbage collection. PHP has a pretty simple garbage collector, which basically will garbage collect an object when it no longer is in scope. The way it does this internally is by using a reference counter, so that when the counter reaches zero (meaning no more references to this object are available), the object will be garbage collected and expunged from memory.
This works fairly well, but can become a problem in situations where one object references another in a parent-child relationship. In this situation, the reference counter for those object are not collected, so the memory used by these objects stays in unreferenced memory and is not unallocated until the end of the request. Let's take a look at an example of when this problem occurs.
Parent-child class relationship not properly garbage collected in PHP V5.2 and earlier
class Parent
{
public function __construct()
{
$this->child = new Child($this);
}
}
class Child
{
public function __construct(
Parent $parent
)
{
$this->parent = $parent;
}
}
In this instance, every time you create an instance of the Parent class and then subsequently the instance goes out of scope, the memory is never released, so the script will grow and grow in memory usage. There are a few user space solutions to this problem, such as creating a destructor for the parent class that will release the child object directly. This destructor would have to be called specifically before unsetting the parent class reference. While doing all of this works, it complicates your code quite a bit.
In PHP V5.3, the garbage collector will detect these circular references and is able to free up the memory used by them, so the PHP memory usage will remain flat as the script is executed. As each reference to the Parent class is removed, the Child class reference inside the Parent class will also be garbage collected.
Tuesday, September 8, 2009
New features in PHP 5.3 & Improvements in Object oriented concepts
Subscribe to:
Post Comments (Atom)
0 comments:
Post a Comment