Crossing to PHP5

Introduction

In fact, PHP is the mostly widespread web-programming language. On the way to this status it has passed many stages from simple web-programming language with many drawbacks (PHP3) to the fast, powerful and distensible as it is nowadays (PHP4). It’s also very pleasant that PHP keeps developing staying at the same time easy for beginners and offering more abilities for more experienced developers. Expecting release of PHP5 a lot of information about innovations in PHP 5 appears including the information that comes from developers themselves. For example, wonderful article from one of the authors Zend Engine – Zeev Suraski will help a lot in understanding peculiarities of changes in work with objects. There are, of course, general reviews of PHP5 abilities. In my review I tried to give as complete picture of changes in PHP5 as I could. This article is also a peculiar ‘working report’ as review of each change is supported with its detailed examination and practical usage attempt.

Changes within PHP5

New access levels ‘private’ and ‘public’

In PHP5 new modifiers of access level for variable classes are added. As in many other programming languages they are entitled as ‘private’, ‘protected’ and ‘public’.

Private is the mostly limiting modifier. Private variable of a class can be used only in that class in which it was declared. It’s impossible to address it from other program code.

Protected is an extension of private area which adds it an ability to address a variable from descendant classes.

Public is a widening protected modifier which sets the widest access area. To the ability to use a variable in descendant classes the ability to address a variable directly from other code is added. Frankly speaking, public isn’t a new access area. Earlier all the classes’ variables have been public variables.

Private variables are used for algorithms which are used only within currant class and cannot be redirected in the descendant classes. Protected can be used when a family of objects is organized which possess similar algorithms and are organized into a hierarchy. Usage of public variables isn’t a common good practice but sometimes it is justified. They may be used if a class has many qualities which should be available to all algorithms which use this class.

In a similar way private/protected/public modifiers are used for class methods. Methods declared without modifier are public methods.

If method or variable are redirected in the descendant class, the access level should be the same or higher. For example, you can make protected method public in the descendant class but you cannot make it private.

As an example we’ll examine classes NewClass and NewClass1.

class NewClass {
// new PHP5 modifiers
private $myPrivateVar = "myPrivateVar";
protected $myProtectedVar = "myProtectedVar";
public $myPublicVar = "myPublicVar";
// old PHP declaration
var $myVar = "myVar";
}

class NewClass1 extends NewClass {
function getProtectedVar() {
return $this->myProtectedVar;
}
}

NewClass contains some variables with different access areas. NewClass1 is used for testing of vision areas connected with inheritance.

Create classes’ objects:

$c = new NewClass();
$c1 = new NewClass1();

Address the variables:

print $c->myPrivateVar;

Direct addressing to private results into an error.

print $c->myProtectedVar;

Direct addressing to protected variable results into an error.

print $c->myPublicVar;

Addressing to public variable returns its meaning.

print $c->myVar;

Addressing to variable declared in the old style is equivalent to addressing to a public variable.

print $c1->myPrivateVar;

Private variable hasn’t been inherited by NewClass1. Addressing it is equivalent to addressing a non-declared variable.

print $c1->myProtectedVar;

Protected variable has been inherited and direct addressing it results into an error. For checking the fact it has been inherited together with its initial meaning “print $c1->getProtectedVar();” can be called.

print $c1->myPublicVar;

Public variable has been inherited and addressing it returns its meaning.

Abstract classes and methods

Abstract classes are used for creating family of objects which possess unified interface. They are also used when we need to forbid creating object of some class.

Example for creation and usage of an abstract class:

abstract class NewClass {
abstract function myMethod();
}

class NewClass1 extends NewClass {
function myMethod() {
return ‘myMethod’;
}
}

$c = new NewClass1();
print $c->myMethod();

If the method is determined as abstract, it should be redirected in the descendant class. At that parameters of redirected method must coincide with those of abstract method. Access level modifier for abstract methods isn’t taken into account. Access level is determined by the method which redirects the abstract one.

Interfaces

Interface is similar to abstract class with the exception of the fact that usage of interfaces enables usage of multiple inheritance. Thus a class can realize some interfaces simultaneously instead of extending one abstract class only.

Example of interface usage:

interface Printable {
public function dump();
}
interface Editable {
public function edit();
}

class NewClass implements Printable, Editable {
function dump() { }
function edit() { }
}

$c = new NewClass();
print (($c instanceof Printable) ? ‘true’ : ‘false’);

Typification of functions’ parameters on the classes’ level

For functions’ parameters a class can be set which object can be delivered through this parameter. During the script’s work construction

function myFunction(MyClass $obj) {
}
is equal to construction

function myFunction($obj) {
if (!($obj instanceof MyClass || $obj == null)) {
die(‘Argument 1 must be an instance of ClassName’);
}
}

At this instanceof is spread over not only the class’s name but also over all its ancestors and realized interfaces.

For example, the following code will be accomplished without any errors:

interface Editable {
function edit();
}

abstract class View {
abstract function createView();
}

class NewClass extends View implements Editable {
function createView() { }
function edit() { }
function createMyView(View $obj) { }
function doEdit(Editable $obj) { }
}

$c = new NewClass();
$c->createMyView($c);
$c->doEdit($c);

Final classes and methods

Final method cannot be redirected in the successor class. It’s impossible to use final class for creation of successor classes. This can stand in good stead when you need to save an algorithm which is bagged in a class as invariable. For example, to prevent a programmer using a library from behavior redefinition. Final classes’ usage together with parameters’ typification creates practically 100 per cent obstacle on the way of extension or functionality substitution. Of course, it isn’t difficult to remove final from class or method by the open source but, for example, final is often used in classes which are defined in PHP itself or its extensions (Exception class, DOM extension).

Example of final class and final method:

final class Security {
function createUser() {
...
}
}

class View {
final static function createView(Security $user) {

}
}

Objects’ cloning

For objects’ cloning in PHP4 simple operation $clonedObject =$object was enough. All the qualities of $object were simply copied into $clonedObject. It was possible to change the cloning algorithm by writing your own method for this. In PHP5 special name __clone was invented for this method and access to the object created was simplified. For addressing a new object $this is used; for addressing an already existing object (which clone we make) we use $that.

If there is no __clone method, we use a standard method which copies all the properties of an object.

On the example it looks like this:

class Node {
private $next;
private $name;

function __clone() {
$this->name = $that->name;
$this->next = null;
}

function setName($name) { $this->name = $name; }
function getName() { return $this->name; }
function setNext(Node $next) { $this->next = $next; }
}

$n1 = new Node();
$n1->setName(“Node1”);

$n2 = new Node();
$n2->setName(“Node2”);
$n1->setNext($n2);

$n = $n2->__clone();
print_r($n);

The example also illustrates that it’s possible to get success to private variables of objects $this and $that within method __clone.

Constructors

The main drawback of PHP4 constructors’ structure is the necessity of synchronization of constructor’s name and class’s name. As the name of constructor must coincide with the name of the class we have to rename constructors when renaming a class. In case a class possesses some successors, we have to change accurately heritable class (extends) and call of ancestor class’s constructor (parent) within successor classes.

Leading in a constructor for class with common name __construct into PHP5 makes renaming classes during their development easier. If class has __construct and function which name coincides with the class’s name, __construct will be called as constructor. By reloading constructor method call of parent class’s constructor is made through parent::__construct().

Example of constructors’ usage:

class NewClass1 {
function __construct() {
print "NewClass1::__construct called";
}
}

class NewClass2 extends NewClass1 {
}

class NewClass3 extends newClass2 {
function __construct() {
print “NewClass3::__construct called”;
parent::__construct();
}
}

$n1 = new NewClass1();
// NewClass1::__construct called is put out

$n2 = new NewClass2();
// NewClass1::__construct called is put out- constructor is inherited and called

$n3 = new NewClass3();
// NewClass3::__construct called ? NewClass1::__construct called is put out

At this, if constructor is declared with private modifier, it will be impossible to create class with such constructor. But however addressing parent::__construct is possible. This offers us another way for evading class creation beside declaring it abstract.

Destructors

Destructors are new to PHP. They are rather useful for resources discharge works such as closing open files or data base connections. For destructors name __destruct is defined. As in case with constructors, a destructor can be called if it is inherited and not overloaded. If it is overloaded, only the overloaded constructor will be called. For calling destructor of the parent object you need to use parent::__destruct(). Destructor is called without any parameters.

Example of destructor’s usage:

class Computer {
function compute() {
// big resource-intensive calculations.
}

function __destruct() {
// send a letter that everything is accomplished
}
}

$c = new Computer();
$c->compute();

Constants

Within classes constants can be declared. This is another method (together with final classes and methods) for increase of code’s structure and readability.

Example for definition and usage of constants:

final class ControlTypes {
const Textbox = 1;
const Label = 2;
const Listbox = 3;
const Textarea = 4;
const Link = 7;
const Button = 6;
}

class Control {
private $type;

function __construct($type) {
$this->type = $type;
}
}

$c = new Control(ControlTypes::Textbox);

Modifiers public, protected, private cannot be applied to constants. Constants are always public. They can be addressed through the class’s name only, for example, ControlType::Textbox. Addressings through $this or other class object’s indicator aren’t supported. Only primitive type meaning is possible in a constant, i.e. string or number. Constants are inherited and can be redefined in the child classes. Very interesting peculiarity is the ability of interfaces to contain constants. For example:

interface myInterface {
const test = 2;
}

Exceptions’ intercept system

Exceptions are an imprescriptible part of any modern language. Exceptions’ intercept system combines operator throw, language structure “try { .. } catch ()[catch () …]”and the main object Exception. Unlike Java exceptions PHP lacks block finally.

The main application of exceptions’ system consists in usage of structure try/catch for separation of the principal program code and errors’ procession blocks. Mechanism exceptions also enables correct treatment of exceptions which appeared not directly in the code accomplished but in the functions used.

The following example demonstrates separation of a code from non-standard situations’ processor:

/**
* Notices:
*   Constructor DatabaseConnection may throw DatabaseException
*   Method getUser() may throw UserNotFoundException
*   Method sendMail() may throw MailServiceException
*/
try {
$cn = new DatabaseConnection();
$admin = cn->getUser('Admin');
$admin->sendMail('Database check is complete');
} catch (DatabaseException $e) {
print "Data base connection is impossible. Reason: " . $e->getMessage();
} catch (UserNotFoundException $e) {
print "User doesn’t’t exist ";
} catch (MailServiceException $e) {
print "Letter sending error: " . $e->getMessage();
} catch (Exception $e) {
print "Common error: " . $e->getMessage();
}

In general case usage of exceptions’ system can be replaced with usage of structures if and goto or only if but this results into more bulky code.

Exceptions’ system in PHP works only with exceptions ‘thrown’ by operator throw. Syntax errors aren’t processed with blocks try/catch because of obvious reasons.

At the moment only one exception class is defined in PHP: Exception. For the more flexible work with exceptions’ system you may add your own exception classes but inherit them from the basic class Exception in order to make it possible to catch an exception.

The main methods within class Exception are: getMessage(), getCode(), getTrace(), getFile(), getTraceAsString(), _toString(). All methods are final except for constructor and _toString(). Thus optional functionality of Exception child classes (sending mails with error information, log record) can be realized in constructor.

Class Exception is declared directly in PHP Engine but its approximate model can be presented like this (after www.zend.com):

class Exception {
function __construct(string $message=NULL, int $code=0) {
if (func_num_args()) {
$this->message = $message;
}
$this->code = $code;
$this->file = __FILE__; // of throw clause
$this->line = __LINE__; // of throw clause
$this->trace = debug_backtrace();
$this->string = StringFormat($this);
}

protected $message = “Unknown exception”;  // exception message
protected $code = 0; // user defined exception code
protected $file;     // source filename of exception
protected $line;     // source line of exception

private $trace;      // backtrace of exception
private $string;     // internal only!!

final function getMessage() {
return $this->message;
}
final function getCode() {
return $this->code;
}
final function getFile() {
return $this->file;
}
final function getTrace() {
return $this->trace;
}
final function getTraceAsString() {
return self::TraceFormat($this);
}
function _toString() {
return $this->string;
}
static private function StringFormat(Exception $exception) {
// … a function not available in PHP scripts
// that returns all relevant information as a string
}
static private function TraceFormat(Exception $exception) {
// … a function not available in PHP scripts
// that returns the backtrace as a string
}
}

Objects’ usage without references to them

A very considerable inconvenience in PHP4 has been calling of a methods’ succession. In PHP4 it’s impossible to create an object without reference to it as objects actually were only a syntax construction and on the core level they were equivalent to massives. This created, for example, such constructions:

$page = &$this->getPage();
$page->registerControl($this);

This, of course, isn’t very convenient. Created on the base of PHP5 core table of references to objects makes existing of references to object non-compulsory. Because of this following construction becomes possible:

$this->getPage()->registerControl($this);

It should be mentioned that although such approach is briefer to write its unreasonable usage may result into a very irrational code. For example, it isn’t recommended at any case to do like this:

for($i = 0; $i < 100; $i++)
$myObject->getProperty('relatedObject')->getAncestor($i)->update();

During this method’s work 200 objects are created and 300 methods’ calls are made. This number can be simply reduced to creation of 100 objects and 201 methods’ calls:

$relatedObject = $myObject->getProperty('relatedObject');
for($i = 0; $i < 100; $i++)
$relatedObject->getAncestor($i)->update();

In the following PHP versions you are to expect spreading this approach also over common massives. Of course, if they remain – objects possess a tendency to get more and more functionality. Then the following construction may be available: print ((new ServerEnvironment()).getServerVariables())[‘REQUEST_URI’].

Initialization of class variables out of constructor

Now it will be possible to indicate class variable’s meaning directly by its declaring. However its meaning may be of primitive type only, i.e. a string or a number. Nevertheless this is the only possible method for creation of meaning of static class variable. For example:

class MathUtils {
static private pi = 3.1415926;
...
}

It’s impossible to define pi in other way as far as there is no ‘static’ constructor for static variables.

Static methods of a class

Static methods of a class can be called directly from the class not through one of its objects. Correspondingly indicator $this is unavailable in the static methods. In fact, declaring a class with static methods is mostly grouping method for functions and their common constants and variables. For example, famous in PHP functions of connection with MySQL could be formed as a MySQL-class:

interface DatabaseInterface {
static function connect($host, $user, $password);
static function select_db($database);
static function query($query);
static function fetch_array();
static function free_result($result);
static function close($link);
}

class MySQL implements DatabaseInterface {
static CLIENT_COMPRESS = 1;
static CLIENT_IGNORE_SPACE = 2;

static function connect($host, $user, $password) {

}

static function select_db($database) {

}
}

Applying such approach guarantees that all data base access classes will realize one interface (interchangeability), reduces probability of names’ conflicts, simplifies existing of some versions of the data base access and so on.

instanceof operator

New operator ‘checked object instanceof checked class’ makes it possible to check if the class checked gets into the tree list of class inheritance which specimen the object checked is. On the example it looks like this:

interface Editable {
function startEdit();
function endEdit();
}

class Control {
function getValue() {
//…
}
}

class EditableControl extends Control implements Editable {
function startEdit() {
//…
}
function endEdit() {
//…
}
}

$c = new Control();
$ec = new EditableControl();

print “$c instanceof Editable = ” . ($c instanceof Editable ? “true” : “false”) . “<br>”;
print “$c instanceof Control = ” . ($c instanceof Control ? “true” : “false”) . “<br>”;
print “$c instanceof EditableControl = ” . ($c instanceof EditableControl ? “true” : “false”) . “<br>”;
print “$ec instanceof Editable = ” . ($ec instanceof Editable ? “true” : “false”) . “<br>”;
print “$ec instanceof Control = ” . ($ec instanceof Control ? “true” : “false”) . “<br>”;
print “$ec instanceof EditableControl = ” . ($ec instanceof EditableControl ? “true” : “false”);

The result of this code’s work will be following:

$c instanceof Editable = false
$c instanceof Control = true
$c instanceof EditableControl = false
$ec instanceof Editable = true
$ec instanceof Control = true
$ec instanceof EditableControl = true

Thus for $c instanceof returns true only for Control class; for $ec instanceof returns true only for Editable, Control, EditableControl. For null false will always be returned.

Static function variables

Variables within a function may be declared as static. Static variable of a function is a common variable for all the calls of this function. Static variable is equal in its sense to a global variable which is used within a function only.

Optional transferring through reference functions’ parameters

Parameters transferring through reference in PHP4 cannot have default meaning. This results into impossibility to create a function with an optional object parameter. But the community demanded and in PHP5 appeared an ability to set meaning on default for an object parameter. It should be mentioned that the only possible meaning on default for such parameters is null.

Example of usage:

class Unrequired {
...
}

function myFunction(Unrequired $param = null) {

}

myFunction();
myFunction(new Unrequired());

Event function by creation of an unknown class’s object (__autoload())

PHP doesn’t save all the application in the memory. Even more than this, it reloads all the files with code and converts into convenient for accomplishment form for each file. You can be helped a lot by different PHP code accelerators which save in the memory directly converted into accomplished code PHP-page. But even in case of such optimizer usage it’s undesirable to link up to the script all the files with classes and functions which you may need but don’t use. Setting up and linking up only necessary classes to each concrete page is an occupation which demands big accuracy and provoking a wish to automatize it somehow.

Perhaps namely on that reason the event function named __autoload() was introduced which functions by attempt to address an unknown class or interface. Under addressing is understood an attempt to create a class object, create a child class based on class, create a class realizing interface.

Another problem which __autoload solves is placement of files’ inclusion in order of inheritance hierarchy. For example, if MyClass1 is placed in file MyClass1.php and MyClass2 is placed in file MyClass2.php and MyClass2 extends MyClass1, they should be linked up by means of include only in order inlude(‘MyClass1.php’); include(‘MyClass2.php’). It doesn’t matter when you deal with 2 files. But when they are some tens it becomes difficult.

And finally an example of __autoload usage:

test.php ============================
function __autoload($name) {
include_once("classes/" . $name . ".php");
}

$t = new Textbox();

Control.php =========================
class Control {
// …
}

Textbox.php =========================
class Textbox extends Control {
// …
}

By attempt of Textbox creation file Textbox.php will be loaded. As far as Textbox extends Control Control.php will be loaded immediately

Event function by addressing property of class (__get(), __set())

Functions __get and __set can be treated as ability for realization of qualities which have analogy to properties in .NET, VBScript (ASP) or VB. But unlike all languages (technologies) enumerated in PHP __get and __set are accomplished for all the properties. For example:

<b>ASP</b>
Class MyClass
Property Let Value(NewValue)
...
End Property

Property Get Value()

End Property

Property Let State(NewValue)

End Property

Property Get State()

End Property
End Class

<b>PHP</b>
class MyClass {
function __get($name) {
switch($name) {
case “Value”:

break;
case “State”:

break;
}
}

function __set($name, $value) {
switch($name) {
case “Value”:

break;
case “State”:

break;
}
}
}

Calling methods __get() and __set() when addressing a property occurs only if the class variable with such name doesn’t exist. If it exists, addressing from the main program may result either into an error (if the variable is private or protected) or correspondingly into a variable (if it is public).

Properties’ successions ($myObj->parent->value) work properly. For example:

class Node {
private $mValue = 1;
private $mParent;

function __get($name) {
switch($name) {
case “Value”:
return $this->mValue;
case “Parent”:
return $this->mParent;
}
}

function __set($name, $value) {
switch($name) {
case “Value”:
$this->mValue = $value;
break;
case “Parent”:
$this->mParent = $value;
break;
}
}
}

$n1 = new Node();
$n2 = new Node();
$n2->Parent = $n1;
$n1->Value = 2;
print $n2->Parent->Value; // Puts out 2.

Event function by addressing a method of class (__call())

Event function __call() may be led in together with __get() and __set(). This function is most likely to find its further application. For example, it can be used for emulation of methods’ reloading:

class SpecialItem {
//...
}

class GeneralItem {
//…
}

class Processor {
function processSpecialItem(SpecialItem $item) {
//…
}

function processGeneralItem(GeneralItem $item) {
//…
}

function __call($method, $attributes) {
if ($method == “process” && count($attributes) == 1) {
if ($attributes[0] instanceof GeneralItem)
$this->processGeneralItem($attributes[0]);
elseif ($attributes[0] instanceof SpecialItem)
$this->processSpecialItem($attributes[0]);
}
}
}

$p = new Processor();
$p->process(new GeneralItem()); //processGeneralItem would be called.
$p->process(new SpecialItem()); //processSpecialItem would be called.

Iteration on class properties

All the class variables which are available in the current context can be sorted out by foreach cycle. Such iteration on class properties can be very useful by objects’ cloning. For example, if you need to create a clone of an object with big class variables’ number, you may do like this:

class Node {
private $value;
private $parent;
...
private $type;

function __clone() {
foreach ($that as $propertyName => $propertyValue) {
$this->$propertyName = $propertyValue;
}
}

function setParent($value) { $this->parent = $value; }
function getParent() { return $this->parent; }
function setValue($value) { $this->value = $value; }
function getValue() { return $this->value; }

function setType($value) { $this->type = $value; }
function getType() { return $this->type; }
}

$myNode = new Node();
$myNode->setValue(10);
$myNextNode = $myNode->__clone();
print $myNextNode->getValue();

Simple cycle substitutes easily big number of assignments and saves from necessity to synchronize assignments by cloning with all class variables’ list. In an obvious way this iteration cannot be applied to class properties realized through __get()/__set() functions.

Changing of standard iteration on properties

Standard language elements which enable iteration are massives. But their drawbacks are obvious – you may mistakenly place into the massive an element of another type. It’s impossible to add methods for contains checking to the massive and so on.

For adding optional substances (classes) which enable iteration on their elements two interfaces exist: IteratorAggregate and Iterator.

interface IteratorAggregate {
function getIterator(); // returns massive or object
}

IteratorAggregate can be used when iteration data can be presented in one of the standard PHP-constructions enabling iteration: massive or object realizing Iterator.

Example of IteratorAggregate usage with iteration on massive elements:

/**
Notice:
This example doesn’t work in PHP5 beta 3.
Nevertheless it’s declared in the documentation that getIterator()
May return massive or object realizing Iterator.
I hope it will be corrected to release.
*/
class Control implements IteratorAggregate {
private $controls;
private $name;

function __construct() {
$this->controls = array();
}

function addControl($obj) {
$this->controls[$obj->getName()] = $obj;
}

function setName($value) { $this->name = $value; }
function getName() { return $this->name; }

// this function is from IteratorAggregate
function getIterator() {
return $this->controls;
}
}

$c1 = new Control();
$c1->setName(“userId”);
$c2 = new Control();
$c2->setName(“userName”);
$form = new Control();
$form->addControl($c1);
$form->addControl($c2);

foreach ($form as $ctrl) {
echo $ctrl->getName() . “<br>”;
}

This variant is only a superstructure over the standard PHP-functionality and may be used when you may get all the elements taking part in the iteration before the iteration itself begins. If it’s impossible to do this (in case of getting records from the data base or reading strings from big file) another mechanism is used for iteration’s extension – realization of Iterator interface.

interface Iterator {
function rewind(); // moves iteration to the first element
function next(); // prepares the next element to output
function key(); // returns key of the current element
function current(); // returns current element
function hasMore(); // returns true if there are other elements, otherwise false
}

Following example demonstrates iteration up to finding the element needed:

class Control {
private $name;

function setName($value) { $this->name = $value; }
function getName() { return $this->name; }
}

class Controls implements Iterator {
private $controls;
private $controlNames;
private $num;

function __construct() {
$this->controls = array();
}

function addControl($obj) {
$this->controls[$obj->getName()] = $obj;
}

// the function use class iteration abilities for
// control search with set number
function findControl($name) {
foreach ($this as $control) {
if ($control->getName() == $name)
return $control;
}

return null;
}

// following functions from Iterator
function rewind() {
$this->controlNames = array_keys($controls);
$this->num = 0;
}

function next() {
$this->num++;
}

function key() {
return $this->controlNames($this->num);
}

function current() {
return $this->controls[$this->key()];
}

function hasMore() {
return $this->num < count($this->controlNames);
}

}

$c1 = new Control();
$c1->setName(“userId”);
$c2 = new Control();
$c2->setName(“userName”);
$formControls = new Controls();
$formControls->addControl($c1);
$formControls->addControl($c2);

$userId = $formControls->findControl(“userId”);
$userName = $formControls->findControl(“userName”);

Constant __METHOD__

Constant __METHOD__ is a good addition to already existing ‘magic’ constants of PHP4: __LINE__, __FILE__, __FUNCTION__ (from PHP4.3.0), __CLASS__ (from PHP4.3.0). Such constants are called magic as far as they change their meaning depending on place of the call. I think, the things they return are rather obvious except for difference between __FUNCTION__ and __METHOD__ as far as function of a class is its method at the same time. The PHP5-developers should have decided that constant __FUNCTION__ which returns only name of a function or class method isn’t enough and added constant __METHOD__ returning name of a class (in lower register) and name of a method separated with two colons.

Thus the next code puts out text “myclass|myMethod|myclass::myMethod”:

Class MyClass {
function myMethod() {
echo __CLASS__ . '|' . __FUNCTION__ . '|' . __METHOD__;
}
}

$m = new MyClass();
$m->myMethod();

Method __toString()

When an object variable is converted to string as the result string “Object id #n” returns where n is a number of an object in the global objects’ table. You can change this mechanism if necessary (although it occurs very seldom) by creation of class’s method __toString() which returns some string presentation of the current object.

Although this algorithm isn’t completely worked over by PHP5 beta 3 (__toString() works only by usage of indicator on an object in print operator) this opens interesting perspectives. For example, the following code is a variation of PHP- typification:

class Integer {
private $value;
function __construct($val) {
$this->value = $val;
}
function __toString() {
return (string)($this->value);
}
}

$i = new Integer(10);
/**
Theoretically $i by conversion to a string should give ‘10’
and as far as number 10 is compared to a string it also should
be led to string. We’ll get “10” == “10”. Practically in
this case conversion of $i to string is done according to the variant
PHP4 (i.e. as a result we get “Object” string).
*/

if (10 == $i)
echo ’10!!!! :-)’;

Reflection API

Reflection isn’t a new notion for PHP but only in PHP5 an attempt was made to overview work with structure objects of language. Under structure objects we understand functions, classes, interfaces, parameters and extensions.

Reflection classes enable getting information about language objects immediately during script’s accomplishment. For example, you may get information about some object including its methods, their parameters, in which file description of an object is placed and even which documental comment is placed before it.

Reflection classes are made for each structure language object:

  • Reflection_Function
  • Reflection_Parameter
  • Reflection_Method
  • Reflection_Class
  • Reflection_Property
  • Reflection_Extension

Unlike most other changes in PHP5 Reflections are already documented well enough. Detailed description is available on the address http://sitten-polizei.de/php/reflection_api/docs/language.reflection.html.

Example of Reflection usage:


/**
MyClass is a simple example for demonstration of Reflection.
This code will be put out as documentation to the class MyClass by Reflection.
*/
class MyClass {

/**
And this is a comment to constructor
*/
function __construct() {
}
}

Reflection::export(new Reflection_Class('MyClass'));

Work of this code results into following class description:

/**
MyClass is a simple class sample for demonstration of  Reflection.
This code will be put out as documentation to the class MyClass by Reflection.
*/
Class [ <user>  class myclass ] {
@@ /home/alex/public_html/devlink_draft/articles/docs/test.php 7-14

- Constants [0] {
}

- Static properties [0] {
}

- Static methods [0] {
}

- Properties [0] {
}

- Methods [1] {
/**
And this is a comment to constructor
*/
Method [ <user> <ctor> public method __construct ] {
@@ /home/alex/public_html/devlink_draft/articles/docs/test.php 12 - 13
}
}
}

affiliate_link
Share this Post:
Digg Google Bookmarks reddit Mixx StumbleUpon Technorati Yahoo! Buzz DesignFloat Delicious BlinkList Furl

Comments are closed.