xref: /PHP-7.1/Zend/ZEND_CHANGES (revision 4b953534)
1Changes in the Zend Engine 2.0
2
3    * New Object Model.
4
5      The Zend Engine's handling of objects has been completely
6      changed in order to allow for new features, but also to increase
7      its performance.
8
9      Objects were handled in previous versions like primitive types
10      (for instance integers and strings). The drawback of this method
11      is, that semantically the whole object was copied when a
12      variable was assigned or parameters were passed to a method. The
13      new approach refers to objects by handle and not by value (one
14      can think of a handle as an object's ID).
15
16      Many PHP programmers aren't even aware of the copying quirks of
17      the old object model and, therefore, there is a relatively good
18      chance that the amount of PHP applications that will work out of
19      the box or after a very small amount of modifications would be
20      high.
21
22    * $this
23
24      Unlike in Zend Engine 1 the pseudo variable $this cannot be
25      exchanged in Zend Engine 2. You can of course modify or work with
26      an object by using $this but you cannot replace $this with another
27      object to change the original object.
28
29      Example:
30
31        <?php
32        class Foo {
33            function replace($other)
34            {
35                $this = $other;
36            }
37        }
38
39        $object = new Foo;
40        $object->prop = 'Hello';
41
42        $other  = new Foo;
43        $other->prop = 'Bye';
44
45        $object->replace($other);
46
47        print $object->prop; // still shows 'Hello'
48
49        ?>
50
51        Zend Engine 2.0 will issue a compile error, if an assignment
52        to $this is found.
53
54    * Private and Protected Members.
55
56      The Zend Engine 2.0 introduces private and protected member
57      variables. Note that for performance reasons no error message is
58      emitted in case of an illegal access to a private or protectecd
59      member variable.
60
61      Example:
62
63        <?php
64        class MyClass {
65            private $Hello = "Hello, World!\n";
66            protected $Bar = "Hello, Foo!\n";
67            protected $Foo = "Hello, Bar!\n";
68
69            function printHello() {
70                print "MyClass::printHello() " . $this->Hello;
71                print "MyClass::printHello() " . $this->Bar;
72                print "MyClass::printHello() " . $this->Foo;
73            }
74        }
75
76        class MyClass2 extends MyClass {
77            protected $Foo;
78
79            function printHello() {
80                MyClass::printHello();                          /* Should print */
81                print "MyClass2::printHello() " . $this->Hello; /* Shouldn't print out anything */
82                print "MyClass2::printHello() " . $this->Bar;   /* Shouldn't print (not declared)*/
83                print "MyClass2::printHello() " . $this->Foo;   /* Should print */
84            }
85        }
86
87        $obj = new MyClass();
88        print $obj->Hello;  /* Shouldn't print out anything */
89        print $obj->Bar;    /* Shouldn't print out anything */
90        print $obj->Foo;    /* Shouldn't print out anything */
91        $obj->printHello(); /* Should print */
92
93        $obj = new MyClass2();
94        print $obj->Hello;  /* Shouldn't print out anything */
95        print $obj->Bar;    /* Shouldn't print out anything */
96        print $obj->Foo;    /* Shouldn't print out anything */
97        $obj->printHello();
98        ?>
99
100      Protected member variables can be accessed in classes extending the
101      class they are declared in, whereas private member variables can
102      only be accessed by the class they belong to.
103
104    * Private and protected methods.
105
106      The Zend Engine 2.0 introduces private and protected methods.
107
108      Example:
109
110        <?php
111        class Foo {
112          private function aPrivateMethod() {
113            echo "Foo::aPrivateMethod() called.\n";
114          }
115
116          protected function aProtectedMethod() {
117            echo "Foo::aProtectedMethod() called.\n";
118            $this->aPrivateMethod();
119          }
120        }
121
122        class Bar extends Foo {
123          public function aPublicMethod() {
124            echo "Bar::aPublicMethod() called.\n";
125            $this->aProtectedMethod();
126          }
127        }
128
129        $o = new Bar;
130        $o->aPublicMethod();
131        ?>
132
133      Old code that has no user-defined classes or functions named
134      'public', 'protected' or 'private' should run without modifications.
135
136    * Abstract Classes and Methods.
137
138      The Zend Engine 2.0 introduces abstract classes and methods. An
139      abstract method only declares the method's signature and does not
140      provide an implementation. A class that contains abstract methods
141      needs to be declared abstract.
142
143      Example:
144
145        <?php
146        abstract class AbstractClass {
147          abstract public function test();
148        }
149
150        class ImplementedClass extends AbstractClass {
151          public function test() {
152            echo "ImplementedClass::test() called.\n";
153          }
154        }
155
156        $o = new ImplementedClass;
157        $o->test();
158        ?>
159
160      Classes that do not have abstract methods can be declared abstract
161      to prevent them from being instantiated.
162
163      Old code that has no user-defined classes or functions named
164      'abstract' should run without modifications.
165
166    * Interfaces.
167
168      The Zend Engine 2.0 introduces interfaces. A class may implement
169      an arbitrary list of interfaces.
170
171      Example:
172
173        <?php
174        interface Printable {
175          public function dump();
176        }
177
178        class PrintableExample implements Printable {
179          public function dump() {
180            // ...
181          }
182        }
183        ?>
184
185      Old code that has no user-defined classes or functions named
186      'interface' or 'implements' should run without modifications.
187
188      An interface may extend one or more base interfaces (but not
189      implement them). Neither a class nor an interface can inherit
190      methods of the same name from different root interfaces.
191
192      Interfaces may contain abstract static methods.
193
194      Example:
195
196        <?php
197        interface Printable {
198          function dump();
199        }
200
201        interface Streamable extends Printable {
202          function writeToStream();
203          static function readFromStream();
204        }
205
206        class PrintableExample implements Streamable {
207          public function dump() {
208            // ...
209          }
210          function writeToStream() {
211            // ...
212          }
213          static function readFromStream() {
214            // ...
215          }
216        }
217        ?>
218
219      A class that does not implement all interface methods must be
220      declared as an abstract class.
221
222    * Class Type Hints.
223
224      While remaining loosely typed the Zend Engine 2.0 introduces the
225      ability to use class type hints to declare the expected class of
226      objects that are passed as parameters to a method.
227
228      Example:
229
230        <?php
231        interface Foo {
232          function a(Foo $foo);
233        }
234
235        interface Bar {
236          function b(Bar $bar);
237        }
238
239        class FooBar implements Foo, Bar {
240          function a(Foo $foo) {
241            // ...
242          }
243
244          function b(Bar $bar) {
245            // ...
246          }
247        }
248
249        $a = new FooBar;
250        $b = new FooBar;
251
252        $a->a($b);
253        $a->b($b);
254        ?>
255
256      These class type hints are not checked upon compilation, as would
257      be the case in a typed language, but during runtime.
258
259      This means that
260
261        function foo(ClassName $object) {
262          // ...
263        }
264
265      is equivalent to
266
267        function foo($object) {
268          if (!($object instanceof ClassName)) {
269            die('Argument 1 must be an instance of ClassName');
270          }
271        }
272
273      This syntax only applies to objects/classes, not built-in types.
274
275    * Final methods and classes.
276
277      The Zend Engine 2.0 introduces the "final" keyword to declare
278      final methods. Those cannot be overridden by sub-classes.
279
280      Example:
281
282        <?php
283        class Foo {
284          final function bar() {
285            // ...
286          }
287        }
288        ?>
289
290      It is furthermore possible to make a class final. Doing this
291      prevents a class from being specialized (it cannot be inherited
292      by another class). There's no need to declare the methods of
293      a final class themselves as final.
294
295      Example:
296
297        <?php
298         final class Foo {
299          // class definition
300        }
301        // the next line is impossible
302        // class Bork extends Foo {}
303        ?>
304
305      Properties cannot be final. See per-class constants below.
306
307      Old code that has no user-defined classes or functions named
308      'final' should run without modifications.
309
310    * Object Cloning.
311
312      The Zend Engine 1.0 offered no way a user could decide what copy
313      constructor to run when an object is duplicated. During
314      duplication, the Zend Engine 1.0 did a bitwise copy making an
315      identical replica of all the object's properties.
316
317      Creating a copy of an object with fully replicated properties is
318      not always the wanted behavior. A good example of the need for
319      copy constructors, is if you have an object which represents a
320      GTK window and the object holds the resource of this GTK window,
321      when you create a duplicate you might want to create a new
322      window with the same properties and have the new object hold the
323      resource of the new window. Another example is if your object
324      holds a reference to another object which it uses and when you
325      replicate the parent object you want to create a new instance of
326      this other object so that the replica has its own separate copy.
327
328      An object copy is created by using the clone operator.
329
330      Example:
331
332        <?php
333        $copy_of_object = clone $object;
334        ?>
335
336      When the developer asks to create a new copy of an object, the
337      Zend Engine will check if a __clone() method has been defined or
338      not. If not, it will call a default __clone() which will copy
339      all of the object's properties. If a __clone() method is
340      defined, then it will be responsible to set the necessary
341      properties in the created object. For convenience, the engine
342      ensures, that the clone will be initialized with all of the
343      properties from the source object, so that developers can start
344      with a by-value replica of the source object, and only override
345      properties that need to be changed.
346
347      Example:
348        <?php
349        class MyCloneable {
350          static $id = 0;
351
352          function MyCloneable() {
353            $this->id = self::$id++;
354          }
355
356          function __clone() {
357            $this->address = 'New York';
358            $this->id = self::$id++;
359          }
360        }
361
362        $obj = new MyCloneable();
363
364        $obj->name = 'Hello';
365        $obj->address = 'Tel-Aviv';
366
367        $obj_clone = clone $obj;
368
369        print $obj->id . "\n";
370        print $obj->name . "\n";
371        print $obj->address . "\n";
372
373        print $obj_clone->id . "\n";
374        print $obj_clone->name . "\n";
375        print $obj_clone->address . "\n";
376        ?>
377
378    * Unified Constructors.
379
380      The Zend Engine allows developers to declare constructor methods
381      for classes. Classes which have a constructor method call this
382      method on each newly-created object, so it is suitable for any
383      initialization that the object may need before it can be used.
384
385      With the Zend Engine 1.0, constructor methods were class methods
386      that had the same name as the class itself. Since it is very
387      common to call parent constructors from derived classes, the way
388      the Zend Engine 1.0 worked made it a bit cumbersome to move
389      classes around in a large class hierarchy. If a class is moved
390      to reside under a different parent, the constructor name of that
391      parent changes as well, and the code in the derived class that
392      calls the parent constructor has to be modified.
393
394      The Zend Engine 2.0 introduces a standard way of declaring
395      constructor methods by calling them by the name __construct().
396
397      Example:
398
399        <?php
400        class BaseClass {
401            function __construct() {
402                print "In BaseClass constructor\n";
403            }
404        }
405
406        class SubClass extends BaseClass {
407            function __construct() {
408                parent::__construct();
409                print "In SubClass constructor\n";
410            }
411        }
412
413        $obj = new BaseClass();
414        $obj = new SubClass();
415        ?>
416
417      For backwards compatibility, if the Zend Engine 2.0 cannot find
418      a __construct() function for a given class, it will search for
419      the old-style constructor function, by the name of the class.
420      Effectively, it means that the only case that would have
421      compatibility issues is if the class had a method named
422      __construct() which was used for different semantics.
423
424    * Destructors.
425
426      Having the ability to define destructors for objects can be very
427      useful. Destructors can log messages for debugging, close
428      database connections and do other clean-up work.
429
430      No mechanism for object destructors existed in the Zend Engine
431      1.0, although PHP had already support for registering functions
432      which should be run on request shutdown.
433
434      The Zend Engine 2.0 introduces a destructor concept similar to
435      that of other object-oriented languages, such as Java: When the
436      last reference to an object is destroyed the object's
437      destructor, which is a class method name __destruct() that
438      receives no parameters, is called before the object is freed
439      from memory.
440
441      Example:
442
443        <?php
444        class MyDestructableClass {
445            function __construct() {
446                print "In constructor\n";
447                $this->name = 'MyDestructableClass';
448            }
449
450            function __destruct() {
451                print 'Destroying ' . $this->name . "\n";
452            }
453        }
454
455        $obj = new MyDestructableClass();
456        ?>
457
458      Like constructors, parent destructors will not be called
459      implicitly by the engine. In order to run a parent destructor,
460      one would have to explicitly call parent::__destruct() in the
461      destructor body.
462
463    * Constants.
464
465      The Zend Engine 2.0 introduces per-class constants.
466
467      Example:
468
469        <?php
470        class Foo {
471            const constant = 'constant';
472        }
473
474        echo 'Foo::constant = ' . Foo::constant . "\n";
475        ?>
476
477      Old code that has no user-defined classes or functions
478      named 'const' will run without modifications.
479
480    * Exceptions.
481
482      The Zend Engine 1.0 had no exception handling. The Zend Engine 2.0
483      introduces a exception model similar to that of other programming
484      languages. But there is no catch all and no finally clause.
485
486      Old code that has no user-defined classes or functions 'catch',
487      'throw' and 'try' will run without modifications.
488
489      Exceptions can be rethrown in catch blocks. Also it is possible to
490      have multiple catch blocks. In that case the caught exception is
491      compared with the classtype of each catch block from top to bottom
492      and the first block that has a 'instanceof' match gets executed.
493      When the catch block finishes execution continues at the end of
494      the last catch block. If no catch block has a 'instanceof' match
495      then the next try/catch block is searched until no more try/catch
496      blocks are available. In that case the exception is an uncaught
497      exception and the program terminates with showing the exception.
498
499      Example:
500
501        <?php
502        class MyException {
503            function __construct($exception) {
504                $this->exception = $exception;
505            }
506
507            function Display() {
508                print "MyException: $this->exception\n";
509            }
510        }
511
512        class MyExceptionFoo extends MyException {
513            function __construct($exception) {
514                $this->exception = $exception;
515            }
516
517            function Display() {
518                print "MyException: $this->exception\n";
519            }
520        }
521
522        try {
523            throw new MyExceptionFoo('Hello');
524        }
525        catch (MyException $exception) {
526            $exception->Display();
527        }
528        catch (Exception $exception) {
529            echo $exception;
530        }
531        ?>
532
533      Even though the above example shows that it is possible to define
534      exception classes  that don't inherit from Exception it is best to
535      do so. This is because the internal Exception class can gather a
536      lot of information otherwise not available. The PHP code emulation
537      code would look something like shown below. The comments show the
538      meaning of each property. As the code shows it is possible to read
539      any available information by using the getter methods. But since
540      some of the methods are used internally they are marked final. All
541      in all the class is very restrictive because it must be ensured
542      that anything used internally always  works as expected.
543
544      Emulating class Exception:
545
546        <?php
547        class Exception {
548          function __construct(/*string*/ $message=NULL, /*int*/ $code=0) {
549            if (func_num_args()) {
550              $this->message = $message;
551            }
552            $this->code = $code;
553            $this->file = __FILE__; // of throw clause
554            $this->line = __LINE__; // of throw clause
555            $this->trace = debug_backtrace();
556            $this->string = StringFormat($this);
557          }
558
559          protected $message = 'Unknown exception';  // exception message
560          protected $code = 0; // user defined exception code
561          protected $file;     // source filename of exception
562          protected $line;     // source line of exception
563
564          private $trace;      // backtrace of exception
565          private $string;     // internal only!!
566
567          final function getMessage() {
568            return $this->message;
569          }
570          final function getCode() {
571            return $this->code;
572          }
573          final function getFile() {
574            return $this->file;
575          }
576          final function getTrace() {
577            return $this->trace;
578          }
579          final function getTraceAsString() {
580            return self::TraceFormat($this);
581          }
582          function _toString() {
583            return $this->string;
584          }
585          static private function StringFormat(Exception $exception) {
586            // ... a function not available in PHP scripts
587            // that returns all relevant information as a string
588          }
589          static private function TraceFormat(Exception $exception) {
590            // ... a function not available in PHP scripts
591            // that returns the backtrace as a string
592          }
593        }
594        ?>
595
596      If you derive your exception classes from this Exception base class
597      your exceptions will be nicely shown in the builtin handler for
598      uncaught exceptions.
599
600      Note: The method getMessage() is a final read only access method to
601      the private proeprty message that is set in the constructor. If you
602      feel a need to overwrite the exception display then overload method
603      __toString() in your derived class or implement your own extneral
604      exception display function to accomplish your desired formatting.
605
606      Example:
607
608      <?php
609      function display_exception(Exception $ex)
610      {
611          echo 'Exception: ' . $ex->getMessage() . 'with backtrace: <pre>';
612          echo $ex->getTrace();
613          echo '</pre>';
614      }
615
616      try
617      {
618          // your code here
619      }
620      catch (Exception $ex)
621      {
622          display_exeption($ex);
623      }
624      ?>
625
626    * Dereferencing objects returned from functions.
627
628      Example:
629
630        <?php
631        class Circle {
632            function draw() {
633                print "Circle\n";
634            }
635        }
636
637        class Square {
638            function draw() {
639                print "Square\n";
640            }
641        }
642
643        function ShapeFactoryMethod($shape) {
644            switch ($shape) {
645                case 'Circle': return new Circle();
646                case 'Square': return new Square();
647            }
648        }
649
650        ShapeFactoryMethod('Circle')->draw();
651        ShapeFactoryMethod('Square')->draw();
652        ?>
653
654    * Member variables of classes can now be initialized.
655
656      Example:
657
658        <?php
659        class foo {
660            static $my_static = 5;
661            public $my_prop = 'bla';
662        }
663
664        print foo::$my_static;
665
666        $obj = foo;
667
668        print $obj->my_prop;
669        ?>
670
671    * Static Methods.
672
673      The Zend Engine 2.0 introduces the 'static' keyword to declare
674      a method static, thus callable from outside the object context.
675
676      Example:
677
678        <?php
679        class Foo {
680          public static function aStaticMethod() {
681            // ...
682          }
683        }
684
685        Foo::aStaticMethod();
686        ?>
687
688      The pseudo variable $this is not available inside a method that
689      has been declared static.
690
691    * instanceof.
692      New support for an instanceof operator which checks if an object
693      is of a certain class or interface type.
694
695      Example:
696
697      <?php
698
699      class Foo {
700      }
701
702      $obj = new Foo();
703      if ($obj instanceof Foo) {
704        print "Yay!\n";
705      }
706      ?>
707
708    * Parameters that are passed by reference to a function
709      may now have default values.
710
711      Example:
712
713        <?php
714        function my_function(&$var = null) {
715             if ($var === null) {
716                 die('$var needs to have a value');
717             }
718        }
719        ?>
720
721    * __autoload().
722
723      The __autoload() interceptor function will be automatically called
724      when an undeclared class is to be instantiated. The name of that
725      class will be passed to the __autoload() interceptor function as its
726      only argument. __autoload() must succeed in loading the class. If it
727      doesn't then an E_ERROR is emitted.
728
729      Example:
730
731        <?php
732        function __autoload($className) {
733          include_once $className . '.php';
734        }
735
736        $object = new ClassName;
737        ?>
738
739    * Method calls and property accesses can be overloaded
740      by class methods  __call(), __get() and __set().
741
742      __get() and __set() Example:
743
744        <?php
745            class Setter {
746                public $n;
747                public $x = array('a' => 1, 'b' => 2, 'c' => 3);
748
749                function __get($nm) {
750                    print "Getting [$nm]\n";
751
752                    if(isset($this->x[$nm])) {
753                        $r = $this->x[$nm];
754                        print "Returning: $r\n";
755                        return $r;
756                    } else {
757                        print "Nothing!\n";
758                    }
759                }
760
761                function __set($nm, $val) {
762                    print "Setting [$nm] to $val\n";
763
764                    if(isset($this->x[$nm])) {
765                        $this->x[$nm] = $val;
766                        print "OK!\n";
767                    } else {
768                        print "Not OK!\n";
769                    }
770                }
771            }
772
773            $foo = new Setter();
774            $foo->n = 1;
775            $foo->a = 100;
776            $foo->a++;
777            $foo->z++;
778            var_dump($foo);
779        ?>
780
781      __call() Example:
782
783        <?php
784            class Caller {
785                var $x = array(1, 2, 3);
786
787                function __call($m, $a) {
788                     print "Method $m called:\n";
789                     var_dump($a);
790                     return $this->x;
791                }
792            }
793
794            $foo = new Caller();
795            $a = $foo->test(1, '2', 3.4, true);
796            var_dump($a);
797        ?>
798
799    * Iteration
800
801      Objects may be iterated in an overloaded way when used with
802      foreach. The default behavior is to iterate over all properties
803      with respect to property visibility.
804
805      Example:
806
807        <?php
808            class Foo {
809                var $x = 1;
810                var $y = 2;
811            }
812
813            $obj = new Foo;
814
815            foreach ($obj as $prp_name => $prop_value) {
816                // using the property
817            }
818        ?>
819
820      Each class whose instances can be iterated with foreach should
821      implement the empty interface 'Traversable'. Hence any object
822      that says it implements 'Traversable' can be used with foreach.
823
824      The interfaces 'IteratorAggregate' and 'Iterator' allow to specify
825      how class objects are iterated in PHP code. The first of them simply
826      has a method 'getIterator' which must return an object that either
827      implements the interface 'Iterator' or is instantiated from an
828      internal class that can be iterated.
829
830      Example:
831
832        <?php
833            class ObjectIterator implements Iterator {
834
835                private $obj;
836                private $num;
837
838                function __construct($obj) {
839                    $this->obj = $obj;
840                }
841                function rewind() {
842                    $this->num = 0;
843                }
844                function valid() {
845                    return $this->num < $this->obj->max;
846                }
847                function key() {
848                    return $this->num;
849                }
850                function current() {
851                    switch($this->num) {
852                        case 0: return "1st";
853                        case 1: return "2nd";
854                        case 2: return "3rd";
855                        default: return $this->num."th";
856                    }
857                }
858                function next() {
859                    $this->num++;
860                }
861            }
862
863            class Object implements IteratorAggregate {
864
865                public $max = 3;
866
867                function getIterator() {
868                    return new ObjectIterator($this);
869                }
870            }
871
872            $obj = new Object;
873
874            // this foreach ...
875            foreach($obj as $key => $val) {
876                echo "$key = $val\n";
877            }
878
879            // matches the following 7 lines with the for directive.
880            $it = $obj->getIterator();
881            for($it->rewind(); $it->valid(); $it->next()) {
882                $key = $it->key();
883                $val = $it->current();
884                echo "$key = $val\n";
885            }
886            unset($it);
887        ?>
888
889      The matching for directive is very intersting here since it shows
890      the use of all abstract methods declared in the interfaces Iterator
891      and IteratorAggregate respectively.
892
893    * Array overloading
894
895      Objects can be used with Array notation when they implement the
896      interface ArrayAccess. You cannot use such objects in standard
897      array functions, however you have full control over the array
898      notation. This allows lazy initialization or read only array.
899
900      Note that setting [] results in a call to offsetSet() with
901      index being NULL. That means that as with standard arrays you
902      cannot store NULL keys.
903
904      Example:
905
906        <?php
907	        class ArrayClass implements ArrayAccess {
908				public $a = array();
909
910				function offsetExists($index) {
911					return array_key_exists($index, $this->a);
912				}
913				function offsetGet($index) {
914					return $this->a[$index];
915				}
916				function offsetSet($index, $newval) {
917					return $this->a[$index] = $newval;
918				}
919				function offsetUnset($index) {
920					unset($this->a[$index]);
921				}
922			}
923
924			$obj = new ArrayClass;
925
926			$obj[0] = 'bla';     // calls offsetSet(0,'bla')
927			$obj[] = 42;         // calls offsetSet(NULL, 42)
928			$x = $obj[0];        // calls offsetGet(0)
929			$b = isset($obj[0]); // calls offsetExists(0)
930			unset($obj[0]);      // calls offsetUnset(0)
931		?>
932
933
934    * __METHOD__
935
936      The pseudo constant __METHOD__ shows the current class and method
937      when used inside a method and the function when used outside of a
938      class.
939
940      Example:
941
942        <?php
943            class Foo {
944                function Show() {
945                    echo __FILE__ . '(' . __LINE__ . ')' . __METHOD__;
946                }
947            }
948            function Test() {
949                echo __FILE__ . '(' . __LINE__ . ')' . __METHOD__;
950            }
951        ?>
952
953    * __toString()
954
955      The magic method __toString() allows to overload the object to
956      string conversion. This conversion is only done automatically for
957      the printing functions (echo, print) but not for other functions
958      that expect strings. Also the function __toString is not used in
959      places where objects are not allowed but strings are like array
960      indices. Note that specialized objects may be converted to a string
961      in any place but without calling __toString().
962
963      Example:
964
965        <?php
966            class Foo {
967                function __toString() {
968                    return "What ever";
969                }
970            }
971
972            $obj = new Foo;
973
974            $str = (string) $obj; // call __toString()
975
976            echo $obj; // call __toString()
977
978            $ar = array();
979            $ar[(string)$obj]; // this works
980            $ar[$obj];         // this is not allowed
981        ?>
982
983    * Reflection API
984
985      PHP 5 comes with a complete Reflection API that adds the ability to
986      reverse-engineer classes, interfaces, functions and methods as well
987      as extensions.
988
989      The Reflection API also offers ways of getting doc comments for
990      functions, classes and methods.
991
992      Nearly all aspects of object oriented code can be reflected by
993      using the Reflection API which is documented separately:
994      http://sitten-polizei.de/php/reflection_api/docs/language.reflection.html
995
996      Example:
997
998        <?php
999            class Foo {
1000                public $prop;
1001                function Func($name) {
1002                    echo "Hello $name";
1003                }
1004            }
1005
1006            ReflectionClass::export('Foo');
1007            ReflectionObject::export(new Foo);
1008            ReflectionMethod::export('Foo', 'func');
1009            ReflectionProperty::export('Foo', 'prop');
1010            ReflectionExtension::export('standard');
1011        ?>
1012
1013    * New memory manager
1014      The Zend Engine has a new memory manager which allows it to run efficiently
1015      in multi-threaded environments as it doesn't need to use mutexes to lock
1016      and unlock during allocation/deallocation.
1017
1018    * Others
1019      Probably other changes which we forgot to list. This list will be kept up-to-date
1020      as much as possible.
1021
1022
1023Changes in the Zend Engine 1.0
1024
1025  The Zend Engine was designed from the ground up for increased speed,
1026  reduced memory consumption and more reliable execution. We dare say
1027  it meets all of these goals and does so pretty well. Beyond that,
1028  there are several improvements in the language engine features:
1029
1030    * References support.
1031
1032      $foo = &$a; would make $foo and $a be two names to the same
1033      variable. This works with arrays as well, on either side; e.g.,
1034      $foo = &$a[7]; would make $foo and $a[7] be two names to the
1035      same variable. Changing one would change the other and vice
1036      versa.
1037
1038    * Object overloading support.
1039
1040      This feature allows various OO libraries to use the OO notation
1041      of PHP to access their functionality. Right now, no use is made
1042      of that feature, but we'd have a COM module ready by the time
1043      PHP 4.0 is released. A CORBA module would probably follow.
1044
1045    * include() and eval() are now functions, and not statements.
1046
1047      That means they return a value. The default return value from
1048      include() and eval() is 1, so that you can do if (include())
1049      without further coding. The return value may be changed by
1050      returning a value from the global scope of the included file or
1051      the evaluated string. For example, if 'return 7;' is executed in
1052      the global scope of foo.inc, include('foo.inc') would evaluate
1053      to 7.
1054
1055    * Automatic resource deallocation.
1056
1057      Several people have been bitten by the fact that PHP 3.0 had no
1058      concept of reference counting. The Zend Engine adds full
1059      reference counting for every value in the system, including
1060      resources. As soon as a resource is no longer referenced from
1061      any variable, it is automatically destroyed to save memory and
1062      resources. The most obvious example for the advantage in this is
1063      a loop that has an SQL query inside it, something like '$result
1064      = sql_query(...);'. In PHP 3.0, every iteration resulted in
1065      another SQL result-set allocated in the memory, and all of the
1066      result sets weren't destroyed until the end of the script's
1067      execution. With the Zend Engine, as soon as we overwrite an old
1068      result set with a new one, the old result set which is no longer
1069      referenced, is destroyed.
1070
1071    * Full support for nesting arrays and objects within each other,
1072      in as many levels as you want.
1073
1074    * true and false are now constants of type boolean.
1075
1076      Comparing any other value to them would convert that value to a
1077      boolean first, and conduct the comparison later. That means, for
1078      example, that 5==true would evaluate to true (in PHP 3.0, true
1079      was nothing but a constant for the integer value of 1, so
1080      5==true was identical to 5==1, which was false).
1081
1082    * Runtime binding of function names.
1083
1084      This complex name has a simple explanation - you can now call
1085      functions before they're declared!
1086
1087    * Added here-docs support.
1088
1089    * Added foreach.
1090
1091      Two syntaxes supported:
1092
1093        foreach(array_expr as $val) statement
1094        foreach(array_expr as $key => $val) statement
1095
1096    * A true unset() implementation.
1097
1098      A variable or element that is unset(), is now sent to oblivion
1099      in its entirely, no trace remains from it.
1100
1101    * Output buffering support.
1102
1103      Use ob_start() to begin output buffering, ob_end_flush() to end
1104      buffering and send out the buffered contents, ob_end_clean() to
1105      end buffering without sending the buffered contents, and
1106      ob_get_contents() to retrieve the current contents of the output
1107      buffer. Header information (header(), content type, cookies) are
1108      not buffered. By turning on output buffering, you can
1109      effectively send header information all throughout your file,
1110      regardless of whether you've emitted body output or not.
1111
1112    * Full variable reference within quoted strings:
1113
1114        ${expr}    - full indirect reference support for scalar
1115                     variables
1116        {variable} - full variable support
1117
1118        For example:
1119
1120          $foo[5]['bar'] = 'foobar';
1121          print "{$foo[5]["bar"]}";  // would print "foobar"
1122
1123    * Ability to call member functions of other classes from within
1124      member functions or from the global scope.
1125
1126      You can now, for example, override a parent function with a
1127      child function, and call the parent function from it.
1128
1129    * Runtime information for classes (class name, parent, available
1130      functions, etc.).
1131
1132    * Much more efficient syntax highlighter - runs much quicker,
1133      performs more reliably, and generates much tighter HTML.
1134
1135    * A full-featured debugger has been integrated with the language
1136      (supports breakpoints, expression evaluation, step-in/over,
1137      function call backtrace, and more).
1138
1139  The Zend Engine claims 100% compatibility with the engine of PHP
1140  3.0, and is shamelessly lying about it. Here's why:
1141
1142    * Static variable initializers only accept scalar values
1143      (in PHP 3.0 they accepted any valid expression). The impact
1144      should be somewhere in between void and non existent, since
1145      initializing a static variable with anything but a simple
1146      static value makes no sense at all.
1147
1148    * The scope of break and continue is local to that of an
1149      include()'d file or an eval()'d string. The impact should
1150      be somewhat smaller of the one above.
1151
1152    * The return statement no longer works from a require()'d file. It
1153      hardly worked in PHP 3.0, so the impact should be fairly small. If
1154      you want this functionality - use include() instead.
1155
1156    * unset() is no longer a function, but a statement.
1157
1158    * The following letter combination is not supported within
1159      encapsulated strings:  "{$".  If you have a string that includes
1160      this letter combination, for example, print "{$somevar"; (which
1161      printed the letter { and the contents of the variable $somevar in
1162      PHP 3.0), it will result in a parse error with the Zend Engine.
1163      In this case, you would have to change the code to print
1164      "\{$somevar"; This incompatibility is due to the full variable
1165      reference within quoted strings feature added in the Zend
1166      Engine.
1167