1: Changes 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:
1023: Changes 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.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>