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
+ "public", "protected" or "private" 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>