PHP5: Objects and OOP

Posted on January 27, 2011

Like everything else in the language, PHP doesn’t claim to achieve the level of “purity” that you’ll find in true OO languages. It’s really just an extension of the existing syntax.

Object Basics

Basically, the object model was completely rewritten for PHP5. Classes now have capabilities closer to what you would find in a language like C++/Java. This is why operations like copying objects can break after the upgrade — PHP4 objects are primitives, so they are copied; PHP5 by default uses references to pass objects around.

PHP5 also has some new ways of creating objects:

  • new self will create a new object of the same class as $this
  • new parent will create a new object of the same class as $this’ parent class
  • new $obj will create a new object of the same class as $obj
  • A class method can return new static to create a new object of the same class as $this

Comparison of 2 objects is in line with what you would expect: The standard comparison (==) will return true if the objects are of the same class and have the same attributes and values. The identity comparison (===) will only return true if the objects are the same instance.

PHP5 also has built-in support for iterating over objects, for example in a foreach loop. Properties will be available in the form property name => property value. The exact properties available depends on their visibility in the current scope: if you iterate over an object, then you’ll only see the public properties; if you iterate over $this, you’ll see the private/protected properties as well. (See the “Visibility” section below.)

Cloning

In PHP5, you can use the clone keyword to make a copy of the object.

$copy_of_object = clone $object;

This copies an object, including its properties. It’s a shallow copy — things like objects will just copy the reference. If you need more control, you can declare a __clone() method for the class. (See the “Magic Methods” section for more info.)

Visibility

Class properties and methods can now be declared with a given visibility: public, protected, or private. These work exactly as in C++ or Java, so check out the PHP manual or other OOP references if you’re not sure what they mean.

class MyClass
{
  public $myPublic;
  private $myPrivate;

  // Declare a public constructor
  public function __construct() { }

  // Declare a public method
  public function MyPublic() { }

  // Declare a protected method
  protected function MyProtected() { }

  // Declare a private method
  private function MyPrivate() { }
}

For now, you can still use var for class properties, where it acts as a synonym for public. I was unable to use both var and public/private/protected together, though (contrary to the PHP manual). Methods without an explicit visibility default to public.

Static Properties & Constants

In PHP5, you can now declare class properties as being static. Static properties are accessed using the same double-colon syntax (myClass::staticVar) as with other static variables.

The ordering of the static and public/private keywords doesn’t matter, but for consistency I would recommend following the PHP manual — visibility first, then scope after that.

Class constants act much like static properties, with some obvious differences:

  • Their values cannot be modified.
  • They are declared using the const keyword, and are not prefixed with a $ symbol (since they are not variables).
  • Constants don’t have a visibility, so you can’t use public/private/protected with them.

Inheritance

PHP5 still only has single inheritance in the form of the extends keyword, but now you can declare a class or a method as final. If a class is final, then it cannot be extended. If a method is final, then it cannot be overridden.

Abstraction

Classes and methods can now be abstracted, in the same manner as other OO languages. (In C++/Java, abstracted methods are called pure virtual functions.) Abstract classes cannot be instantiated; they can only be extended. Abstract methods must be defined in the child class as well.

abstract class AbstractClass
{
  // Force extending class to define this method
  abstract protected function getValue();
  abstract protected function prefixValue($prefix);

  // Common method
  public function printOut() {
    print $this->getValue() . "n";
  }
}

Interfaces

PHP5 also adds support for interfaces. Interfaces takes abstraction further to create a class that contains no functionality at all — it only declares (public) methods that the child class must implement.

Instead of using the normal class/extends syntax, interfaces use interface/implements:

// Declare the interface 'iTemplate'
interface iTemplate
{
  public function setVariable($name, $var);
  public function getHtml($template);
}

// Implement the interface
class Template implements iTemplate
{
  private $vars = array();

  public function setVariable($name, $var)
  {
    $this->vars[$name] = $var;
  }

  public function getHtml($template)
  {
    foreach($this->vars as $name => $value) {
      $template = str_replace('{' . $name . '}', $value, $template);
    }
    return $template;
  }
}

Interfaces can also be extended, and even use multiple inheritance, as long as there is no overlap in method names:

interface a
{
  public function foo();
}

interface b
{
  public function bar();
}

interface c extends a, b
{
  public function baz();
}

Constructors & Destructors

In PHP5, the constructor function is declared as __construct(). You can still include a method with the same name as the class for backward-compatibility with PHP4, but as of PHP 5.3.3, these functions will be ignored if no __construct() method exists.

Unlike normal methods, constructors can have a different parameter signature than their parent method.

Unlike C++/Java, you can’t have multiple constructors, but there are hacks around this — check out the user comments in reference manual for ideas.

PHP5 also introduces a destructor function, __destruct(). Like other OO languages, this method is called when its object is implicitly or explicitly deleted. In languages like C++, this method usually contains code to manually delete properties so there aren’t any memory leaks. PHP doesn’t have this problem, but you may need to use it for some cleanup — like constructors, the parent’s destructor is not automatically invoked.

Magic Methods

PHP5 allows you to define a number of “magic methods” — methods that, if defined, will be automatically invoked at specific times. Like constructors and destructors, these all begin with 2 underscores (__).

  • __sleep() — Called prior to serialize(). Returns an array of property names that should be serialized. Used for committing data and performing cleanup prior to serialization.
  • __wakeup() — Called during unserialize(). Used to reconstruct resources lost during serialization.
  • __toString() — Called when an object is explicitly or implicitly casted to a string. In PHP4, converting an object to a string will return the name of the class; in PHP5, casting an object to a string results in an error (if __toString() is not defined).
  • __set() — Called when a property that doesn’t exist or is not visible (“inaccessible”) is assigned a value. Takes the variable name and value for you to work with.
  • __get() — Called when the value of an inaccessible property is queried. Returns a value.
  • __isset() — Called when an inaccessible property is queried using isset() or empty().
  • __unset() — Called when an inaccessible property is invoked using unset().
  • __call() — Called when an inaccessible method is invoked. Takes the name of the function and an array of arguments.
  • __callStatic() — Just like __call(), but for methods invoked in a static context.
  • __clone() — Called when an object is cloned.
  • __invoke() — Called when an object is called as a function, to sort of overload the “()” operator.
  • __set_state() — Called when an object is exported using var_export(). I was not aware of var_export() until now, so I don’t see the uses yet.

Check out the manual for details on these methods.

More Tutorials

Leave a Reply

  1.  

    |