0% found this document useful (0 votes)
27 views

PHP1

Class definitions begin with the "class" keyword followed by a class name in curly braces. A $this pseudo-variable refers to the calling object from within methods. Classes can extend other classes using the "extends" keyword to inherit methods and properties. Constructors and destructors allow initialization and cleanup of objects. Class members and methods can be declared as public, private, or protected to control visibility and access.

Uploaded by

Sanchit Garg
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views

PHP1

Class definitions begin with the "class" keyword followed by a class name in curly braces. A $this pseudo-variable refers to the calling object from within methods. Classes can extend other classes using the "extends" keyword to inherit methods and properties. Constructors and destructors allow initialization and cleanup of objects. Class members and methods can be declared as public, private, or protected to control visibility and access.

Uploaded by

Sanchit Garg
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

The Basics

class

Every class definition begins with the keyword class, followed by a class name, which can be
any name that isn't a reserved word in PHP. Followed by a pair of curly braces, which contains
the definition of the classes members and methods. A pseudo-variable, $this is available when
a method is called from within an object context. $this is a reference to the calling object
(usually the object to which the method belongs, but can be another object, if the method is
called statically from the context of a secondary object). This is illustrated in the following
examples:

Example #1 $this variable in object-oriented language

<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this is not defined.\n";
}
}
}

class B
{
function bar()
{
A::foo();
}
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>

The above example will output:


$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.

Example #2 Simple Class definition

<?php
class SimpleClass
{
// member declaration
public $var = 'a default value';

// method declaration
public function displayVar() {
echo $this->var;
}
}
?>

The default value must be a constant expression, not (for example) a variable, a class member
or a function call.

Example #3 Class members' default value

<?php
class SimpleClass
{
// invalid member declarations:
public $var1 = 'hello '.'world';
public $var2 = <<<EOD
hello world
EOD;
public $var3 = 1+2;
public $var4 = self::myStaticMethod();
public $var5 = $myVar;

// valid member declarations:


public $var6 = myConstant;
public $var7 = self::classConstant;
public $var8 = array(true, false);

}
?>
Example #4 Static data example

<?php
class foo {
// As of PHP 5.3.0
public $bar = <<<'EOT'
bar
EOT;
}
?>

Note: Nowdoc support was added in PHP 5.3.0.

new

To create an instance of a class, a new object must be created and assigned to a variable. An
object will always be assigned when creating a new object unless the object has a constructor
defined that throws an exception on error. Classes should be defined before instantiation (and in
some cases this is a requirement).

Example #5 Creating an instance

<?php
$instance = new SimpleClass();
?>

In the class context, it is possible to create a new object by new self and new parent.

When assigning an already created instance of a class to a new variable, the new variable will
access the same instance as the object that was assigned. This behaviour is the same when
passing instances to a function. A copy of an already created object can be made by cloning it.

extends

A class can inherit methods and members of another class by using the extends keyword in the
declaration. It is not possible to extend multiple classes, a class can only inherit one base class.

The inherited methods and members can be overridden, unless the parent class has defined a
method as final, by redeclaring them with the same name defined in the parent class. It is
possible to access the overridden methods or static members by referencing them with parent::

Example #7 Simple Class Inheritance

<?php
class ExtendClass extends SimpleClass
{
// Redefine the parent method
function displayVar()
{
echo "Extending class\n";
parent::displayVar();
}
}

$extended = new ExtendClass();


$extended->displayVar();
?>

The above example will output:

Extending class
a default value

Autoloading Objects

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 includes at the
beginning of each script (one for each class).

In PHP 5, this is no longer necessary. You may define an __autoload function which is
automatically called in case you are trying to use a class/interface which hasn't been defined
yet. By calling this function the scripting engine is given a last chance to load the class before
PHP fails with an error.

Note: Exceptions thrown in __autoload function cannot be caught in the catch block and results
in a fatal error.

Note: Autoloading is not available if using PHP in CLI interactive mode.

Note: If the class name is used e.g. in call_user_func() then it can contain some dangerous
characters such as ../. It is recommended to not use the user-input in such functions or at least
verify the input in __autoload().

Example #1 Autoload example

This example attempts to load the classes MyClass1 and MyClass2 from the files MyClass1.php
and MyClass2.php respectively.

<?php
function __autoload($class_name) {
require_once $class_name . '.php';
}

$obj = new MyClass1();


$obj2 = new MyClass2();
?>
This example attempts to load the interface ITest.

<?php

function __autoload($name) {
var_dump($name);
}

class Foo implements ITest {


}

/*
string(5) "ITest"

Fatal error: Interface 'ITest' not found in ...


*/
?>

Constructors and Destructors

Constructor

void __construct ([ mixed $args [, $... ]] )

PHP 5 allows developers to declare constructor methods for classes. Classes which have a
constructor method call this method on each newly-created object, so it is suitable for any
initialization that the object may need before it is used.

Note: Parent constructors are not called implicitly if the child class defines a constructor. In
order to run a parent constructor, a call to parent::__construct() within the child constructor is
required.

Example #1 using new 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 backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it
will search for the old-style constructor function, by the name of the class. Effectively, it means
that the only case that would have compatibility issues is if the class had a method named
__construct() which was used for different semantics.

Destructor

void __destruct ( void )

PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such
as C++. The destructor method will be called as soon as all references to a particular object are
removed or when the object is explicitly destroyed or in any order in shutdown sequence.

Example #2 Destructor Example

<?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 destructors will not be called implicitly by the engine. In order to run a
parent destructor, one would have to explicitly call parent::__destruct() in the destructor body.

Note: Destructors called during the script shutdown have HTTP headers already sent. The
working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache).

Note: Attempting to throw an exception from a destructor (called in the time of script termination)
causes a fatal error.

Visibility

The visibility of a property or method can be defined by prefixing the declaration with the
keywords: public, protected or private. Public declared items can be accessed everywhere.
Protected limits access to inherited and parent classes (and to the class that defines the item).
Private limits visibility only to the class that defines the item.

Members Visibility

Class members must be defined with public, private, or protected.


Example #1 Member declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';

function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}

$obj = new MyClass();


echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private

/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';

function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}

$obj2 = new MyClass2();


echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined

?>

Note: The PHP 4 method of declaring a variable with the var keyword is still supported for
compatibility reasons (as a synonym for the public keyword). In PHP 5 before 5.1.3, its usage
would generate an E_STRICT warning.
Method Visibility

Class methods must be defined with public, private, or protected. Methods without any
declaration are defined as public.

Example #2 Method Declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
// 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() { }

// This is public
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}

$myclass = new MyClass;


$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work

/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// This is public
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // Fatal Error
}
}
$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private

class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}

public function testPublic() {


echo "Bar::testPublic\n";
}

private function testPrivate() {


echo "Bar::testPrivate\n";
}
}

class Foo extends Bar


{
public function testPublic() {
echo "Foo::testPublic\n";
}

private function testPrivate() {


echo "Foo::testPrivate\n";
}
}

$myFoo = new foo();


$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>

Scope Resolution Operator (::)

The Scope Resolution Operator (also called Paamayim Nekudotayim) or in simpler terms, the
double colon, is a token that allows access to static, constant, and overridden members or
methods of a class.

When referencing these items from outside the class definition, use the name of the class.

As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can
not be a keyword (e.g. self, parent and static).

Paamayim Nekudotayim would, at first, seem like a strange choice for naming a double-colon.
However, while writing the Zend Engine 0.5 (which powers PHP 3), that's what the Zend team
decided to call it. It actually does mean double-colon - in Hebrew!

Example #1 :: from outside the class definition


<?php
class MyClass {
const CONST_VALUE = 'A constant value';
}

$classname = 'MyClass';
echo $classname::CONST_VALUE; // As of PHP 5.3.0

echo MyClass::CONST_VALUE;
?>

Two special keywords self and parent are used to access members or methods from inside the
class definition.

Example #2 :: from inside the class definition

<?php
class OtherClass extends MyClass
{
public static $my_static = 'static var';

public static function doubleColon() {


echo parent::CONST_VALUE . "\n";
echo self::$my_static . "\n";
}
}

$classname = 'OtherClass';
echo $classname::doubleColon(); // As of PHP 5.3.0

OtherClass::doubleColon();
?>

When an extending class overrides the parents definition of a method, PHP will not call the
parent's method. It's up to the extended class on whether or not the parent's method is called.
This also applies to Constructors and Destructors, Overloading, and Magic method definitions.

Static Keyword

Declaring class members or methods as static makes them accessible without needing an
instantiation of the class. A member declared as static can not be accessed with an instantiated
class object (though a static method can).

For compatibility with PHP 4, if no visibility declaration is used, then the member or method will
be treated as if it was declared as public.

Because static methods are callable without an instance of the object created, the pseudo
variable $this is not available inside the method declared as static.

Static properties cannot be accessed through the object using the arrow operator ->.

Calling non-static methods statically generates an E_STRICT level warning.


As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can
not be a keyword (e.g. self, parent and static).

Example #1 Static member example

<?php
class Foo
{
public static $my_static = 'foo';

public function staticValue() {


return self::$my_static;
}
}

class Bar extends Foo


{
public function fooStatic() {
return parent::$my_static;
}
}

print Foo::$my_static . "\n";

$foo = new Foo();


print $foo->staticValue() . "\n";
print $foo->my_static . "\n"; // Undefined "Property" my_static

print $foo::$my_static . "\n";


$classname = 'Foo';
print $classname::$my_static . "\n"; // As of PHP 5.3.0

print Bar::$my_static . "\n";


$bar = new Bar();
print $bar->fooStatic() . "\n";
?>

Example #2 Static method example

<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}

Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
?>

Class Constants
It is possible to define constant values on a per-class basis remaining the same and
unchangeable. Constants differ from normal variables in that you don't use the $ symbol to
declare or use them.

The value must be a constant expression, not (for example) a variable, a class member, result
of a mathematical operation or a function call.

As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can
not be a keyword (e.g. self, parent and static).

Example #1 Defining and using a constant

<?php
class MyClass
{
const constant = 'constant value';

function showConstant() {
echo self::constant . "\n";
}
}

echo MyClass::constant . "\n";

$classname = "MyClass";
echo $classname::constant . "\n"; // As of PHP 5.3.0

$class = new MyClass();


$class->showConstant();

echo $class::constant."\n"; // As of PHP 5.3.0


?>

Example #2 Static data example

<?php
class foo {
// As of PHP 5.3.0
const bar = <<<'EOT'
bar
EOT;
}
?>

Unlike heredocs, nowdocs can be used in any static data context.

Note: Nowdoc support was added in PHP 5.3.0.

Class Abstraction

PHP 5 introduces abstract classes and methods. It is not allowed to create an instance of a
class that has been defined as abstract. Any class that contains at least one abstract method
must also be abstract. Methods defined as abstract simply declare the method's signature they
cannot define the implementation.

When inheriting from an abstract class, all methods marked abstract in the parent's class
declaration must be defined by the child; additionally, these methods must be defined with the
same (or a less restricted) visibility. For example, if the abstract method is defined as protected,
the function implementation must be defined as either protected or public, but not private.

Example #1 Abstract class example

<?php
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";
}
}

class ConcreteClass1 extends AbstractClass


{
protected function getValue() {
return "ConcreteClass1";
}

public function prefixValue($prefix) {


return "{$prefix}ConcreteClass1";
}
}

class ConcreteClass2 extends AbstractClass


{
public function getValue() {
return "ConcreteClass2";
}

public function prefixValue($prefix) {


return "{$prefix}ConcreteClass2";
}
}

$class1 = new ConcreteClass1;


$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;


$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>
The above example will output:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

Old code that has no user-defined classes or functions named 'abstract' should run without
modifications.

Object Interfaces

Object interfaces allow you to create code which specifies which methods a class must
implement, without having to define how these methods are handled.

Interfaces are defined using the interface keyword, in the same way as a standard class, but
without any of the methods having their contents defined.

All methods declared in an interface must be public, this is the nature of an interface.

implements

To implement an interface, the implements operator is used. All methods in the interface must
be implemented within a class; failure to do so will result in a fatal error. Classes may implement
more than one interface if desired by separating each interface with a comma.

Note: A class cannot implement two interfaces that share function names, since it would cause
ambiguity.

Examples

Example #1 Interface example

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

// Implement the interface


// This will work
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;
}
}

// This will not work


// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();

public function setVariable($name, $var)


{
$this->vars[$name] = $var;
}
}

?>

Overloading

Overloading in PHP provides means to dynamically "create" members and methods. These
dynamic entities are processed via magic methods one can establish in a class for various
action types.

The overloading methods are invoked when interacting with members or methods that have not
been declared or are not visible in the current scope. The rest of this section will use the terms
"inaccessible members" and "inaccessible methods" to refer to this combination of declaration
and visibility.

All overloading methods must be defined as public.

Note: None of the arguments of these magic methods can be passed by reference.

Note: PHP's interpretation of "overloading" is different than most object oriented languages.
Overloading traditionally provides the ability to have multiple methods with the same name but
different quantities and types of arguments.

ChangeLog

Version Description
5.1.0 Added __isset() and __unset().
Version Description
5.3.0 Added __callStatic().

Member overloading

void __set ( string $name , mixed $value )


mixed __get ( string $name )
bool __isset ( string $name )
void __unset ( string $name )

__set() is run when writing data to inaccessible members.

__get() is utilized for reading data from inaccessible members.

__isset() is triggered by calling isset() or empty() on inaccessible members.

__unset() is invoked when unset() is used on inaccessible members.

The $name argument is the name of the member being interacted with. The __set() method's
$value argument specifies the value the $name'ed member should be set to.

Member overloading only works in object context. These magic methods will not be triggered in
static context. Therefore these methods can not be declared static.

Example #1 overloading with __get, __set, __isset and __unset example

<?php
class MemberTest {
/** Location for overloaded data. */
private $data = array();

/** Overloading not used on declared members. */


public $declared = 1;

/** Overloading not triggered when accessed inside the class. */


private $hidden = 2;

public function __set($name, $value) {


echo "Setting '$name' to '$value'\n";
$this->data[$name] = $value;
}

public function __get($name) {


echo "Getting '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}

$trace = debug_backtrace();
trigger_error(
'Undefined property: ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}

/** As of PHP 5.1.0 */


public function __isset($name) {
echo "Is '$name' set?\n";
return isset($this->data[$name]);
}

/** As of PHP 5.1.0 */


public function __unset($name) {
echo "Unsetting '$name'\n";
unset($this->data[$name]);
}

/** Not a magic method, just here for example. */


public function getHidden() {
echo "'hidden' visible here so __get() not used\n";
return $this->hidden;
}
}

echo "<pre>\n";

$obj = new MemberTest;

$obj->a = 1;
echo $obj->a . "\n";

var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));

echo $obj->declared . "\n";


echo $obj->getHidden() . "\n";
echo $obj->hidden . "\n";
?>

The above example will output:

Setting 'a' to '1'


Getting 'a'
1
Is 'a' set?
bool(true)
Unsetting 'a'
Is 'a' set?
bool(false)
1
'hidden' visible here so __get() not used
2
Getting 'hidden'

Notice: Undefined property: hidden in <file> on line 64 in <file> on line 28

Method overloading

mixed __call ( string $name , array $arguments )


mixed __callStatic ( string $name , array $arguments )

__call() is triggered when invoking inaccessible methods in an object context.

__callStatic() is triggered when invoking inaccessible methods in a static context.

The $name argument is the name of the method being called. The $arguments argument is an
enumerated array containing the parameters passed to the $name'ed method.

Example #2 overloading instantiated methods with __call and ___callStatic

<?php
class MethodTest {
public function __call($name, $arguments) {
// Note: value of $name is case sensitive.
echo "Calling object method '$name' "
. implode(', ', $arguments). "\n";
}

/** As of PHP 5.3.0 */


public static function __callStatic($name, $arguments) {
// Note: value of $name is converted to lower case.
echo "Calling static method '$name' "
. implode(', ', $arguments). "\n";
}
}

$obj = new MethodTest;


$obj->runTest('in object context');

MethodTest::runTest('in static context'); // As of PHP 5.3.0


?>

The above example will output:

Calling object method 'runTest' in object context


Calling static method 'runtest' in static context
Object Iteration

PHP 5 provides a way for objects to be defined so it is possible to iterate through a list of items,
with, for example a foreach statement. By default, all visible properties will be used for the
iteration.

Example #1 Simple Object Iteration

<?php
class MyClass
{
public $var1 = 'value 1';
public $var2 = 'value 2';
public $var3 = 'value 3';

protected $protected = 'protected var';


private $private = 'private var';

function iterateVisible() {
echo "MyClass::iterateVisible:\n";
foreach($this as $key => $value) {
print "$key => $value\n";
}
}
}

$class = new MyClass();

foreach($class as $key => $value) {


print "$key => $value\n";
}
echo "\n";

$class->iterateVisible();

?>

The above example will output:

var1 => value 1


var2 => value 2
var3 => value 3

MyClass::iterateVisible:
var1 => value 1
var2 => value 2
var3 => value 3
protected => protected var
private => private var

As the output shows, the foreach iterated through all visible variables that can be accessed. To
take it a step further you can implement one of PHP 5's internal interface named Iterator. This
allows the object to decide what and how the object will be iterated.

Example #2 Object Iteration implementing Iterator

<?php
class MyIterator implements Iterator
{
private $var = array();

public function __construct($array)


{
if (is_array($array)) {
$this->var = $array;
}
}

public function rewind() {


echo "rewinding\n";
reset($this->var);
}

public function current() {


$var = current($this->var);
echo "current: $var\n";
return $var;
}

public function key() {


$var = key($this->var);
echo "key: $var\n";
return $var;
}

public function next() {


$var = next($this->var);
echo "next: $var\n";
return $var;
}

public function valid() {


$var = $this->current() !== false;
echo "valid: {$var}\n";
return $var;
}
}

$values = array(1,2,3);
$it = new MyIterator($values);

foreach ($it as $a => $b) {


print "$a: $b\n";
}
?>

The above example will output:

rewinding
current: 1
valid: 1
current: 1
key: 0
0: 1
next: 2
current: 2
valid: 1
current: 2
key: 1
1: 2
next: 3
current: 3
valid: 1
current: 3
key: 2
2: 3
next:
current:
valid:

You can also define your class so that it doesn't have to define all the Iterator functions by
simply implementing the PHP 5 IteratorAggregate interface.

Example #3 Object Iteration implementing IteratorAggregate

<?php
class MyCollection implements IteratorAggregate
{
private $items = array();
private $count = 0;
// Required definition of interface IteratorAggregate
public function getIterator() {
return new MyIterator($this->items);
}

public function add($value) {


$this->items[$this->count++] = $value;
}
}

$coll = new MyCollection();


$coll->add('value 1');
$coll->add('value 2');
$coll->add('value 3');

foreach ($coll as $key => $val) {


echo "key/value: [$key -> $val]\n\n";
}
?>

The above example will output:

rewinding
current: value 1
valid: 1
current: value 1
key: 0
key/value: [0 -> value 1]

next: value 2
current: value 2
valid: 1
current: value 2
key: 1
key/value: [1 -> value 2]

next: value 3
current: value 3
valid: 1
current: value 3
key: 2
key/value: [2 -> value 3]

next:
current:
valid:

Patterns
Patterns are ways to describe best practices and good designs. They show a flexible solution to
common programming problems.

Factory

The Factory pattern allows for the instantiation of objects at runtime. It is called a Factory
Pattern since it is responsible for "manufacturing" an object. A Parameterized Factory receives
the name of the class to instantiate as argument.

Example #1 Parameterized Factory Method

<?php
class Example
{
// The parameterized factory method
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception ('Driver not found');
}
}
}
?>

Defining this method in a class allows drivers to be loaded on the fly. If the Example class was a
database abstraction class, loading a MySQL and SQLite driver could be done as follows:

<?php
// Load a MySQL Driver
$mysql = Example::factory('MySQL');

// Load a SQLite Driver


$sqlite = Example::factory('SQLite');
?>

Singleton

The Singleton pattern applies to situations in which there needs to be a single instance of a
class. The most common example of this is a database connection. Implementing this pattern
allows a programmer to make this single instance easily accessible by many other objects.

Example #2 Singleton Function

<?php
class Example
{
// Hold an instance of the class
private static $instance;
// A private constructor; prevents direct creation of object
private function __construct()
{
echo 'I am constructed';
}

// The singleton method


public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}

return self::$instance;
}

// Example method
public function bark()
{
echo 'Woof!';
}

// Prevent users to clone the instance


public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}

?>

This allows a single instance of the Example class to be retrieved.

<?php
// This would fail because the constructor is private
$test = new Example;

// This will always retrieve a single instance of the class


$test = Example::singleton();
$test->bark();

// This will issue an E_USER_ERROR.


$test_clone = clone $test;

?>

Magic Methods

The function names __construct, __destruct (see Constructors and Destructors), __call,
__callStatic, __get, __set, __isset, __unset (see Overloading), __sleep, __wakeup, __toString,
__set_state and __clone are magical in PHP classes. You cannot have functions with these
names in any of your classes unless you want the magic functionality associated with them.
Caution

PHP reserves all function names starting with __ as magical. It is recommended that you do not
use function names with __ in PHP unless you want some documented magic functionality.

__sleep and __wakeup

serialize() checks if your class has a function with the magic name __sleep. If so, that function is
executed prior to any serialization. It can clean up the object and is supposed to return an array
with the names of all variables of that object that should be serialized. If the method doesn't
return anything then NULL is serialized and E_NOTICE is issued.

The intended use of __sleep is to commit pending data or perform similar cleanup tasks. Also,
the function is useful if you have very large objects which do not need to be saved completely.

Conversely, unserialize() checks for the presence of a function with the magic name __wakeup.
If present, this function can reconstruct any resources that the object may have.

The intended use of __wakeup is to reestablish any database connections that may have been
lost during serialization and perform other reinitialization tasks.

Example #1 Sleep and wakeup

<?php
class Connection {
protected $link;
private $server, $username, $password, $db;

public function __construct($server, $username, $password, $db)


{
$this->server = $server;
$this->username = $username;
$this->password = $password;
$this->db = $db;
$this->connect();
}

private function connect()


{
$this->link = mysql_connect($this->server, $this->username, $this-
>password);
mysql_select_db($this->db, $this->link);
}

public function __sleep()


{
return array('server', 'username', 'password', 'db');
}

public function __wakeup()


{
$this->connect();
}
}
?>

__toString

The __toString method allows a class to decide how it will react when it is converted to a string.

Example #2 Simple example

<?php
// Declare a simple class
class TestClass
{
public $foo;

public function __construct($foo) {


$this->foo = $foo;
}

public function __toString() {


return $this->foo;
}
}

$class = new TestClass('Hello');


echo $class;
?>

The above example will output:

Hello

It is worth noting that before PHP 5.2.0 the __toString method was only called when it was
directly combined with echo() or print(). Since PHP 5.2.0, it is called in any string context (e.g. in
printf() with %s modifier) but not in other types contexts (e.g. with %d modifier). Since PHP
5.2.0, converting objects without __toString method to string would cause
E_RECOVERABLE_ERROR.

__set_state

This static method is called for classes exported by var_export() since PHP 5.1.0.

The only parameter of this method is an array containing exported properties in the form
array('property' => value, ...).

Example #3 Using __set_state (since PHP 5.1.0)


<?php

class A
{
public $var1;
public $var2;

public static function __set_state($an_array) // As of PHP 5.1.0


{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';

eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(


// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);

?>

The above example will output:

object(A)#2 (2) {
["var1"]=>
int(5)
["var2"]=>
string(3) "foo"
}

Final Keyword

PHP 5 introduces the final keyword, which prevents child classes from overriding a method by
prefixing the definition with final. If the class itself is being defined final then it cannot be
extended.

Example #1 Final methods example

<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}

class ChildClass extends BaseClass {


public function moreTesting() {
echo "ChildClass::moreTesting() called\n";
}
}
// Results in Fatal error: Cannot override final method
BaseClass::moreTesting()
?>

Example #2 Final class example

<?php
final class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}

// Here it doesn't matter if you specify the function as final or not


final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}

class ChildClass extends BaseClass {


}
// Results in Fatal error: Class ChildClass may not inherit from final class
(BaseClass)
?>

Object cloning

Creating a copy of an object with fully replicated properties is not always the wanted behavior. A
good example of the need for copy constructors, is if you have an object which represents a
GTK window and the object holds the resource of this GTK window, when you create a
duplicate you might want to create a new window with the same properties and have the new
object hold the resource of the new window. Another example is if your object holds a reference
to another object which it uses and when you replicate the parent object you want to create a
new instance of this other object so that the replica has its own separate copy.

An object copy is created by using the clone keyword (which calls the object's __clone() method
if possible). An object's __clone() method cannot be called directly.

$copy_of_object = clone $object;

When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties.
Any properties that are references to other variables, will remain references. If a __clone()
method is defined, then the newly created object's __clone() method will be called, to allow any
necessary properties that need to be changed.
Example #1 Cloning an object

<?php
class SubObject
{
static $instances = 0;
public $instance;

public function __construct() {


$this->instance = ++self::$instances;
}

public function __clone() {


$this->instance = ++self::$instances;
}
}

class MyCloneable
{
public $object1;
public $object2;

function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone $this->object1;
}
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();


$obj->object2 = new SubObject();

$obj2 = clone $obj;

print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

The above example will output:

Original Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 1
)
[object2] => SubObject Object
(
[instance] => 2
)

)
Cloned Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 3
)

[object2] => SubObject Object


(
[instance] => 2
)

Comparing objects

In PHP 5, object comparison is more complicated than in PHP 4 and more in accordance to
what one will expect from an Object Oriented Language (not that PHP 5 is such a language).

When using the comparison operator (==), object variables are compared in a simple manner,
namely: Two object instances are equal if they have the same attributes and values, and are
instances of the same class.

On the other hand, when using the identity operator (===), object variables are identical if and
only if they refer to the same instance of the same class.

An example will clarify these rules.

Example #1 Example of object comparison in PHP 5

<?php
function bool2str($bool)
{
if ($bool === false) {
return 'FALSE';
} else {
return 'TRUE';
}
}

function compareObjects(&$o1, &$o2)


{
echo 'o1 == o2 : ' . bool2str($o1 == $o2) . "\n";
echo 'o1 != o2 : ' . bool2str($o1 != $o2) . "\n";
echo 'o1 === o2 : ' . bool2str($o1 === $o2) . "\n";
echo 'o1 !== o2 : ' . bool2str($o1 !== $o2) . "\n";
}

class Flag
{
public $flag;

function Flag($flag = true) {


$this->flag = $flag;
}
}

class OtherFlag
{
public $flag;

function OtherFlag($flag = true) {


$this->flag = $flag;
}
}

$o = new Flag();
$p = new Flag();
$q = $o;
$r = new OtherFlag();

echo "Two instances of the same class\n";


compareObjects($o, $p);

echo "\nTwo references to the same instance\n";


compareObjects($o, $q);

echo "\nInstances of two different classes\n";


compareObjects($o, $r);
?>

You might also like