mirror of
https://github.com/php/web-php.git
synced 2026-03-31 19:52:29 +02:00
885 lines
24 KiB
PHP
885 lines
24 KiB
PHP
<?php
|
|
// $Id$
|
|
$_SERVER['BASE_PAGE'] = 'zend-engine-2.php';
|
|
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/prepend.inc';
|
|
site_header("Changes in PHP 5/Zend Engine 2.0");
|
|
?>
|
|
|
|
<h1>Changes in PHP 5/Zend Engine 2.0</h1>
|
|
|
|
<p>
|
|
[ <a href="http://www.nexen.net/interview/index.php?id=32">Disponible
|
|
en français</a> ]
|
|
</p>
|
|
|
|
<h2>New Object Model.</h2>
|
|
<p>
|
|
PHP's handling of objects has been completely rewritten, allowing for better
|
|
performance and more features. In previous versions of PHP, objects were
|
|
handled like primitive types (for instance integers and strings). The drawback
|
|
of this method was that semantically the whole object was copied when a
|
|
variable was assigned, or pass as a parameter to a method. In the new approach,
|
|
objects are referenced by handle, and not by value (one can think of a handle
|
|
as an object's identifier).
|
|
</p>
|
|
<p>
|
|
Many PHP programmers aren't even aware of the copying quirks of the old object
|
|
model and, therefore, the majority of PHP applications will work out of the box,
|
|
or with very few modifications.
|
|
</p>
|
|
|
|
<h2>Private and Protected Members</h2>
|
|
<p>
|
|
PHP 5 introduces private and protected member variables, they allow you to
|
|
define the visibility of class properties.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<p>
|
|
Protected member variables can be accessed in classes extending the class
|
|
they are declared in, whereas private member variables can only be accessed
|
|
by the class they belong to.
|
|
</p>
|
|
<?php highlight_php('<?php
|
|
class MyClass {
|
|
private $Hello = "Hello, World!\n";
|
|
protected $Bar = "Hello, Foo!\n";
|
|
protected $Foo = "Hello, Bar!\n";
|
|
|
|
function printHello() {
|
|
print "MyClass::printHello() " . $this->Hello;
|
|
print "MyClass::printHello() " . $this->Bar;
|
|
print "MyClass::printHello() " . $this->Foo;
|
|
}
|
|
}
|
|
|
|
class MyClass2 extends MyClass {
|
|
protected $Foo;
|
|
|
|
function printHello() {
|
|
MyClass::printHello(); /* Should print */
|
|
print "MyClass2::printHello() " . $this->Hello; /* Shouldn\'t print out anything */
|
|
print "MyClass2::printHello() " . $this->Bar; /* Shouldn\'t print (not declared)*/
|
|
print "MyClass2::printHello() " . $this->Foo; /* Should print */
|
|
}
|
|
}
|
|
|
|
$obj = new MyClass();
|
|
print $obj->Hello; /* Shouldn\'t print out anything */
|
|
print $obj->Bar; /* Shouldn\'t print out anything */
|
|
print $obj->Foo; /* Shouldn\'t print out anything */
|
|
$obj->printHello(); /* Should print */
|
|
|
|
$obj = new MyClass2();
|
|
print $obj->Hello; /* Shouldn\'t print out anything */
|
|
print $obj->Bar; /* Shouldn\'t print out anything */
|
|
print $obj->Foo; /* Shouldn\'t print out anything */
|
|
$obj->printHello();
|
|
?>'); ?>
|
|
|
|
<h2>Private and protected methods</h2>
|
|
<p>
|
|
With PHP 5, private and protected methods are also introduced.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
private function aPrivateMethod() {
|
|
echo "Foo::aPrivateMethod() called.\n";
|
|
}
|
|
|
|
protected function aProtectedMethod() {
|
|
echo "Foo::aProtectedMethod() called.\n";
|
|
$this->aPrivateMethod();
|
|
}
|
|
}
|
|
|
|
class Bar extends Foo {
|
|
public function aPublicMethod() {
|
|
echo "Bar::aPublicMethod() called.\n";
|
|
$this->aProtectedMethod();
|
|
}
|
|
}
|
|
|
|
$o = new Bar;
|
|
$o->aPublicMethod();
|
|
?>'); ?>
|
|
<p>
|
|
Old code that has no user-defined classes or functions named "public",
|
|
"protected" or "private" should run without modifications.
|
|
</p>
|
|
|
|
<h2>Abstract Classes and Methods</h2>
|
|
<p>
|
|
PHP 5 also introduces abstract classes and methods. An abstract method
|
|
only declares the method's signature and does not provide an implementation.
|
|
A class that contains abstract methods needs to be declared abstract.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
abstract class AbstractClass {
|
|
abstract public function test();
|
|
}
|
|
|
|
class ImplementedClass extends AbstractClass {
|
|
public function test() {
|
|
echo "ImplementedClass::test() called.\n";
|
|
}
|
|
}
|
|
|
|
$o = new ImplementedClass;
|
|
$o->test();
|
|
?>'); ?>
|
|
<p>
|
|
Abstract classes cannot be instantiated. Old code that has no user-defined
|
|
classes or functions named 'abstract' should run without modifications.
|
|
</p>
|
|
|
|
<h2>Interfaces</h2>
|
|
<p>
|
|
PHP 5 introduces interfaces. A class may implement an arbitrary
|
|
list of interfaces.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
interface Throwable {
|
|
public function getMessage();
|
|
}
|
|
|
|
class MyException implements Throwable {
|
|
public function getMessage() {
|
|
// ...
|
|
}
|
|
}
|
|
?>'); ?>
|
|
<p>
|
|
Old code that has no user-defined classes or functions named 'interface' or
|
|
'implements' should run without modifications.
|
|
</p>
|
|
|
|
<h2>Class Type Hints</h2>
|
|
<p>
|
|
While remaining loosely typed PHP 5 introduces the ability to use class type
|
|
hints to declare the expected class of objects that are passed as parameters
|
|
to a method.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
interface Foo {
|
|
function a(Foo $foo);
|
|
}
|
|
|
|
interface Bar {
|
|
function b(Bar $bar);
|
|
}
|
|
|
|
class FooBar implements Foo, Bar {
|
|
function a(Foo $foo) {
|
|
// ...
|
|
}
|
|
|
|
function b(Bar $bar) {
|
|
// ...
|
|
}
|
|
}
|
|
|
|
$a = new FooBar;
|
|
$b = new FooBar;
|
|
|
|
$a->a($b);
|
|
$a->b($b);
|
|
?>'); ?>
|
|
<p>
|
|
These class type hints are not checked upon compilation, as would be the case
|
|
in a typed language, but during runtime. This means that:
|
|
</p>
|
|
<?php
|
|
highlight_php('<?php
|
|
function foo(ClassName $object) {
|
|
// ...
|
|
}
|
|
?>');
|
|
?>
|
|
<p>
|
|
is equivalent to:
|
|
</p>
|
|
<?php
|
|
highlight_php('<?php
|
|
function foo($object) {
|
|
if (!($object instanceof ClassName)) {
|
|
die("Argument 1 must be an instance of ClassName");
|
|
}
|
|
}
|
|
?>'); ?>
|
|
<p>
|
|
This syntax only applies to objects/classes, not built-in types.
|
|
</p>
|
|
|
|
<h2>final</h2>
|
|
<p>
|
|
PHP 5 introduces the "final" keyword to declare final members and methods.
|
|
Methods and members declared final cannot be overridden by sub-classes.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
final function bar() {
|
|
// ...
|
|
}
|
|
}
|
|
?>'); ?>
|
|
<p>
|
|
It is furthermore possible to make a class final. Doing this
|
|
prevents a class from being specialized (it cannot be inherited
|
|
by another class). There's no need to declare the methods of
|
|
a final class themselves as final.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
final class Foo {
|
|
// class definition
|
|
}
|
|
|
|
// the next line is impossible
|
|
// class Bork extends Foo {}
|
|
?>'); ?>
|
|
<p>
|
|
Properties cannot be final.
|
|
</p>
|
|
<p>
|
|
Old code that has no user-defined classes or functions named 'final' should
|
|
run without modifications.
|
|
</p>
|
|
|
|
<h2>Object Cloning</h2>
|
|
<p>
|
|
PHP 4 offered no way a user could decide what copy constructor to run when an
|
|
object is duplicated. During duplication, PHP 4 did a bit for bit copy making
|
|
an identical replica of all the object's properties.
|
|
</p>
|
|
<p>
|
|
Creating a copy of an object with fully replicated properties is not always the
|
|
wanted behavior. A good example of the need for copy constructors, is if you have
|
|
an object which represents a GTK window and the object holds the resource of this
|
|
GTK window, when you create a duplicate you might want to create a new window with
|
|
the same properties and have the new object hold the resource of the new window.
|
|
Another example is if your object holds a reference to another object which it
|
|
uses and when you replicate the parent object you want to create a new instance
|
|
of this other object so that the replica has its own separate copy.
|
|
</p>
|
|
<p>
|
|
An object copy is created by calling the object's <code>__clone()</code> method:
|
|
</p>
|
|
<?php highlight_php('<?php
|
|
$copy_of_object = $object->__clone();
|
|
?>'); ?>
|
|
<p>
|
|
When the developer asks to create a new copy of an object, PHP 5 will
|
|
check if a <code>__clone()</code> method has been defined or not. If not, it
|
|
will call a default <code>__clone()</code> which will copy all of the object's
|
|
properties. If a <code>__clone()</code> method is defined, then it will be
|
|
responsible to set the necessary properties in the created object. For
|
|
convenience, the engine will supply a function that imports all of the properties
|
|
from the source object, so that they can start with a by-value replica of the
|
|
source object, and only override properties that need to be changed.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class MyCloneable {
|
|
static $id = 0;
|
|
|
|
function MyCloneable() {
|
|
$this->id = self::$id++;
|
|
}
|
|
|
|
function __clone() {
|
|
$this->name = $that->name;
|
|
$this->address = "New York";
|
|
$this->id = self::$id++;
|
|
}
|
|
}
|
|
|
|
$obj = new MyCloneable();
|
|
|
|
$obj->name = "Hello";
|
|
$obj->address = "Tel-Aviv";
|
|
|
|
print $obj->id . "\n";
|
|
|
|
$obj = $obj->__clone();
|
|
|
|
print $obj->id . "\n";
|
|
print $obj->name . "\n";
|
|
print $obj->address . "\n";
|
|
?>');
|
|
?>
|
|
|
|
<h2>Unified Constructors</h2>
|
|
<p>
|
|
PHP 5 allows developers to declare constructor methods for classes.
|
|
Classes which have a constructor method call this method on each newly-created
|
|
object, so it is suitable for any initialization that the object may need
|
|
before it is used.
|
|
</p>
|
|
<p>
|
|
With PHP 4, constructor methods were class methods that had the same name as
|
|
the class itself. Since it is very common to call parent constructors from derived
|
|
classes, the way PHP 4 worked made it a bit cumbersome to move classes around
|
|
in a large class hierarchy. If a class is moved to reside under a different
|
|
parent, the constructor name of that parent changes as well, and the code in
|
|
the derived class that calls the parent constructor has to be modified.
|
|
</p>
|
|
<p>
|
|
PHP 5 introduces a standard way of declaring constructor methods by calling
|
|
them by the name <code>__construct()</code>.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class BaseClass {
|
|
function __construct() {
|
|
print "In BaseClass constructor\n";
|
|
}
|
|
}
|
|
|
|
class SubClass extends BaseClass {
|
|
function __construct() {
|
|
parent::__construct();
|
|
print "In SubClass constructor\n";
|
|
}
|
|
}
|
|
|
|
$obj = new BaseClass();
|
|
$obj = new SubClass();
|
|
?>'); ?>
|
|
<p>
|
|
For backwards compatibility, if PHP 5 cannot find a <code>__construct()</code>
|
|
function for a given class, it will search for the old-style constructor function,
|
|
by the name of the class. Effectively, it means that the only case that would
|
|
have compatibility issues is if the class had a method named
|
|
<code>__construct()</code> which was used for different semantics.
|
|
</p>
|
|
|
|
<h2>Destructors</h2>
|
|
<p>
|
|
Having the ability to define destructors for objects can be very useful.
|
|
Destructors can log messages for debugging, close database connections and do
|
|
other clean-up work. No mechanism for object destructors existed in PHP 4,
|
|
although PHP had already support for registering functions which should be
|
|
run on request shutdown.
|
|
</p>
|
|
<p>
|
|
PHP 5 introduces a destructor concept similar to that of other object-oriented
|
|
languages, such as Java: When the last reference to an object is destroyed the
|
|
object's destructor, which is a class method named <code>__destruct()</code>
|
|
that receives no parameters, is called before the object is freed from memory.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class MyDestructableClass {
|
|
function __construct() {
|
|
print "In constructor\n";
|
|
$this->name = "MyDestructableClass";
|
|
}
|
|
|
|
function __destruct() {
|
|
print "Destroying " . $this->name . "\n";
|
|
}
|
|
}
|
|
|
|
$obj = new MyDestructableClass();
|
|
?>'); ?>
|
|
<p>
|
|
Like constructors, parent destructors will not be called implicitly by the
|
|
engine. In order to run a parent destructor, one would have to explicitly
|
|
call <code>parent::__destruct()</code> in the destructor body.
|
|
</p>
|
|
|
|
<h2>Constants</h2>
|
|
<p>
|
|
PHP 5 introduces per-class constants:
|
|
</p>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
const constant = "constant";
|
|
}
|
|
|
|
echo "Foo::constant = " . Foo::constant . "\n";
|
|
?>'); ?>
|
|
<p>
|
|
Old code that has no user-defined classes or functions named 'const'
|
|
will run without modifications.
|
|
</p>
|
|
|
|
<h2>Exceptions</h2>
|
|
<p>
|
|
PHP 4 had no exception handling. PHP 5 introduces a exception model similar
|
|
to that of other programming languages. Note that there is support for "catch
|
|
all" and for the "finally" clause.
|
|
</p>
|
|
<p>
|
|
Exceptions can be rethrown in catch blocks. Also it is possible to
|
|
have multiple catch blocks. In that case the caught exception is
|
|
compared with the classtype of each catch block from top to bottom
|
|
and the first block that has an 'instanceof' match gets executed.
|
|
When the catch block finishes, execution continues at the end of
|
|
the last catch block. If no catch block has an 'instanceof' match
|
|
then the next try/catch block is searched until no more try/catch
|
|
blocks are available. In that case the exception is an uncaught
|
|
exception and the program terminates with showing the exception.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class MyException {
|
|
function __construct($exception) {
|
|
$this->exception = $exception;
|
|
}
|
|
|
|
function Display() {
|
|
print "MyException: $this->exception\n";
|
|
}
|
|
}
|
|
|
|
class MyExceptionFoo extends MyException {
|
|
function __construct($exception) {
|
|
$this->exception = $exception;
|
|
}
|
|
|
|
function Display() {
|
|
print "MyException: $this->exception\n";
|
|
}
|
|
}
|
|
|
|
try {
|
|
throw new MyExceptionFoo(\'Hello\');
|
|
}
|
|
catch (MyException $exception) {
|
|
$exception->Display();
|
|
}
|
|
catch (Exception $exception) {
|
|
echo $exception;
|
|
}
|
|
?>'); ?>
|
|
<p>
|
|
Even though the above example shows that it is possible to define
|
|
exception classes that don't inherit from Exception it is best to
|
|
do so. This is because the internal Exception class can gather a
|
|
lot of information otherwise not available. The PHP code emulation
|
|
code would look something like shown below. The comments show the
|
|
meaning of each property and hence their getter methods. As the code
|
|
shows it is possible to read any available information by using the
|
|
getter methods. But since some of the methods are used internally
|
|
they are marked final. All in all the class is very restrictive
|
|
because it must be ensured that anything used internally always
|
|
works as expected.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Exception {
|
|
function __construct(string $message=NULL, int code=0) {
|
|
if (func_num_args()) {
|
|
$this->message = $message;
|
|
}
|
|
$this->code = $code;
|
|
$this->file = __FILE__; // of throw clause
|
|
$this->line = __LINE__; // of throw clause
|
|
$this->trace = debug_backtrace();
|
|
$this->string = StringFormat($this);
|
|
}
|
|
|
|
protected $message = \'Unknown exception\'; // exception message
|
|
protected $code = 0; // user defined exception code
|
|
protected $file; // source filename of exception
|
|
protected $line; // source line of exception
|
|
|
|
private $trace; // backtrace of exception
|
|
private $string; // internal only!!
|
|
|
|
final function getMessage() {
|
|
return $this->message;
|
|
}
|
|
final function getCode() {
|
|
return $this->code;
|
|
}
|
|
final function getFile() {
|
|
return $this->file;
|
|
}
|
|
final function getTrace() {
|
|
return $this->trace;
|
|
}
|
|
final function getTraceAsString() {
|
|
return self::TraceFormat($this);
|
|
}
|
|
function _toString() {
|
|
return $this->string;
|
|
}
|
|
static private function StringFormat(Exception $exception) {
|
|
// ... a function not available in PHP scripts
|
|
// that returns all relevant information as a string
|
|
}
|
|
static private function TraceFormat(Exception $exception) {
|
|
// ... a function not available in PHP scripts
|
|
// that returns the backtrace as a string
|
|
}
|
|
}
|
|
?>'); ?>
|
|
<p>
|
|
If you derive your exception classes from this Exception base class
|
|
your exceptions will be nicely shown in the built-in handler for
|
|
uncaught exceptions.
|
|
</p>
|
|
<p>
|
|
Old code that has no user-defined classes or functions 'catch', 'throw'
|
|
and 'try' will run without modifications.
|
|
</p>
|
|
|
|
<h2>Dereferencing objects returned from functions</h2>
|
|
<p>
|
|
In PHP 4 it wasn't possible to dereference objects returned by functions
|
|
and make further method calls on those objects. With PHP 5, the following
|
|
is now possible:
|
|
</p>
|
|
<?php highlight_php('<?php
|
|
class Circle {
|
|
function draw() {
|
|
print "Circle\n";
|
|
}
|
|
}
|
|
|
|
class Square {
|
|
function draw() {
|
|
print "Square\n";
|
|
}
|
|
}
|
|
|
|
function ShapeFactoryMethod($shape) {
|
|
switch ($shape) {
|
|
case "Circle":
|
|
return new Circle();
|
|
case "Square":
|
|
return new Square();
|
|
}
|
|
}
|
|
|
|
ShapeFactoryMethod("Circle")->draw();
|
|
ShapeFactoryMethod("Square")->draw();
|
|
?>'); ?>
|
|
|
|
<h2>Static member variables of static classes can now be initialized</h2>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class foo {
|
|
static $my_static = 5;
|
|
public $my_prop = \'bla\';
|
|
}
|
|
|
|
print foo::$my_static;
|
|
$obj = new foo;
|
|
print $obj->my_prop;
|
|
?>'); ?>
|
|
|
|
<h2>Static Methods</h2>
|
|
<p>
|
|
PHP 5 introduces the 'static' keyword to declare a method static, thus
|
|
callable from outside the object context.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
public static function aStaticMethod() {
|
|
// ...
|
|
}
|
|
}
|
|
|
|
Foo::aStaticMethod();
|
|
?>'); ?>
|
|
<p>
|
|
The pseudo variable <code>$this</code> is not available inside a method
|
|
that has been declared static.
|
|
</p>
|
|
|
|
<h2>instanceof</h2>
|
|
<p>
|
|
PHP 5 introduces the <code>instanceof</code> keyword, that allows you to
|
|
ascertain whether or not an object is an instance of a class, or extends
|
|
a class, or implements an interface.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class baseClass { }
|
|
|
|
$a = new baseClass;
|
|
|
|
if ($a instanceof baseClass) {
|
|
echo "Hello World";
|
|
}
|
|
?>'); ?>
|
|
|
|
<h2>Static function variables</h2>
|
|
<p>
|
|
Statics are now treated at compile-time which allows developers to assign
|
|
variables to statics by reference. This change also greatly improves their
|
|
performance but means that indirect references to statics will not work
|
|
anymore.
|
|
</p>
|
|
|
|
<h2>Parameters that are passed by reference to a function may now have default values</h2>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
function my_function(&$var = null) {
|
|
if ($var === null) {
|
|
die("$var needs to have a value");
|
|
}
|
|
}
|
|
?>'); ?>
|
|
|
|
<h2>__autoload()</h2>
|
|
<p>
|
|
The <code>__autoload()</code> interceptor function will be automatically called
|
|
when an undeclared class is to be instantiated. The name of that class will be
|
|
passed to the <code>__autoload()</code> interceptor function as its only argument.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
function __autoload($className) {
|
|
include_once $className . ".php";
|
|
}
|
|
|
|
$object = new ClassName;
|
|
?>'); ?>
|
|
|
|
<h2>Overloadable Method calls and Property accesses</h2>
|
|
<p>
|
|
Both method calls and property accesses can be overloaded via the
|
|
<code>__call()</code>, <code>__get()</code> and <code>__set()</code>
|
|
methods.
|
|
</p>
|
|
<h3>Example: __get() and __set()</h3>
|
|
<?php highlight_php('<?php
|
|
class Setter {
|
|
public $n;
|
|
public $x = array("a" => 1, "b" => 2, "c" => 3);
|
|
|
|
function __get($nm) {
|
|
print "Getting [$nm]\n";
|
|
|
|
if (isset($this->x[$nm])) {
|
|
$r = $this->x[$nm];
|
|
print "Returning: $r\n";
|
|
return $r;
|
|
} else {
|
|
print "Nothing!\n";
|
|
}
|
|
}
|
|
|
|
function __set($nm, $val) {
|
|
print "Setting [$nm] to $val\n";
|
|
|
|
if (isset($this->x[$nm])) {
|
|
$this->x[$nm] = $val;
|
|
print "OK!\n";
|
|
} else {
|
|
print "Not OK!\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
$foo = new Setter();
|
|
$foo->n = 1;
|
|
$foo->a = 100;
|
|
$foo->a++;
|
|
$foo->z++;
|
|
var_dump($foo);
|
|
?>'); ?>
|
|
<h3>Example: __call()</h3>
|
|
<?php highlight_php('<?php
|
|
class Caller {
|
|
var $x = array(1, 2, 3);
|
|
|
|
function __call($m, $a) {
|
|
print "Method $m called:\n";
|
|
var_dump($a);
|
|
return $this->x;
|
|
}
|
|
}
|
|
|
|
$foo = new Caller();
|
|
$a = $foo->test(1, "2", 3.4, true);
|
|
var_dump($a);
|
|
?>'); ?>
|
|
|
|
<h2>Iteration</h2>
|
|
<p>
|
|
Objects may be iterated in an overloaded way when used with
|
|
foreach. The default behavior is to iterate over all properties.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
var $x = 1;
|
|
var $y = 2;
|
|
}
|
|
|
|
$obj = new Foo;
|
|
|
|
foreach ($obj as $prp_name => $prop_value) {
|
|
// using the property
|
|
}
|
|
?>'); ?>
|
|
<p>
|
|
Each class whose instances can be iterated with foreach should
|
|
implement the empty interface <code>Traversable</code>. Hence any object
|
|
that says it implements <code>Traversable</code> can be used with foreach.
|
|
</p>
|
|
<p>
|
|
The interfaces <code>IteratorAggregate</code> and <code>Iterator</code>
|
|
allows you to specify how class objects are iterated in PHP code. The first
|
|
of them simply has a method <code>getIterator()</code> which must return
|
|
an array or an object that either implements the interface <code>Iterator</code>
|
|
or is instantiated from an internal class that can be iterated.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class ObjectIterator implements Iterator {
|
|
|
|
private $obj;
|
|
private $num;
|
|
|
|
function __construct($obj) {
|
|
$this->obj = $obj;
|
|
}
|
|
function rewind() {
|
|
$this->num = 0;
|
|
}
|
|
function hasMore() {
|
|
return $this->num < $this->obj->max;
|
|
}
|
|
function key() {
|
|
return $this->num;
|
|
}
|
|
function current() {
|
|
switch($this->num) {
|
|
case 0: return "1st";
|
|
case 1: return "2nd";
|
|
case 2: return "3rd";
|
|
default: return $this->num."th";
|
|
}
|
|
}
|
|
function next() {
|
|
$this->num++;
|
|
}
|
|
}
|
|
|
|
class Object implements IteratorAggregate {
|
|
|
|
public $max = 3;
|
|
|
|
function getIterator() {
|
|
return new ObjectIterator($this);
|
|
}
|
|
}
|
|
|
|
$obj = new Object;
|
|
|
|
// this foreach ...
|
|
foreach($obj as $key => $val) {
|
|
echo "$key = $val\n";
|
|
}
|
|
|
|
// matches the following 7 lines with the for directive.
|
|
$it = $obj->getIterator();
|
|
for($it->rewind(); $it->hasMore(); $it->next) {
|
|
$key = $it->current();
|
|
$val = $it->key();
|
|
echo "$key = $val\n";
|
|
}
|
|
unset($it);
|
|
?>'); ?>
|
|
<p>
|
|
The matching for directive is very interesting here since it shows
|
|
the use of all abstract methods declared in the interfaces
|
|
<code>Iterator</code> and <code>IteratorAggregate</code> respectively.
|
|
</p>
|
|
|
|
<h2>New <code>__METHOD__</code> constant</h2>
|
|
<p>
|
|
The new <code>__METHOD__</code> pseudo constant shows the current class
|
|
and method when used inside a method and the function when used outside of a
|
|
class.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
function Show() {
|
|
echo __FILE__ . \'(\' . __LINE__ . \')\' . __METHOD__;
|
|
}
|
|
}
|
|
function Test() {
|
|
echo __FILE__ . \'(\' . __LINE__ . \')\' . __METHOD__;
|
|
}
|
|
?>'); ?>
|
|
|
|
<h2>New <code>__toString()</code> method</h2>
|
|
|
|
<p>
|
|
The new <code>__toString()</code> magic method allows you to overload the
|
|
object to string conversion.
|
|
</p>
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
function __toString() {
|
|
return "What ever";
|
|
}
|
|
}
|
|
|
|
$obj = Foo;
|
|
|
|
$str = (string) $obj; // call __toString()
|
|
|
|
echo $obj; // call __toString()
|
|
?>'); ?>
|
|
|
|
<h2>Reflection API</h2>
|
|
|
|
<p>
|
|
PHP 5 comes with a complete reflection API that adds the ability to
|
|
reverse-engineer classes, interfaces, functions and methods as well
|
|
as extensions.
|
|
</p>
|
|
|
|
<p>
|
|
The reflection API also offers ways of getting doc comments for
|
|
functions, classes and methods.
|
|
</p>
|
|
|
|
<p>
|
|
Nearly all aspects of object oriented code can be reflected by
|
|
using the reflection API which is
|
|
<a href="http://sitten-polizei.de/php/reflection_api/docs/language.reflection.html">documented
|
|
separately</a>.
|
|
</p>
|
|
|
|
<h3>Example</h3>
|
|
<?php highlight_php('<?php
|
|
class Foo {
|
|
public $prop;
|
|
function Func($name) {
|
|
echo "Hello $name";
|
|
}
|
|
}
|
|
|
|
reflection_class::export(\'Foo\');
|
|
reflection_object::export(new Foo);
|
|
reflection_method::export(\'Foo\', \'func\');
|
|
reflection_property::export(\'Foo\', \'prop\');
|
|
reflection_extension::export(\'standard\');
|
|
?>'); ?>
|
|
|
|
<h2>New memory manager</h2>
|
|
<p>
|
|
PHP 5 has a new memory manager which allows it to run efficiently in
|
|
multi-threaded environments as it doesn't need to use mutexes to lock
|
|
and unlock during allocation/deallocation.
|
|
</p>
|
|
|
|
<?php site_footer(); ?>
|