lovchy          Sun May 23 12:30:39 2004 EDT

  Modified files:              
    /phpdoc/en/appendices       migration5.xml 
  Log:
  Changes in PHP5/Zend2 inserted into OOP section
  
http://cvs.php.net/diff.php/phpdoc/en/appendices/migration5.xml?r1=1.15&r2=1.16&ty=u
Index: phpdoc/en/appendices/migration5.xml
diff -u phpdoc/en/appendices/migration5.xml:1.15 
phpdoc/en/appendices/migration5.xml:1.16
--- phpdoc/en/appendices/migration5.xml:1.15    Wed Apr 14 22:30:57 2004
+++ phpdoc/en/appendices/migration5.xml Sun May 23 12:30:39 2004
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!-- $Revision: 1.15 $ -->
+<!-- $Revision: 1.16 $ -->
  <appendix id="migration5">
   <title>Migrating from PHP 4 to PHP 5</title>
 
   <section id='migration5.changes'>
    <title>What has changed in PHP 5</title>
    <para>
-    PHP 5 and the integrated Zend Engine 2 have greatly improved PHP's
+    &php; 5 and the integrated Zend Engine 2 have greatly improved PHP's
     performance and capabilities, but great care has been taken to break as
-    little existing code as possible. So migrating your code from PHP 4 to 5
-    should be very easy. Most existing PHP 4 code should be ready to run
+    little existing code as possible. So migrating your code from &php; 4 to 5
+    should be very easy. Most existing &php; 4 code should be ready to run
     without changes, but you should still know about the <link
      linkend="migration5.incompatible">few differences</link> and
     take care to test your code before switching versions in production
@@ -20,7 +20,7 @@
   <section id="migration5.incompatible">
    <title>Backward Incompatible Changes</title>
    <para>
-    Although most existing PHP 4 code should work without changes, you should
+    Although most existing &php; 4 code should work without changes, you should
     pay attention to the following backward incompatible changes:
    </para>
    <itemizedlist>
@@ -40,7 +40,7 @@
     </simpara></listitem>
     <listitem><simpara>
      PATH_TRANSLATED server variable is no longer set implicitly under
-     Apache2 SAPI in contrast to the situation in PHP 4, where it is set to
+     Apache2 SAPI in contrast to the situation in &php; 4, where it is set to
      the same value as the SCRIPT_FILENAME server variable when it is not
      populated by Apache. This change was made to comply with the <ulink
       url="&url.cgispecs;">CGI specification</ulink>. Please refer to <ulink
@@ -49,11 +49,11 @@
     <listitem><simpara>
      The <constant>T_ML_CONSTANT</constant> constant is no longer defined by
      the <link linkend="ref.tokenizer">Tokenizer</link> extension. If
-     error_reporting is set to <constant>E_ALL</constant>, PHP will generate a
+     error_reporting is set to <constant>E_ALL</constant>, &php; will generate a
      notice. Although the <constant>T_ML_CONSTANT</constant> was never used
-     at all, it was defined in PHP 4. In both PHP 4 and PHP 5  // and /* */
+     at all, it was defined in &php; 4. In both &php; 4 and &php; 5  // and /* */
      are resolved as the <constant>T_COMMENT</constant> constant. However the
-     PHPDoc style comments /** */ ,which starting PHP 5 are parsed by PHP, are
+     PHPDoc style comments /** */ ,which starting &php; 5 are parsed by &php;, are
      recognized as <constant>T_DOC_COMMENT</constant>.
     </simpara></listitem>
     <listitem><simpara>
@@ -110,8 +110,8 @@
     </example>
    </para>
    <para>
-    The following example was valid in PHP 4, although it will produce a fatal
-    error in PHP 5.
+    The following example was valid in &php; 4, although it will produce a fatal
+    error in &php; 5.
    </para>
    <para>
     <example>
@@ -137,19 +137,19 @@
   <section id="migration5.cli-cgi">
    <title>CLI and CGI</title>
    <para>
-    In PHP 5 there were some changes in CLI and CGI filenames. In PHP 5, the
+    In &php; 5 there were some changes in CLI and CGI filenames. In &php; 5, the
     CGI version was renamed to <literal>php-cgi.exe</literal> (previously
     <literal>php.exe</literal>) and the CLI version now sits in the main
     directory (previously <literal>cli/php.exe</literal>).
    </para>
    <para>
-    In PHP 5 it was also introduced a new mode:
+    In &php; 5 it was also introduced a new mode:
     <literal>php-win.exe</literal>. This is equal to the CLI version, except
     that php-win doesn't output anything and thus provides no console (no "dos
     box" appears on the screen). This behavior is similar to php-gtk.
    </para>
    <para>
-    In PHP 5, the CLI version will always populate the global $argv and $argc
+    In &php; 5, the CLI version will always populate the global $argv and $argc
     variables.
    </para>
   </section>
@@ -179,7 +179,7 @@
     </informalexample>
    </para>
    <para>
-    If your webserver is running PHP in CGI mode, you should note that the
+    If your webserver is running &php; in CGI mode, you should note that the
     CGI version has changed its name from php.exe to php-cgi.exe.
     In Apache you should do something like this:
     <informalexample>
@@ -203,7 +203,7 @@
   <section id="migration5.functions">
    <title>New Functions</title>
    <para>
-    In PHP 5 there are some new functions. Here is the list of them:
+    In &php; 5 there are some new functions. Here is the list of them:
    </para>
    <para>Arrays:</para>
     <itemizedlist>
@@ -522,7 +522,7 @@
   <section id="migration5.newconf">
    <title>New Directives</title>
    <para>
-    There were some new &php.ini; directives introduced in PHP 5. Here is a
+    There were some new &php.ini; directives introduced in &php; 5. Here is a
     list of them:
    </para>
    <itemizedlist>
@@ -534,7 +534,7 @@
    </simpara></listitem>
     <listitem><simpara>
      <link linkend="ini.register-long-arrays">register_long_arrays</link> -
-     allow/disallow PHP to register the deprecated long $HTTP_*_VARS
+     allow/disallow &php; to register the deprecated long $HTTP_*_VARS
    </simpara></listitem>
     <listitem><simpara>
       <link linkend="ini.session.hash-function">session.hash_function</link> -
@@ -547,7 +547,7 @@
       binary hash data to something readable (from 4 to 6)
    </simpara></listitem>
     <listitem><simpara>
-     zend.ze1_compatibility_mode - Enable compatibility mode with Zend Engine 1 (PHP 
4)
+     zend.ze1_compatibility_mode - Enable compatibility mode with Zend Engine 1 
(&php; 4)
    </simpara></listitem>
    </itemizedlist>
   </section>
@@ -555,10 +555,10 @@
   <section id="migration5.databases">
    <title>Databases</title>
    <para>
-    There were some changes in PHP 5 regarding databases (MySQL and SQLite).
+    There were some changes in &php; 5 regarding databases (MySQL and SQLite).
    </para>
    <para>
-    In PHP 5 the MySQL client libraries are not bundled, because of license
+    In &php; 5 the MySQL client libraries are not bundled, because of license
     problems and some others. For more information, read the <link
      linkend="faq.databases.mysql.php5">FAQ entry</link>.
    </para>
@@ -567,24 +567,1107 @@
      MySQL)</link>, which is designed to work with MySQL 4.1 and above.
    </para>
    <para>
-    Since PHP 5, the <link linkend="ref.sqlite">SQLite</link> extension is
-    built-in PHP. SQLite is an embeddable SQL database engine and is not a
+    Since &php; 5, the <link linkend="ref.sqlite">SQLite</link> extension is
+    built-in &php;. SQLite is an embeddable SQL database engine and is not a
     client library used to connect to a big database server (like MySQL or
     PostgreSQL). The SQLite library reads and writes directly to and from the
     database files on disk.
    </para>
   </section>
 
+
   <section id='migration5.oop'>
    <title>New Object Model</title>
    <para>
-    In PHP 5 there is a new Object Model. PHP's handling of objects has been
+    In &php; 5 there is a new Object Model. PHP's handling of objects has been
     completely rewritten, allowing for better performance and more features.
-    Please read <ulink
-     
url="http://www.php.net/zend-engine-2.php";>http://www.php.net/zend-engine-2.php</ulink>
-    for more info.
+    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).
+   </para>
+   <para>
+    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.
    </para>
+
+   <section id='migration.oop.members'>
+    <title>Private and Protected Members</title>
+    <para>
+     &php; 5 introduces private and protected member variables, they allow you
+     to define the visibility of class properties.
+    </para>
+    <example>
+     <title>Private and Protected Members accesibility</title>
+     <simpara>
+      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.
+     </simpara>
+     <programlisting role="php">
+<![CDATA[
+<?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();
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+   
+   <section id='migration.oop.methods'>
+    <title>Private and Protected Methods</title>
+    <para>
+     With &php; 5, private and protected methods are also introduced.
+    </para>
+    <example>
+     <title>Protected methods example</title>
+     <programlisting role="php">
+<![CDATA[
+<?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();
+?>
+]]>
+     </programlisting>
+    </example>
+    <simpara>
+     Old code that has no user-defined classes or functions named 
+     &quot;public&quot;, &quot;protected&quot; or &quot;private&quot; should
+     run without modifications.
+    </simpara>
+   </section>
+
+   <section id='migration.oop.abstract'>
+    <title>Abstract Classes and Methods</title>
+    <para>
+     &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.
+    </para>
+    <example>
+     <title>Abstract class example</title>
+     <programlisting role="php">
+<![CDATA[
+<?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();
+?> 
+]]>
+     </programlisting>
+    </example>
+    <simpara>
+     Abstract classes cannot be instantiated. Old code that has no
+     user-defined classes or functions named 'abstract' should run without
+     modifications.
+    </simpara>
+   </section> 
+   
+   <section id='migration.oop.interfaces'>
+    <title>Interfaces</title>
+    <para>
+     &php; 5 introduces interfaces. A class may implement an arbitrary list of
+     interfaces.
+    </para>
+    <example>
+     <title>Interface example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+interface Throwable {
+    public function getMessage();
+}
+
+class MyException implements Throwable {
+    public function getMessage() {
+        // ...
+    }
+}
+?> 
+]]>
+      </programlisting>
+    </example>
+    <simpara>
+     Old code that has no user-defined classes or functions named 'interface'
+     or 'implements' should run without modifications. 
+    </simpara>
+   </section>
+
+   <section id='migration.oop.typehints'>
+    <title>Class Type Hints</title>
+    <para>
+     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.
+    </para>
+    <example>
+     <title>Class type hinting example</title>
+     <programlisting role="php">
+<![CDATA[
+<?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);
+?>
+]]>
+      </programlisting>
+    </example>
+    <simpara>
+     These class type hints are not checked upon compilation, as would be the
+     case in a typed language, but during runtime. This means that: 
+    </simpara>
+    <informalexample>
+     <programlisting role="php">
+<![CDATA[
+<?php
+function foo(ClassName $object) {
+    // ...
+}
+?>
+]]>
+      </programlisting>
+    </informalexample>
+    <simpara>is equivalent to:</simpara>
+    <informalexample>
+      <programlisting role="php">
+<![CDATA[
+<?php
+function foo($object) {
+    if (!($object instanceof ClassName)) {
+        die("Argument 1 must be an instance of ClassName");
+    }
+}
+?>
+]]>
+      </programlisting>
+    </informalexample>
+   </section>
+
+   <section id='migration5.oop.final'>
+    <title>final</title>
+    <para>
+     &php; 5 introduces the "final" keyword to declare final members and
+     methods. Methods and members declared final cannot be overridden by
+     sub-classes.
+    </para>
+    <example>
+     <title>final method</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Foo {
+    final function bar() {
+        // ...
+    }
+}
+?>
+]]>
+     </programlisting>
+    </example>
+    <para>
+     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.
+    </para>
+    <example>
+     <title>final class</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+final class Foo {
+    // class definition
+}
+
+// the next line is impossible
+// class Bork extends Foo {}
+?>
+]]>
+     </programlisting>
+    </example>
+    <para>
+     Properties can not be final.
+    </para>
+    <para>
+     Old code that has no user-defined classes or functions named 'final'
+     should run without modifications.
+    </para>
+   </section>
+
+   <section id='migration5.oop.cloning'>
+    <title>Objects Cloning</title>
+    <para>
+     &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.
+    </para>
+    <para>
+     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.
+    </para>
+    <para>
+     An object copy is created by using the clone keyword (which calls the
+     object's <function>__clone</function> method if possible). An object's 
+     <function>__clone</function>  method cannot be called directly. 
+    </para>
+    <para>
+     When the developer asks to create a new copy of an object, &php; 5 will
+     check if a <function>__clone</function> 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 <function>__clone</function> 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.
+    </para>
+    <example>
+     <title>Objects cloning</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class MyCloneable {
+    static $id = 0;
+
+    function MyCloneable() {
+        $this->id = self::$id++;
+    }
+
+    function __clone() {
+        $this->address = "New York";
+        $this->id = self::$id++;
+    }
+}
+
+$obj = new MyCloneable();
+
+$obj->name = "Hello";
+$obj->address = "Tel-Aviv";
+
+print $obj->id . "\n";
+
+$obj_cloned = clone $obj;
+
+print $obj_cloned->id . "\n";
+print $obj_cloned->name . "\n";
+print $obj_cloned->address . "\n";
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+
+   <section id='migration5.oop.constructors'>
+    <title>Constructors</title>
+    <para>
+     &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.
+    </para>
+    <para>
+     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.
+    </para>
+    <para>
+     &php; 5 introduces a standard way of declaring constructor methods by
+     calling them by the name <function>__construct</function>.
+    </para>
+    <example>
+     <title>using new unified constructors</title>
+     <programlisting role="php">
+<![CDATA[
+<?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();
+?> 
+]]>
+     </programlisting>
+    </example>
+    <para>
+     For backwards compatibility, if &php; 5 cannot find a 
+     <function>__construct</function> 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 
+     <function>__construct</function> which was used for different semantics.
+    </para>
+   </section>
+
+   <section id='migration5.oop.destructors'>
+    <title>Destructors</title>
+    <para>
+     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.
+    </para>
+    <para>
+     &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 <function>__destruct</function>  that receives no parameters, is
+     called before the object is freed from memory.
+    </para>
+    <example>
+     <title>Destructor</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class MyDestructableClass {
+    function __construct() {
+        print "In constructor\n";
+        $this->name = "MyDestructableClass";
+    }
+
+    function __destruct() {
+        print "Destroying " . $this->name . "\n";
+    }
+}
+
+$obj = new MyDestructableClass();
+?> 
+]]>
+     </programlisting>
+    </example>
+    <para>
+     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 <function>parent::__destruct</function> in the destructor
+     body.
+    </para>
+   </section>
+
+   <section id='migration5.oop.constants'>
+    <title>Constants</title>
+    <para>
+     &php; 5 introduces per-class constants:
+    </para>
+    <example>
+     <title>Class constant example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Foo {
+    const constant = "constant";
+}
+
+echo "Foo::constant = " . Foo::constant . "\n";
+?> 
+]]>
+     </programlisting>
+    </example>
+    <simpara>
+     Old code that has no user-defined classes or functions named 'const'
+     will run without modifications.
+    </simpara>
+   </section>
+   
+   <section id='migration5.oop.exceptions'>
+    <title>Exceptions</title>
+    <para>
+     &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" but not for the "finally" clause.
+    </para>
+    <para>
+     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.
+    </para>
+    <example>
+     <title>Exception creation example</title>
+     <programlisting role="php">
+<![CDATA[
+<?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;
+}
+?>
+]]>
+     </programlisting>
+    </example>
+    <para>
+     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.
+    </para>
+    <example>
+     <title>Base exceptions class</title>
+     <programlisting role="php">
+<![CDATA[
+<?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
+    }
+}
+?>
+]]>
+     </programlisting>
+    </example>
+    <simpara>
+     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.
+    </simpara> 
+    <simpara>
+     Old code that has no user-defined classes or functions 'catch', 'throw'
+     and 'try' will run without modifications.
+    </simpara>
+   </section>
+    
+   <section id='migration5.oop.dereferencing'>
+    <title>Dereferencing objects returned from functions</title>
+    <para>
+     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:
+    </para> 
+    <example>
+     <title>Dereferencing example</title>
+     <programlisting role="php">
+<![CDATA[
+<?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();
+?> 
+]]>
+     </programlisting>
+    </example>
+   </section>
+
+   <section id='migration5.oop.staticinit'>
+    <title>Static member variables initialization</title>
+    <para>
+     Static member variables of static classes can now be initialized.
+    </para>
+    <example>
+     <title>Static variable initialization example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class foo {
+    static $my_static = 5;
+    public $my_prop = 'bla';
+}
+
+print foo::$my_static;
+$obj = new foo;
+print $obj->my_prop;
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+
+   <section id='migration5.oop.staticmethods'>
+    <title>Static Methods</title>
+    <para>
+     &php; 5 introduces the 'static' keyword to declare a method static, thus
+     callable from outside the object context.
+    </para>
+    <example>
+     <title> Static Methods example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Foo {
+    public static function aStaticMethod() {
+        // ...
+    }
+}
+
+Foo::aStaticMethod();
+?>
+]]>
+     </programlisting>
+    </example>
+    <para>
+     The pseudo variable $this is not available inside a method that has been
+     declared static.
+    </para>
+   </section>
+
+   <section id='migration5.oop.instanceof'>
+    <title>instanceof</title>
+    <para>
+     &php; 5 introduces the <literal>instanceof</literal> 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.
+    </para>
+    <example>
+     <title><literal>instanceof</literal> example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class baseClass { }
+
+$a = new baseClass;
+
+if ($a instanceof baseClass) {
+    echo "Hello World";
+}
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+   
+   <section id='migration5.oop.staticvars'>
+    <title>Static function variables</title>
+    <para>
+     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.
+    </para>
+   </section>
+
+   <section id='migration5.oop.refparams'>
+    <title>Parameters passed by reference</title>
+    <para>
+     Parameters that are passed by reference to a function may now have
+     default values
+    </para>
+    <example>
+     <title />
+     <programlisting role="php">
+<![CDATA[
+<?php
+function my_function(&$var = null) {
+    if ($var === null) {
+        die("$var needs to have a value");
+    }
+}
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+
+   <section id='migration5.oop.autoload'>
+    <title><function>__autoload</function></title>
+    <para>
+     The <function>__autoload</function> interceptor function will be 
+     automatically called when an undeclared class is to be instantiated. 
+     The name of that class will be passed to the <function>__autoload</function>
+     interceptor function as its only argument.
+    </para>
+    <example>
+     <title><function>__autoload</function> example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+function __autoload($className) {
+    include_once $className . ".php";
+}
+
+$object = new ClassName;
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+    
+    <section id='migration5.oop.overload'>
+     <title>Overloadable Method calls and Property accesses</title>
+     <para>
+      Both method calls and property accesses can be overloaded via the
+      <function>__call</function>, <function>__get</function> and
+      <function>__set</function> methods. 
+     </para>
+     <example>
+      <title>
+       <function>__get</function> and
+       <function>__set</function>
+      </title>
+      <programlisting role="php">
+<![CDATA[
+<?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);
+?>
+]]>
+     </programlisting>
+    </example>
+    <example>
+     <title><function>__get</function> example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Caller {
+    private $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);
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>   
+
+   <section id='migration5.oop.iteration'>
+    <title>Iteration</title>
+    <para>
+     Objects may be iterated in an overloaded way when used with foreach. The
+     default behavior is to iterate over all properties.
+    </para>
+    <example>
+     <title>Object iteration example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Foo {
+    public $x = 1;
+    public $y = 2;
+}
+
+$obj = new Foo;
+
+foreach ($obj as $prp_name => $prop_value) {
+    // using the property
+}
+?> 
+]]>
+     </programlisting>
+    </example>
+    <para>
+     Each class whose instances can be iterated with foreach should implement
+     the empty interface <literal>Traversable</literal>. Hence any object that
+     says it implements <literal>Traversable</literal> can be used with foreach. 
+    </para>
+    <para>
+     The interfaces <literal>IteratorAggregate</literal> and 
<literal>Iterator</literal>
+     allows you to specify how class objects are iterated in &php; code. The first
+     of them simply has a method <function>getIterator</function> which must
+     return an array or an object that either implements the interface 
+     <literal>Iterator</literal>  or is instantiated from an internal
+     class that can be iterated
+    </para>
+    <example>
+     <title>Iterator creation example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class ObjectIterator implements Iterator {
+
+    private $obj;
+    private $num;
+
+    function __construct($obj) {
+        $this->obj = $obj;
+    }
+    function rewind() {
+        $this->num = 0;
+    }
+    function valid() {
+        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);
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+    
+   <section id='migrating5.oop.methodconst'>
+    <title><literal>__METHOD__</literal> constant</title>
+    <para>
+     The new <literal>__METHOD__</literal> pseudo constant shows the current
+     class and method when used inside a method and the function when used outside
+     of a class.
+    </para>
+    <example>
+     <title><literal>__METHOD__</literal> use example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Foo {
+    function show() {
+        echo __METHOD__;
+    }
+}
+
+class Bar extends Foo {
+}
+
+Foo::show(); // outputs Foo::show
+Bar::show(); // outputs Foo::show either since __METHOD__ is
+             // compile-time evaluated token
+
+function test() {
+    echo __METHOD__;
+}
+
+test();      // outputs test
+?>
+]]>
+     </programlisting>
+    </example>
+   </section>
+  
+   <section id='migrating5.oop.tostring'>
+    <title><function>__toString</function> method</title>
+    <para>
+     The new <function>__toString</function> magic method allows you to
+     overload the object to string conversion.
+    </para>
+    <example>
+     <title><function>__toString</function> example</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+class Foo {
+    function __toString() {
+        return "What ever";
+    }
+}
+
+$obj = new Foo;
+
+echo $obj; // call __toString()
+?> 
+]]>
+     </programlisting>
+    </example>
+   </section>
+
+   <section id='migrating5.oop.reflection'>
+    <title>Reflection API</title>
+    <para>
+     &php; 5 comes with a complete reflection API that adds the ability to
+     reverse-engineer classes, interfaces, functions and methods as well as
+     extensions.
+    </para>
+    <para>
+     The reflection API also offers ways of getting doc comments for
+     functions, classes and methods. 
+    </para>
+    <para>
+     Nearly all aspects of object oriented code can be reflected by using the
+     reflection API which is 
+     <ulink 
url="http://sitten-polizei.de/php/reflection_api/docs/language.reflection.html";>
+     documented separately</ulink>.
+    </para>
+    <example>
+     <title>Reflection API use example</title>
+     <programlisting role="php">
+<![CDATA[
+<?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');
+?> 
+]]>
+     </programlisting>
+    </example>
+   </section>
+
   </section>
+
  </appendix>
 
 

Reply via email to