• Index
  •  » Articles
  •  » Zend eliminates lack of objective oriented programming in PHP

Zend eliminates lack of objective oriented programming in PHP

Zend eliminates lack of objective oriented programming in PHP

Weak points of PHP as an objective oriented language were obvious to many professional programmers. Zend Technologies seemed to be worried about the same problem and so they released a new core version - Zend Engine 2.0. On the base of Zend Engine 2.0 new version PHP 4.3.0 will be released (it is already available on site PHP 4.3.0 in the following edition: php-4.3.0-dev-zend2-alpha2). The most changes have been done in the part of objective oriented programming and also the possibility for exceptions treatment in the style C++ was added.

New object model

Objects’ handling within Zend 2.0 Core has been changed completely for realization of new abilities. In the previous version objects were interpreted as fundamental types (such as integers and strings). The drawback of this method was copying of the whole object when defining a variable or transmitting parameters to the method. In the new realization reference to objects is done by descriptor not by value (descriptor may be presented as ID of an object). Perhaps it looks a bit like objects indicators mechanism in C++.

Secret terms

Core Zend 2.0 enables usage of secret terms of a class. Only internals may be declared as secret. In case of illegal access to a secret member there will be no error message generated. A class term is closed if it is declared with the key word ‘private’. Scope of a secret term includes only that class within which the term given is declared. For derived classes a secret term is not available. An object also has no access to a secret term. For example:

<?php
class MyClass {
    private 
$Hello "Hello, World!\n";
    function 
printHello() {
        print 
$this->Hello;
    }
}

class 
MyClass2 extends MyClass {
    function 
printHello() {
        
MyClass::printHello(); /* Will be printed */
        
print $this->Hello;    /* Won’t be printed */
    
}
}

$obj = new MyClass();
print 
$obj->Hello;  /* Won’t be printed */
$obj->printHello(); /* Will be printed */

$obj = new MyClass2();
print 
$obj->Hello;  /* Won’t be printed */
$obj->printHello();
?>

Objects’ cloning

In the core Zend 1.0 there was no ability for usage of a copying constructor which would be called by creation of an object’s duplicate. During duplication the core Zend 1.0 had been copying bit-by-bit creating an identical duplicate of all the object’s internals. Creation of an object’s copy with complete duplication of its internals doesn’t always correspond with what we expect. A good example of necessary copying constructor usage is following: if your object contains a reference to another object which is used by it, you are likely to create a new copy of the object to which a parent refers when copying the parent’s object. Copy of the object is created by calling the method __clone(). For example: $copy_of_object = $object->__clone(); When developer creates a new object’s copy (syntax described before is used) Zend core checks if method __clone() is declared in the class which specimen the object given is. If not method __clone() declared on default will be called which copies all the internals of the object. If method __clone() is declared, it will be responsible for installation of necessary internals by creation of an object. To make it convenient the core will support the function importing all the internals from the initial object. It can be needed to start copying from creation of a duplicate of the initial object and following redefinition of necessary internals only. This function hasn’t been realized yet. Within method __clone() initial object named $clone is available. Example:

<?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 1.0 core haven’t offered any possibility for deletion of an object if there were some references on it. Now you may use delete instruction which calls destructor and destroys an object even if a reference on it from other place in the core exists. Other references to the object destroyed become out-of-date and any attempt to access an object through them results into a fatal error. Attention! If you declared function delete() in your scripts, the Zend core analyzer will generate an error by their handling. Beginning with the given core version ‘delete’ is a reserved word.

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. Zend 2.0 core represents a notion of inserted classes for solving the problem of names’ intersection enabling declaration of some names’ tables which may contain all the types. Each class can contain its own set of constants, functions and static variables. For local class names access you may use self:: operator (for example, self::$my_static_name = "Hello"). You may also use a class name for getting access: MyClass::$my_static_name = "Hello". If you don’t indicate the class in the context of which constants and functions are used, firstly search in the current class will be done. If nothing is found, the search is continued in the global scope. If you want to make PHP check the global scope only, you may use main:: access operator. For example, using main::strlen() you may be sure that you call strlen() from the global scope. You should worry about that only if you declare methods with names which are already present in the global scope. Use may use analogical syntax for constants: self::MY_CONSTANT or main::MY_CONSTANT. Sometimes you wouldn’t like to have access to constants, functions and classes through the class access operator (i.e. MyClass::), for example, because of frequent usage of such construction. In this case you may import functions, classes and constants from classes using the key word import. All this is explained on the examples below. - Classes may contain other classes. Example:

<?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:

<?php
class foo {
    const 
hey 'hello';
}

print 
foo::hey;
?>

- Names’ table for the current names’ space is viewed first for constants and functions.

Example: the code given prints ‘foobar’ instead of ‘bar’ because the constant declared in the class recovers global constant with the same name.

<?php
define
('foo''bar');

class 
FooClass {
    const 
foo 'foobar';

    function 
printFoo() {
        print 
foo;
    }
}
?>

- Class is the current scope of a function. Example:

<?php
class FooClass {
    function 
foo() {
        
$this->bar();
        
bar();
    }

    function 
bar() {
        print 
"foobar\n";
    }
}

$obj = new FooClass;
$obj->foo();
?>

The given example prints "foobar" twice as far as method bar() exists within current names’ space. – The key word ‘import’ enables importing names from one names’ space into another. For example:

<?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:

<?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:

<?php
class MyOuterClass {
    const 
Hello "Hello, World\n";
}

import const Hello from MyOuterClass;
print 
Hello;
?>

Unification of constructors

Zend core enables declaring constructors for classes. Classes which possess constructors call it for each newly created object. Constructors are used for initialization of an object before its usage. Within core Zend 1.0 the role of constructor was performed by the method having the same name as a class. Call of the base class constructor from the derived class could cause many problems by changing the hierarchy of classes. If base class was changed for some class, we had to change the name of a parent constructor called as well. Core Zend 2.0 represents a common name for constructors: __construct(). For example:

<?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 backward compatibility following ability is realized: if core Zend 2.0 doesn’t find function __construct(), it tries to find a constructor written in the old style. The only case in which problem with compatibility can appear is presence of method __construct() which is used in another context in your old class.

Destructors

It’s rather useful to have an ability to declare destructors for objects. Destructors can show up checkout messages, close connections with data base and do other kinds of works before object’s destruction. There was no destructors’ mechanism within core Zend 1.0 although PHP enabled registering functions which were called when finishing the work. Core Zend 2.0 represents conception of destructors which is similar to other objective oriented languages. When the last reference to an object is deleted, the object’s destructor is called before its destruction. Destructor is declared as method of a class named __destruct() and doesn’t take any parameters. For example:

<?php
class MyDestructableClass {
    function 
__construct() {
        print 
"In constructor\n";
        
$this->name 'MyDestructableClass';
    }

    function 
__destruct() {
        print 
'Destroying' $this->name "\n";
    }
}

$obj = new MyDestructableClass();
?>

As in the case with constructors, parent’s destructors aren’t called indirectly. To call a parent’s destructor you should define this within the destructor: parent::__destruct().

Exceptions

Core Zend 1.0 didn’t support exceptions’ handling. Core Zend 2.0 introduces an exceptions’ model which is similar to other programming languages (in particular with C++). Example:

<?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();
}
?>

If an exception is generated with instruction throw within block try, one of the handlers catch is called. In the handler type (i.e. name of a class) of an object transmitted and the name on which the object given will be available in the handler should be indicated. Some handlers may be defined for one try block. The necessary handler will be defined by the type indicated. Only object can be transmitted to the handler. The old code without functions ‘catch’, ‘throw’ and ‘try’ declared by a user will work without any changes.

Dereferencing of objects returned from functions

Example:

<?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();
?>

Static variables which are members of a class may be initialized.

Example:

<?php
class foo {
  static 
$my_static 5;
}

print 
foo::$my_static;
?>

Parameters transmitted into a function through reference can have a value on default.

Example:

<?php
function my_function(&$var null) {
     if (
$var === null) {
         die(
'$var needs to have a value');
     }
}
?>

 
  • Top