File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / ZEND_CHANGES
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 08:02:46 2013 UTC (11 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29p0, v5_4_29, v5_4_20p0, v5_4_20, HEAD
v 5.4.20

    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>