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 retreive 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