cvs: phpweb / ZEND_CHANGES.txt index.php zend2_example.php /gifs engine.gif
| From: | Zeev Suraski | Date: | Sun, 09 Jun 2002 15:59:30 +0000 |
| Subject: | cvs: phpweb / ZEND_CHANGES.txt index.php zend2_example.php /gifs engine.gif | ||
| Groups: | php.mirrors | ||
| Request: | Send a blank email to php-mirrors+get-10750@lists.php.net to get a copy of this message | ||
zeev Sun Jun 9 11:59:30 2002 EDT
Added files:
/phpweb ZEND_CHANGES.txt zend2_example.php
/phpweb/gifs engine.gif
Modified files:
/phpweb index.php
Log:
Publish 4.3.0-ZE2 alpha
Index: phpweb/index.php diff -u phpweb/index.php:1.246 phpweb/index.php:1.247 --- phpweb/index.php:1.246 Fri Jun 7 14:40:15 2002 +++ phpweb/index.php Sun Jun 9 11:59:30 2002 @@ -114,6 +114,29 @@ echo "\n<!--$MYSITE-->\n"; ?> +<?php echo make_image("engine.gif", "Zend Engine 2", "right"); ?> + +<h1>Initial Alpha Release of PHP w/ the Zend Engine 2 Available</h1> +<font class="newsdate">[9-Jun-2002]</font> +The first alpha release of PHP w/ Zend Engine2 is +<a href="distributions/php-4.3.0-dev-zend2-alpha1.tar.gz">now available</a>. +It is based on the current PHP 4 CVS (4.3.0-dev) and includes the new +scripting engine which greatly improves the object model, adds exception +handling and provides a much better infrastructure for the integration +of external technologies like Java or .NET. For more details and +examples you can check out the <a href="ZEND_CHANGES.txt">CHANGES file</a> +and an <a href="http://www.php.net/source.php?url=/zend2_example.php">example script</a> +which shows how some of these features can be used. + +<b>Note:</b> This is an alpha version. It should not be used in production +or even semi-production web sites. There are known bugs in it, and in +addition, some of the features may change (based on feedback). We +encourage you to download and play with it (and report bugs if you find any!), +but please don't expect it to replace your copy of PHP 4 at this stage. + +<?php echo hdelim(); ?> + + <h1>ActiveState Awards</h1> <p> ActiveState is delighted to announce the second annual Programmers' Index: phpweb/ZEND_CHANGES.txt +++ phpweb/ZEND_CHANGES.txt Changes in the Zend Engine 2.0 * New Object Model. The Zend Engine's handling of objects has been completely changed in order to allow for new features, but also to increase its performance. Objects were handled in previous versions like primitive types (for instance integers and strings). The drawback of this method is, that semantically the whole object was copied when a variable was assigned or parameters were passed to a method. The new approach refers to objects by handle and not by value (one can think of a handle as an object's ID). Many PHP programmers aren't even aware of the copying quirks of the old object model and, therefore, there is a relatively good chance that the amount of PHP applications that will work out of the box or after a very small amount of modifications would be high. * Private Members. The Zend Engine 2.0 introduces private member variables. Note that for performance reasons no error message is emitted in case of an illegal access to a private member variable. Example: <?php class MyClass { private $Hello = "Hello, World!\n"; function printHello() { print $this->Hello; } } class MyClass2 extends MyClass { function printHello() { MyClass::printHello(); /* Should print */ print $this->Hello; /* Shouldn't print out anything */ } } $obj = new MyClass(); print $obj->Hello; /* Shouldn't print out anything */ $obj->printHello(); /* Should print */ $obj = new MyClass2(); print $obj->Hello; /* Shouldn't print out anything */ $obj->printHello(); ?> * Object Cloning. The Zend Engine 1.0 offered no way a user could decide what copy constructor to run when an object is duplicated. During duplication, the Zend Engine 1.0 did a bitwise copy making an identical replica of all the object's properties. 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. An object copy is created by calling the object's __clone() method. Example: <?php $copy_of_object = $object->__clone(); ?> When the developer asks to create a new copy of an object, the Zend Engine will check if a __clone() method has been defined or not. If not, it will call a default __clone() which will copy all of the object's properties. If a __clone() 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. [The function hasn't been implemented yet] Example: <?php class MyCloneable { static $id = 0; function MyCloneable() { $this->id = self::$id++; } function __clone() { $this->name = $clone->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"; ?> * Forced deletion of objects. The Zend Engine 1.0 had no means to force deletion of an object if there are still references to it. The newly introduced delete statement calls the object's destructor and frees it even if the object is referenced by some other places in the engine. Other references to the deleted object become stale and trying to access them results in a fatal error. Note that if you have a user-defined function delete() in an old script, this script will yield a parser error with the Zend Engine 2.0, since 'delete' is now a reserved word. * Nested classes (namespaces). The Zend Engine 1.0 provided only three scopes: the global scope, the class scope and the function scope. All scopes but classes could contain variables, only the class and global scopes could contain functions, while only the global scope could contain constants and classes. This means that all of the Zend Engine 1.0's scoping methods were inherently limited for solving symbol name collision problems. The Zend Engine 2.0 introduces the concept of nested classes to solve the symbol collision problem by making it possible to define multiple symbol tables able to contain all types of symbols. The Zend Engine is aware of a current class, defaulting to the global scope. Each class can contain it's own set of constants, functions and static variables. In order to access a class's local symbols you can use the self:: class accessor, for example, you can do self::$my_static_name = "Hello". You can also use the class's name such as MyClass::$my_static_name = "Hello". WIth both constants and functions, if you don't specify a class context the current class will be searched first and if the search fails then the global scope will be searched. If you want to force PHP to only check the global scope you can use the main:: accessor. For example, main::strlen() to make sure you're calling the strlen() in the main scope. You will only need to worry about this if you are defining methods which have the same name as global functions. For constants you can use the same notation such as self::MY_CONSTANT or main::MY_CONSTANT. Sometimes you will not want to access constants, functions or classes via the class accessor (i.e. MyClass::) because you use them very often and are an extremely slow typist. In this case, you can import functions, classes and constants from classes with the import keyword. It's quite self explanatory and there are a few examples below. * Classes may contain classes. Example: <?php class DB::MySQL { var $host = ''; function db_connect($user) { print "Connecting to MySQL database '$this->host' as $user\n"; } } class DB::Oracle { var $host = 'localhost'; function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } } $MySQL_obj = new DB::MySQL(); $MySQL_obj->db_connect('Susan'); $Oracle_obj = new DB::Oracle(); $Oracle_obj->db_connect('Barbara'); ?> * Classes may contain constants. Example: <?php class foo { const hey = 'hello'; } print foo::hey; ?> * Current namespace's symbol tables are searched first for constants and functions. Example: The following code prints "foobar", not "foo", because the class constant overrides the "global" constant of the same name. <?php define('foo', 'bar'); class FooClass { const foo = 'foobar'; function printFoo() { print foo; } } ?> * In the scope of a function, the current namespace is that of the containing class/namespace. Example: <?php class FooClass { function foo() { $this->bar(); bar(); } function bar() { print "foobar\n"; } } $obj = new FooClass; $obj->foo(); $obj->foo(); ?> This prints "foobar" two times, since a bar() method exists in the current namespace. * It is possible to "import" symbols from one namespace into another. Example: <?php class MyClass { class MyClass2 { function hello() { print "Hello, World in MyClass2\n"; } } function hello() { print "Hello, World\n"; } } import function hello, class MyClass2 from MyClass; MyClass2::hello(); hello(); ?> Example: <?php class MyOuterClass { class MyInnerClass { function func1() { print "func1()\n"; } function func2() { print "func2()\n"; } } } import class * from MyOuterClass; import function func2 from MyOuterClass::MyInnerClass; MyInnerClass::func1(); func2(); ?> Example: <?php class MyOuterClass { const Hello = "Hello, World\n"; } import const Hello from MyOuterClass; print Hello; ?> Old code that does not take advantage of namespaces will run without modifications. * Unified Constructors. The Zend Engine 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 can be used. With the Zend Engine 1.0, 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 the Zend Engine 1.0 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. The Zend Engine 2.0 introduces a standard way of declaring constructor methods by calling them by the name __construct(). Example: <?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(); ?> For backwards compatibility, if the Zend Engine 2.0 cannot find a __construct() 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 __construct() which was used for different semantics. * Destructors. 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 the Zend Engine 1.0, although PHP had already support for registering functions which should be run on request shutdown. The Zend Engine 2.0 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 name __destruct() that recieves no parameters, is called before the object is freed from memory. Example: <?php class MyDestructableClass { function __construct() { print "In constructor\n"; $this->name = 'MyDestructableClass'; } function __destruct() { print 'Destroying ' . $this->name . "\n"; } } $obj = new MyDestructableClass(); ?> 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 parent::__destruct() in the destructor body. * Exceptions. The Zend Engine 1.0 had no exception handling. The Zend Engine 2.0 introduces a exception model similar to that of other programming languages. Example: <?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(); } ?> Old code that has no user-defined functions 'catch', 'throw' and 'try' will run without modifications. * Dereferencing objects returned from functions. Example: <?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(); ?> * Static member variables of static classes can now be initialized. Example: <?php class foo { static $my_static = 5; } print foo::$my_static; ?> * Parameters that are passed by reference to a function may now have default values. Example: <?php function my_function(&$var = null) { if ($var === null) { die('$var needs to have a value'); } } ?> * Built-In Backtracing. Example: <?php $backtrace = debug_backtrace(); foreach ($backtrace as $step) { $class = isset($step['class']) ? $step['class'] . '::' : ''; printf( "%s [%s:%s]\n", $step['function'], $step['file'], $step['line'] ); } ?> Index: phpweb/zend2_example.php +++ phpweb/zend2_example.php Example 1: A singleton (static members) ======================================= <?php class Counter { var $counter = 0; function increment_and_print() { print ++$this->counter; print "\n"; } } class SingletonCounter { static $m_instance = NULL; function Instance() { if (self::$m_instance == NULL) { self::$m_instance = new Counter(); } return self::$m_instance; } } SingletonCounter::Instance()->increment_and_print(); SingletonCounter::Instance()->increment_and_print(); SingletonCounter::Instance()->increment_and_print(); ?> Example 2: Factory method (derefencing objects returned from functions) ======================================================================= <?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(); ?> Example 3: Nested class ======================= <?php class Database { class MySQL { var $host = ""; function db_connect($user) { print "Connecting to MySQL database '$this->host' as $user\n"; } } class Oracle { var $host = "localhost"; function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } } } $MySQL_obj = new Database::MySQL(); $MySQL_obj->db_connect("John"); $Oracle_obj = new Database::Oracle(); $Oracle_obj->db_connect("Mark"); unset($MySQL_obj); unset($Oracle_obj); ?> Example 3: Nested class suitable for a PEAR like hierarchy ========================================================== <?php class DB::MySQL { var $host = ""; function db_connect($user) { print "Connecting to MySQL database '$this->host' as $user\n"; } } class DB::Oracle { var $host = "localhost"; function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } } $MySQL_obj = new DB::MySQL(); $MySQL_obj->db_connect("Susan"); $Oracle_obj = new DB::Oracle(); $Oracle_obj->db_connect("Barbara"); ?> Example 4: Class constants and class scope ========================================== <?php class ErrorCodes { const FATAL = "Fatal error\n"; const WARNING = "Warning\n"; const INFO = "Informational message\n"; function print_fatal_error_codes() { print "FATAL = " . FATAL; print "self::FATAL = " . self::FATAL; } } /* Call the static function and move into the ErrorCodes scope */ ErrorCodes::print_fatal_error_codes(); ?> Example 5: Regular object method using both local and global functions ====================================================================== <?php class HelloWorld { const HELLO_WORLD = "Hello, World!\n"; function get_hello_world() { return HELLO_WORLD; } function length_of_hello_world() { $str = get_hello_world(); return strlen($str); } } $obj = new HelloWorld(); print "length_of_hello_world() = " . $obj->length_of_hello_world(); print "\n"; ?> Example 6: Multiple derefencing of objects returned from methods ================================================================ <?php class Name { function Name($_name) { $this->name = $_name; } function display() { print $this->name; print "\n"; } } class Person { function Person($_name, $_address) { $this->name = new Name($_name); } function getName() { return $this->name; } } $person = new Person("John", "New York"); print $person->getName()->display(); ?> Example 7: Exception handling ============================= <? class MyException { function MyException($_error) { $this->error = $_error; } function getException() { return $this->error; } } function ThrowException() { throw new MyException("'This is an exception!'"); } try { } catch (MyException $exception) { print "There was an exception: " . $exception->getException(); print "\n"; } try { ThrowException(); } catch (MyException $exception) { print "There was an exception: " . $exception->getException(); print "\n"; } ?> Example 8: __clone() =================== <? class MyCloneable { static $id = 0; function MyCloneable() { $this->id = self::$id++; } function __clone() { $this->name = $clone->name; $this->address = "New York"; $this->id = self::$id++; } } $obj = new MyCloneable(); $obj->name = "Hello"; $obj->address = "Tel-Aviv"; print $obj->id; print "\n"; $obj = $obj->__clone(); print $obj->id; print "\n"; print $obj->name; print "\n"; print $obj->address; print "\n"; ?> Example 9: Unified constructors =============================== <? 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(); ?> Example 10: Destructors ======================= <?php class MyDestructableClass { function __construct() { print "In constructor\n"; $this->name = "MyDestructableClass"; } function __destruct() { print "Destroying " . $this->name . "\n"; } } $obj = new MyDestructableClass(); ?>
Index: phpweb/index.php diff -u phpweb/index.php:1.246 phpweb/index.php:1.247 --- phpweb/index.php:1.246 Fri Jun 7 14:40:15 2002 +++ phpweb/index.php Sun Jun 9 11:59:30 2002 @@ -114,6 +114,29 @@ echo "\n<!--$MYSITE-->\n"; ?> +<?php echo make_image("engine.gif", "Zend Engine 2", "right"); ?> + +<h1>Initial Alpha Release of PHP w/ the Zend Engine 2 Available</h1> +<font class="newsdate">[9-Jun-2002]</font> +The first alpha release of PHP w/ Zend Engine2 is +<a href="distributions/php-4.3.0-dev-zend2-alpha1.tar.gz">now available</a>. +It is based on the current PHP 4 CVS (4.3.0-dev) and includes the new +scripting engine which greatly improves the object model, adds exception +handling and provides a much better infrastructure for the integration +of external technologies like Java or .NET. For more details and +examples you can check out the <a href="ZEND_CHANGES.txt">CHANGES file</a> +and an <a href="http://www.php.net/source.php?url=/zend2_example.php">example script</a> +which shows how some of these features can be used. + +<b>Note:</b> This is an alpha version. It should not be used in production +or even semi-production web sites. There are known bugs in it, and in +addition, some of the features may change (based on feedback). We +encourage you to download and play with it (and report bugs if you find any!), +but please don't expect it to replace your copy of PHP 4 at this stage. + +<?php echo hdelim(); ?> + + <h1>ActiveState Awards</h1> <p> ActiveState is delighted to announce the second annual Programmers' Index: phpweb/ZEND_CHANGES.txt +++ phpweb/ZEND_CHANGES.txt Changes in the Zend Engine 2.0 * New Object Model. The Zend Engine's handling of objects has been completely changed in order to allow for new features, but also to increase its performance. Objects were handled in previous versions like primitive types (for instance integers and strings). The drawback of this method is, that semantically the whole object was copied when a variable was assigned or parameters were passed to a method. The new approach refers to objects by handle and not by value (one can think of a handle as an object's ID). Many PHP programmers aren't even aware of the copying quirks of the old object model and, therefore, there is a relatively good chance that the amount of PHP applications that will work out of the box or after a very small amount of modifications would be high. * Private Members. The Zend Engine 2.0 introduces private member variables. Note that for performance reasons no error message is emitted in case of an illegal access to a private member variable. Example: <?php class MyClass { private $Hello = "Hello, World!\n"; function printHello() { print $this->Hello; } } class MyClass2 extends MyClass { function printHello() { MyClass::printHello(); /* Should print */ print $this->Hello; /* Shouldn't print out anything */ } } $obj = new MyClass(); print $obj->Hello; /* Shouldn't print out anything */ $obj->printHello(); /* Should print */ $obj = new MyClass2(); print $obj->Hello; /* Shouldn't print out anything */ $obj->printHello(); ?> * Object Cloning. The Zend Engine 1.0 offered no way a user could decide what copy constructor to run when an object is duplicated. During duplication, the Zend Engine 1.0 did a bitwise copy making an identical replica of all the object's properties. 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. An object copy is created by calling the object's __clone() method. Example: <?php $copy_of_object = $object->__clone(); ?> When the developer asks to create a new copy of an object, the Zend Engine will check if a __clone() method has been defined or not. If not, it will call a default __clone() which will copy all of the object's properties. If a __clone() 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. [The function hasn't been implemented yet] Example: <?php class MyCloneable { static $id = 0; function MyCloneable() { $this->id = self::$id++; } function __clone() { $this->name = $clone->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"; ?> * Forced deletion of objects. The Zend Engine 1.0 had no means to force deletion of an object if there are still references to it. The newly introduced delete statement calls the object's destructor and frees it even if the object is referenced by some other places in the engine. Other references to the deleted object become stale and trying to access them results in a fatal error. Note that if you have a user-defined function delete() in an old script, this script will yield a parser error with the Zend Engine 2.0, since 'delete' is now a reserved word. * Nested classes (namespaces). The Zend Engine 1.0 provided only three scopes: the global scope, the class scope and the function scope. All scopes but classes could contain variables, only the class and global scopes could contain functions, while only the global scope could contain constants and classes. This means that all of the Zend Engine 1.0's scoping methods were inherently limited for solving symbol name collision problems. The Zend Engine 2.0 introduces the concept of nested classes to solve the symbol collision problem by making it possible to define multiple symbol tables able to contain all types of symbols. The Zend Engine is aware of a current class, defaulting to the global scope. Each class can contain it's own set of constants, functions and static variables. In order to access a class's local symbols you can use the self:: class accessor, for example, you can do self::$my_static_name = "Hello". You can also use the class's name such as MyClass::$my_static_name = "Hello". WIth both constants and functions, if you don't specify a class context the current class will be searched first and if the search fails then the global scope will be searched. If you want to force PHP to only check the global scope you can use the main:: accessor. For example, main::strlen() to make sure you're calling the strlen() in the main scope. You will only need to worry about this if you are defining methods which have the same name as global functions. For constants you can use the same notation such as self::MY_CONSTANT or main::MY_CONSTANT. Sometimes you will not want to access constants, functions or classes via the class accessor (i.e. MyClass::) because you use them very often and are an extremely slow typist. In this case, you can import functions, classes and constants from classes with the import keyword. It's quite self explanatory and there are a few examples below. * Classes may contain classes. Example: <?php class DB::MySQL { var $host = ''; function db_connect($user) { print "Connecting to MySQL database '$this->host' as $user\n"; } } class DB::Oracle { var $host = 'localhost'; function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } } $MySQL_obj = new DB::MySQL(); $MySQL_obj->db_connect('Susan'); $Oracle_obj = new DB::Oracle(); $Oracle_obj->db_connect('Barbara'); ?> * Classes may contain constants. Example: <?php class foo { const hey = 'hello'; } print foo::hey; ?> * Current namespace's symbol tables are searched first for constants and functions. Example: The following code prints "foobar", not "foo", because the class constant overrides the "global" constant of the same name. <?php define('foo', 'bar'); class FooClass { const foo = 'foobar'; function printFoo() { print foo; } } ?> * In the scope of a function, the current namespace is that of the containing class/namespace. Example: <?php class FooClass { function foo() { $this->bar(); bar(); } function bar() { print "foobar\n"; } } $obj = new FooClass; $obj->foo(); $obj->foo(); ?> This prints "foobar" two times, since a bar() method exists in the current namespace. * It is possible to "import" symbols from one namespace into another. Example: <?php class MyClass { class MyClass2 { function hello() { print "Hello, World in MyClass2\n"; } } function hello() { print "Hello, World\n"; } } import function hello, class MyClass2 from MyClass; MyClass2::hello(); hello(); ?> Example: <?php class MyOuterClass { class MyInnerClass { function func1() { print "func1()\n"; } function func2() { print "func2()\n"; } } } import class * from MyOuterClass; import function func2 from MyOuterClass::MyInnerClass; MyInnerClass::func1(); func2(); ?> Example: <?php class MyOuterClass { const Hello = "Hello, World\n"; } import const Hello from MyOuterClass; print Hello; ?> Old code that does not take advantage of namespaces will run without modifications. * Unified Constructors. The Zend Engine 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 can be used. With the Zend Engine 1.0, 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 the Zend Engine 1.0 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. The Zend Engine 2.0 introduces a standard way of declaring constructor methods by calling them by the name __construct(). Example: <?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(); ?> For backwards compatibility, if the Zend Engine 2.0 cannot find a __construct() 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 __construct() which was used for different semantics. * Destructors. 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 the Zend Engine 1.0, although PHP had already support for registering functions which should be run on request shutdown. The Zend Engine 2.0 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 name __destruct() that recieves no parameters, is called before the object is freed from memory. Example: <?php class MyDestructableClass { function __construct() { print "In constructor\n"; $this->name = 'MyDestructableClass'; } function __destruct() { print 'Destroying ' . $this->name . "\n"; } } $obj = new MyDestructableClass(); ?> 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 parent::__destruct() in the destructor body. * Exceptions. The Zend Engine 1.0 had no exception handling. The Zend Engine 2.0 introduces a exception model similar to that of other programming languages. Example: <?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(); } ?> Old code that has no user-defined functions 'catch', 'throw' and 'try' will run without modifications. * Dereferencing objects returned from functions. Example: <?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(); ?> * Static member variables of static classes can now be initialized. Example: <?php class foo { static $my_static = 5; } print foo::$my_static; ?> * Parameters that are passed by reference to a function may now have default values. Example: <?php function my_function(&$var = null) { if ($var === null) { die('$var needs to have a value'); } } ?> * Built-In Backtracing. Example: <?php $backtrace = debug_backtrace(); foreach ($backtrace as $step) { $class = isset($step['class']) ? $step['class'] . '::' : ''; printf( "%s [%s:%s]\n", $step['function'], $step['file'], $step['line'] ); } ?> Index: phpweb/zend2_example.php +++ phpweb/zend2_example.php Example 1: A singleton (static members) ======================================= <?php class Counter { var $counter = 0; function increment_and_print() { print ++$this->counter; print "\n"; } } class SingletonCounter { static $m_instance = NULL; function Instance() { if (self::$m_instance == NULL) { self::$m_instance = new Counter(); } return self::$m_instance; } } SingletonCounter::Instance()->increment_and_print(); SingletonCounter::Instance()->increment_and_print(); SingletonCounter::Instance()->increment_and_print(); ?> Example 2: Factory method (derefencing objects returned from functions) ======================================================================= <?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(); ?> Example 3: Nested class ======================= <?php class Database { class MySQL { var $host = ""; function db_connect($user) { print "Connecting to MySQL database '$this->host' as $user\n"; } } class Oracle { var $host = "localhost"; function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } } } $MySQL_obj = new Database::MySQL(); $MySQL_obj->db_connect("John"); $Oracle_obj = new Database::Oracle(); $Oracle_obj->db_connect("Mark"); unset($MySQL_obj); unset($Oracle_obj); ?> Example 3: Nested class suitable for a PEAR like hierarchy ========================================================== <?php class DB::MySQL { var $host = ""; function db_connect($user) { print "Connecting to MySQL database '$this->host' as $user\n"; } } class DB::Oracle { var $host = "localhost"; function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } } $MySQL_obj = new DB::MySQL(); $MySQL_obj->db_connect("Susan"); $Oracle_obj = new DB::Oracle(); $Oracle_obj->db_connect("Barbara"); ?> Example 4: Class constants and class scope ========================================== <?php class ErrorCodes { const FATAL = "Fatal error\n"; const WARNING = "Warning\n"; const INFO = "Informational message\n"; function print_fatal_error_codes() { print "FATAL = " . FATAL; print "self::FATAL = " . self::FATAL; } } /* Call the static function and move into the ErrorCodes scope */ ErrorCodes::print_fatal_error_codes(); ?> Example 5: Regular object method using both local and global functions ====================================================================== <?php class HelloWorld { const HELLO_WORLD = "Hello, World!\n"; function get_hello_world() { return HELLO_WORLD; } function length_of_hello_world() { $str = get_hello_world(); return strlen($str); } } $obj = new HelloWorld(); print "length_of_hello_world() = " . $obj->length_of_hello_world(); print "\n"; ?> Example 6: Multiple derefencing of objects returned from methods ================================================================ <?php class Name { function Name($_name) { $this->name = $_name; } function display() { print $this->name; print "\n"; } } class Person { function Person($_name, $_address) { $this->name = new Name($_name); } function getName() { return $this->name; } } $person = new Person("John", "New York"); print $person->getName()->display(); ?> Example 7: Exception handling ============================= <? class MyException { function MyException($_error) { $this->error = $_error; } function getException() { return $this->error; } } function ThrowException() { throw new MyException("'This is an exception!'"); } try { } catch (MyException $exception) { print "There was an exception: " . $exception->getException(); print "\n"; } try { ThrowException(); } catch (MyException $exception) { print "There was an exception: " . $exception->getException(); print "\n"; } ?> Example 8: __clone() =================== <? class MyCloneable { static $id = 0; function MyCloneable() { $this->id = self::$id++; } function __clone() { $this->name = $clone->name; $this->address = "New York"; $this->id = self::$id++; } } $obj = new MyCloneable(); $obj->name = "Hello"; $obj->address = "Tel-Aviv"; print $obj->id; print "\n"; $obj = $obj->__clone(); print $obj->id; print "\n"; print $obj->name; print "\n"; print $obj->address; print "\n"; ?> Example 9: Unified constructors =============================== <? 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(); ?> Example 10: Destructors ======================= <?php class MyDestructableClass { function __construct() { print "In constructor\n"; $this->name = "MyDestructableClass"; } function __destruct() { print "Destroying " . $this->name . "\n"; } } $obj = new MyDestructableClass(); ?>