Section 1.2. Language Features


1.2. Language Features

1.2.1. New Object-Oriented Model

When Zeev Suraski added the object-oriented syntax back in the days of PHP 3, it was added as "syntactic sugar for accessing collections." The OO model also had support for inheritance and allowed a class (and object) to aggregate both methods and properties, but not much more. When Zeev and Andi Gutmans rewrote the scripting engine for PHP 4, it was a completely new engine; it ran much faster, was more stable, and boasted more features. However, the OO model first introduced in PHP 3 was barely touched.

Although the object model had serious limitations, it was used extensively around the world, often in large PHP applications. This impressive use of the OOP paradigm with PHP 4, despite its weaknesses, led to it being the main focus for the PHP 5 release.

So, what were some of the limitations in PHP 3 and 4? The biggest limitation (which led to further limitations) was the fact that the copy semantics of objects were the same as for native types. So, how did this actually affect the PHP developer? When assigning a variable (that points to an object) to another variable, a copy of the object would be created. Not only did this impact performance, but it also usually led to obscure behavior and bugs in PHP 4 applications because many developers thought that both variables would point at the same object, which was not the case. The variables were instead pointing at separate copies of the same object. Changing one would not change the other.

For example:

 class Person {     var $name;     function getName()      {         return $this->name;     }     function setName($name)      {         $this->name = $name;     }     function Person($name)      {         $this->setName($name);     } } function changeName($person, $name)  {     $person->setName($name); } $person = new Person("Andi"); changeName($person, "Stig"); print $person->getName(); 

In PHP 4, this code would print out "Andi". The reason is that we pass the object $person to the changeName() function by-value, and thus, $person is copied and changeName() works on a copy of $person.

This behavior is not intuitive, as many developers would expect the Java-like behavior. In Java, variables actually hold a handle (or pointer) to the object, and therefore, when it is copied, only the handle (and not the entire object) is duplicated.

There were two kinds of users in PHP 4: the ones who were aware of this problem and the ones who were not. The latter would usually not notice this problem and their code was written in a way where it did not really matter if the problem existed. Surely some of these people had sleepless nights trying to track down weird bugs that they could not pinpoint. The former group dealt with this problem by always passing and assigning objects by reference. This would prevent the engine from copying their objects, but it would be a headache because the code included numerous & signs.

The old object model not only led to the afore-mentioned problems, but also to fundamental problems that prevented implementing some additional features on top of the existing object model.

In PHP 5, the infrastructure of the object model was rewritten to work with object handles. Unless you explicitly clone an object by using the clone keyword, you never create behind-the-scenes duplicates of your objects. In PHP 5, you don't need a need to pass objects by reference or assign them by reference.

Note

Passing by reference and assigning by reference are still supported, in case you want to actually change a variable's content (whether object or other type).


1.2.2. New Object-Oriented Features

The new OO features are too numerous to give a detailed description in this section. Chapter 3, "PHP 5 OO Language," details each feature.

The following list provides the main new features:

  • public/private/protected access modifiers for methods and properties.

    Allows the use of common OO access modifiers to control access to methods and properties:

     class MyClass {     private $id = 18;     public function getId() {         return $this->id;    } } 

  • Unified constructor name __construct().

    Instead of the constructor being the name of the class, it is now declared as __construct(), which makes it easier to shift classes inside class hierarchies:

     class MyClass {      function __construct() {         print "Inside constructor";     } } 

  • Object destructor support by defining a __destructor() method.

    Allows defining a destructor function that runs when an object is destroyed:

     class MyClass {     function __destruct() {         print "Destroying object";     } } 

  • Interfaces.

    Gives the ability for a class to fulfill more than one is-a relationships. A class can inherit only from one class, but may implement as many interfaces as it wants:

     interface Display {     function display(); } class Circle implements Display {     function display() {         print "Displaying circle\n";     } } 

  • instanceof operator.

    Language-level support for is-a relationship checking. The PHP 4 is_a() function is now deprecated:

     if ($obj instanceof Circle) {     print '$obj is a Circle'; } 

  • Final methods.

    The final keyword allows you to mark methods so that an inheriting class cannot overload them:

     class MyClass {     final function getBaseClassName() {         return __CLASS__;     } } 

  • Final classes.

    After declaring a class as final, it cannot be inherited. The following example would error out.

     final class FinalClass { } class BogusClass extends FinalClass { } 

  • Explicit object cloning.

    To clone an object, you must use the clone keyword. You may declare a __clone() method, which will be called during the clone process (after the properties have been copied from the original object):

     class MyClass {     function __clone() {          print "Object is being cloned";     } } $obj = new MyClass(); $obj_copy = clone $obj; 

  • Class constants.

    Class definitions can now include constant values and are referenced using the class:

     class MyClass {      const SUCCESS = "Success";      const FAILURE = "Failure"; } print MyClass::SUCCESS; 

  • Static methods.

    You can now define methods as static by allowing them to be called from non-object context. Static methods do not define the $this variable because they are not bound to any specific object:

     class MyClass {     static function helloWorld() {         print "Hello, world";     } } MyClass::helloWorld(); 

  • Static members.

    Class definitions can now include static members (properties) that are accessible via the class. Common usage of static members is in the Singleton pattern:

     class Singleton {     static private $instance = NULL;     private function __construct() {     }     static public function getInstance() {         if (self::$instance == NULL) {             self::$instance = new Singleton();         }         return self::$instance;     } } 

  • Abstract classes.

    A class may be declared abstract to prevent it from being instantiated. However, you may inherit from an abstract class:

     abstract class MyBaseClass {     function display() {         print "Default display routine being called";     } } 

  • Abstract methods.

    A method may be declared abstract, thereby deferring its definition to an inheriting class. A class that includes abstract methods must be declared abstract:

     abstract class MyBaseClass {     abstract function display(); } 

  • Class type hints.

    Function declarations may include class type hints for their parameters. If the functions are called with an incorrect class type, an error occurs:

     function expectsMyClass(MyClass $obj) { } 

  • Support for dereferencing objects that are returned from methods.

    In PHP 4, you could not directly dereference objects that were returned from methods. You had to first assign the object to a dummy variable and then dereference it.

    PHP 4:

     $dummy = $obj->method(); $dummy->method2(); 

    PHP 5:

     $obj->method()->method2(); 

  • Iterators.

    PHP 5 allows both PHP classes and PHP extension classes to implement an Iterator interface. After you implement this interface, you can iterate instances of the class by using the foreach() language construct:

     $obj = new MyIteratorImplementation(); foreach ($obj as $value) {     print "$value"; } 

For a more complete example, see Chapter 4, "PHP 5 Advanced OOP and Design Patterns."

  • __autoload().

Many developers writing object-oriented applications create one PHP source file per class definition. One of the biggest annoyances is having to write a long list of needed inclusions at the beginning of each script (one for each class). In PHP 5, this is no longer necessary. You may define an __autoload() function that is automatically called in case you are trying to use a class that has not been defined yet. By calling this function, the scripting engine offers one last chance to load the class before PHP bails out with an error:

 function __autoload($class_name) {     include_once($class_name . "php"); } $obj = new MyClass1(); $obj2 = new MyClass2(); 

1.2.3. Other New Language Features

  • Exception handling.

    PHP 5 adds the ability for the well-known TRy/throw/catch structured exception-handling paradigm. You are only allowed to throw objects that inherit from the Exception class:

     class SQLException extends Exception {     public $problem;     function __construct($problem) {         $this->problem = $problem;     } } try {     ...     throw new SQLException("Couldn't connect to database");     ... } catch (SQLException $e) {     print "Caught an SQLException with problem $obj->problem"; } catch (Exception $e) {     print "Caught unrecognized exception"; } 

Currently for backward-compatibility purposes, most internal functions do not throw exceptions. However, new extensions make use of this capability, and you can use it in your own source code. Also, similar to the already existing set_error_handler(), you may use set_exception_handler() to catch an unhandled exception before the script terminates.

  • foreach with references.

    In PHP 4, you could not iterate through an array and modify its values. PHP 5 supports this by enabling you to mark the foreach() loop with the & (reference) sign, which makes any values you change affect the array over which you are iterating:

     foreach ($array as &$value) {     if ($value === "NULL") {         $value = NULL;     } } 

  • Default values for by-reference parameters.

    In PHP 4, default values could be given only to parameters, which are passed by-values. PHP 5 now supports giving default values to by-reference parameters:

     function my_func(&$arg = null) {     if ($arg === NULL) {         print '$arg is empty';     } } my_func(); 



    PHP 5 Power Programming
    PHP 5 Power Programming
    ISBN: 013147149X
    EAN: 2147483647
    Year: 2003
    Pages: 240

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net