New object model
Notice: the abilities described are available in PHP5 only. Usage is admissible as testing only.
In order to introduce new abilities and increase working speed the objects’ management system in Zend Engine has been changed completely.
In the previous versions objects were managed like fundamental data types (i.e. like whole numbers or symbols’ strings). The drawback of this method is that the whole object was copied completely semantically by value appropriation to an object’s property or by transmitting arguments to its method. The new approach is included in communication with an object through handler not by value (i.e. handler may be presented just as an object’s identifier).
And as far as many PHP-programmers had no idea about copying peculiarities in the old object model there is a great chance for the possibility that applications themselves or after inconsiderable changes done will work much faster.
Secret terms
Secret properties are introduced in Zend Engine 2.0. It should be mentioned that by unapproved access to a secret attribute an error message won’t be displayed in order to evade slowing down of work.
Example 1: Secret terms
<?php
class MyClass {
private $Hello = "Hello, World!\n";
function printHello() {
print $this->Hello;
}
}
class MyClass2 extends MyClass {
function printHello() {
MyClass::printHello(); /* Output */
print $this->Hello; /* No output */
}
}
$obj = new MyClass();
print $obj->Hello; /* No output */
$obj->printHello(); /* Output */
$obj = new MyClass2();
print $obj->Hello; /* No output */
$obj->printHello();
?>
Objects’ cloning
By copying objects within Zend Engine 1.0 a user couldn’t decide what exactly the constructor had to copy and what not. Version 1.0 copied an object bit-by-bit and released the complete copy of all its properties by the output.
However absolute copying of an object with complete set of properties isn’t always the thing we need. A good example would be following – you have an object representing a GTK-window and information about all the interface’s elements of this window is also saved in the object. You may need to create a new window which is a copy of the first one and save the data about all the interface’s elements of the new window in the new object. Another variant is following: your object contains reference to another object which is used by the first one somehow. By cloning your parent object you create a copy of other object and thus the duplicate of your object has its own copy of those object used.
An object’s copy is created by method __clone() of this object.
When a developer calls cloning of some object Zend Engine checks if method __clone() has been defined. If it hasn’t __clone() is called on default and all the properties of an object are duplicated completely. If the method has been defined, it enumerates the properties of an object which will be transferred into its copy. For convenience of usage Zend Engine presents a function which imports all the properties of copied into the object: thus they will be in the copy on their meaning and a developer is left only rewrite those properties which he is going to change. [In the given version this function hasn’t been realized yet].
Example 2: Objects’ cloning
<?php
class MyCloneable {
static $id = 0;
function MyCloneable() {
$this->id = self::$id++;
}
function __clone() {
$this->name = $clone->name;
$this->address = 'New York';
$this->id = self::$id++;
}
}
$obj = new MyCloneable();
$obj->name = 'Hello';
$obj->address = 'Tel-Aviv';
print $obj->id . "\n";
$obj = $obj->__clone();
print $obj->id . "\n";
print $obj->name . "\n";
print $obj->address . "\n";
?>
Compulsory deletion of objects
Zend Engine 1.0 hasn’t contained any means for compulsory deletion of an object if some references to it existed. Operator delete represented in the new version calls destructor of an object and frees the memory occupied by an object even if there are references on it in the other places of the system. All the references on the object destroyed become out-of-date and all the attempts to become access through them result into a fatal error.
You should take into account that if there is a defined by a user function delete() in your script, such a script will display a parse error in Zend Engine 2.0 as far as ‘delete’ is reserved word from this moment.
Inserted classes (names’ spaces)
Zend 1.0 core provided only three scopes: global scope, class scope and function scope. All the scopes except for classes could contain variables; only class and global scope could contain functions; only global scope could contain constants and classes. This means that in all the versions of Zend Engine 1.0 methods of scope had been limited in order to evade conflicts within names’ space.
In Zend Engine 2.0 new conception of inserted classes is represented in order to solve the problem of name conflicts with alternative method: a possibility appears to define some names’ tables containing any symbols types. Zend Engine always watches in which class area accomplishment is placed setting up the global area on default. Each class may contain its own set of constants, functions and static variables. For access to identifiers within a class a class access operator self:: is used and thus the following string is possible: self::$my_static_name = "Hello". With functions and constants as well the search will be firstly led within the current class if you haven’t defined the class to which they belong and then (if the search has resulted into nothing) the global scope will be examined. If you need to lead search within the global scope only, you may set up this explicitly through the access operator main::. For example, using main::strlen() you may be sure that you call namely strlen() from the global scope. Thus you are to use main:: only in those cases when you create a method having the same name as a global function does. Syntax for access to the constants is the same: self::MY_CONSTANT or main::MY_CONSTANT.
Sometimes you may dislike getting access to constants, variables and classes through access operators (such as MyClass::): you have use them too often and your setting speed is insufficient. In such a case you may import functions, classes and constants from other classes through the key word ‘import’. The name speaks of itself; there are also some examples given below.
Classes may contain other classes
Example 3: Inserted classes
<?php
class DB::MySQL {
var $host = '';
function db_connect($user) {
print "Connecting to MySQL database '$this->host' as $user\n";
}
}
class DB::Oracle {
var $host = 'localhost';
function db_connect($user) {
print "Connecting to Oracle database '$this->host' as $user\n";
}
}
$MySQL_obj = new DB::MySQL();
$MySQL_obj->db_connect('Susan');
$Oracle_obj = new DB::Oracle();
$Oracle_obj->db_connect('Barbara');
?>
Classes may contain constants
Example 4: constants
<?php
class foo {
const hey = 'hello';
}
print foo::hey;
?>
Search for functions and constants is led firstly in the names’ table of the current class.
Example 5: class names’ table
<?php
define('foo','bar');
class FooClass {
const foo = 'foobar';
function printFoo() {
print foo;
}
}
?>
The code given below displays "foobar" instead of "foo" as far as constant of a class rewrites constant of global scope with the same name.
Within function scope table of class names/name’s space containing it is used.
Example 6: table of class names
<?php
class FooClass {
function foo() {
$this->bar();
bar();
}
function bar() {
print "foobar\n";
}
}
$obj = new FooClass;
$obj->foo();
$obj->foo();
?>
"foobar" is put out twice as far as method bar() already exists in the given names’ space.
There is a possibility to ‘import’ names from one space into another.
Example 7: import of names
<?php
class MyClass {
class MyClass2 {
function hello() {
print "Hello, World in MyClass2\n";
}
}
function hello() {
print "Hello, World\n";
}
}
import function hello, class MyClass2 from MyClass;
MyClass2::hello();
hello();
?>
Example 8: import of names
<?php
class MyOuterClass {
class MyInnerClass {
function func1() {
print "func1()\n";
}
function func2() {
print "func2()\n";
}
}
}
import class * from MyOuterClass;
import function func2 from MyOuterClass::MyInnerClass;
MyInnerClass::func1();
func2();
?>
Example 9: import of names
<?php
class MyOuterClass {
const Hello = "Hello, World\n";
}
import const Hello from MyOuterClass;
print Hello;
?>
Scripts written in the old versions and not using the peculiarities given will function without any changes.
Unified constructors
Zend Engine enables developers define for classes their own constructor methods. Classes with defined constructor call this method by creation of each new specimen i.e. the whole initialization necessary for usage of this object is done.
In Zend Engine 1.0 constructor methods represented class methods having the same names as the class did. Because of the widespread practice to call constructor of the parent class from derived classes such a peculiarity of Zend Engine 1.0 made transferring from one class (by complicated class hierarchy) to another one into complicated and slow work. And if some derived class is transferred to other parent, the name of parent class constructor will change and you’ll also have to change code for this constructor’s call from the class derived.
In Zend Engine 2.0 new unified method of construct method declaring is introduced: to call constructor with name__construct().
Example 10: Unified constructors
<?php
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}
$obj = new BaseClass();
$obj = new SubClass();
?>
For saving compatibility with the previous versions if Zend Engine 2.0 doesn’t find any method with name__construct() for the given class, search of a constructor declared according to the old rules will be done i.e. of that one which has the same name as class does. The problem of compatibility with scripts of the previous versions may appear in one case only: if your class contains method __construct() which is used for other purposes.
Unified destructors
Possibility to define destructors for objects can be rather useful. Destructors can add entries into log for program checkout, shut down connections with data bases and do other erasure works.
In Zend Engine 1.0 there were no means for destructors’ support although PHP has already supported functions of logging which were called by request stopping.
In Zend Engine 2.0 a destructor’s conception is introduced which is similar with destructors within objective oriented languages such as, for example, Java: when the last reference to an object is destroyed destructor is called before releasing of the memory occupied by it. The last one represents method of class with name __destruct() and taking no parameters.
Example 11: Unified destructors
<?php
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = 'MyDestructableClass';
}
function __destruct() {
print 'Destroying ' . $this->name . "\n";
}
}
$obj = new MyDestructableClass();
?>
Like constructors parent’s destructor isn’t called automatically. For this operation you need to call parent::__destruct() in the body of destructor evidently.
Exceptions
In Zend Engine 1.0 exceptions management wasn’t supported. In Zend Engine 2.0 an exceptions’ model is introduced which is similar with the models like this in other languages.
Example 12: Exceptions
<?php
class MyException {
function __construct($exception) {
$this->exception = $exception;
}
function Display() {
print "MyException: $this->exception\n";
}
}
class MyExceptionFoo extends MyException {
function __construct($exception) {
$this->exception = $exception;
}
function Display() {
print "MyException: $this->exception\n";
}
}
try {
throw new MyExceptionFoo('Hello');
}
catch (MyException $exception) {
$exception->Display();
}
?>
Scripts of the previous versions without defined by a user functions 'catch', 'throw', 'try' will work without any changes.
Dereferencing of objects got from functions
Example 13: Dereferencing of objects
<?php
class Circle {
function draw() {
print "Circle\n";
}
}
class Square {
function draw() {
print "Square\n";
}
}
function ShapeFactoryMethod($shape) {
switch ($shape) {
case 'Circle': return new Circle();
case 'Square': return new Square();
}
}
ShapeFactoryMethod('Circle')->draw();
ShapeFactoryMethod('Square')->draw();
?>
Initialization of static terms of the classes.
Example 14: Initialization of static terms
<?php
class foo {
static $my_static = 5;
}
print foo::$my_static;
?>
Parameters transmitted into function through reference can have values on default.
Example 15: Values on default
<?php
function my_function(&$var = null) {
if ($var === null) {
die('$var needs to have a value');
}
}
?>
Integrated backtrace
Example 16: Values. Backtrace.
<?php
$backtrace = debug_backtrace();
foreach ($backtrace as $step) {
$class = isset($step['class']) ? $step['class'] . '::' : '';
printf(
"%s [%s:%s]\n",
$step['function'],
$step['file'],
$step['line']
);
}
?>



