Advance
OOP in PHP
OVERLOADING
• PHP Overloading can be broken down into two basic
components
• Method overloading
• Property overloading
• Overloading in PHP provides the means to dynamically
create members and methods via set of "magical" methods
• Invoked with interacting with members or methods that have
not been declared or are not visible in the current scope
• All of the magic methods must be declared as public
• None of the magic functions can be called with arguments,
passed by reference
OVERLOADING
• All overloading methods are invoked when accessing variable or
method that is not declared or is inaccessible
• __set($index, $value) – when writing (property
overloading)
• __get ($name) –when reading (property overloading)
• __call ($name, $arguments) - when calling a
method
OVERLOADING
• PHP "overloading" is a lot different from most
languages "overloading"
• Usually it means the ability to declare two methods
with different sets of parameters but same names
• Normally no property overloading
EXAMPLE
(METHOD OVERLOADING)
<?php • <?php
class MyClass{ class MyClass{
public function foo() {
public function foo() {
return "This is the foo function";
} return "This is the foo function";
}
} /*** __call() method with two args ***/
public function __call($method, $arg){
// create a new class object
echo $method.'<br />';
$obj = new MyClass;
$obj->bar(); print_r($arg);
?> }
}
$obj = new MyClass;
/*** call a non-existant method ***/
$obj->bar("arg1", "arg2");
5
?>
EXAMPLE (METHOD
<?php
OVERLOADING)
class readyGetSet {
private $item = 'Skate Board';
private $price = 100;
function __call($method, $arguments){
/*** set property and prefix ***/
$prefix = strtolower(substr($method, 0, 3));
$property = strtolower(substr($method, 3));
if (empty($prefix) || empty($property))
{
return;
}
if ($prefix == 'get' && isset($this->$property))
{
return $this->$property;
}
if ($prefix == 'set')
{
$this->$property = $arguments[0];
}
}
}
$obj = new readyGetSet; 6
echo 'Item: ' . $obj->getItem() . '<br />';
echo 'Price: ' . $obj->getPrice() . '<br />';
EXAMPLE (PROPERTY
OVERLOADING)
<?php <?php
class candy{
class candy{ public $type='chocolate';
/*** declare a property ***/ public $choctype = array('milk'=>0, 'dark'=
public $type='chocolate'; >1, 'plain'=>2);
public function wrap(){
/*** a normal method ***/ echo 'Its a wrap';
public function wrap(){ }
echo 'Its a wrap'; public function __get($index){
echo 'Retrieving element of $choctype pr
}
operty with index of '.$index.'<br />';
/*** our __set() function ***/ return $this->choctype[$index];
public function __set($index, $value){ }
echo 'The value of '.$index.' is '.$value;
} /*** end of class ***/
}
/*** a new candy object ***/
} /*** end of class ***/ $candy = new candy;
/*** set a non existant property ***/
7
echo 'The value of the following element pr
/*** a new candy object ***/ operty is '.$candy->milk;
$candy = new candy;
OBJECT ITERATION
• PHP provides a way for object to be iterated trough as a list of
items (array)
• foreach can be used
• By default iterates all visible properties
OBJECT ITERATION –
EXAMPLE
class A {
public $var1 = 1;
public $var2 = 2;
protected $var3 = 3;
private $var4 = 4;
function printIteration () {
foreach ($this as $key=>$val)
echo "$key : $val\n";
}
}
$obj = new A();
// this prints only the public properties
foreach ($obj as $key=>$val)
echo "$key : $val \n";
// this prints protected and private too
$obj->printIteration ();
OBJECT CLONING
• An object can be cloned with the clone keyword
$obj1 = new A();
$obj2 = clone $obj1;
• This will create new independent object
• Creating a copy of an object with fully replicated properties is not
always the wanted behavior
OBJECT CLONING
• A class can implement the magic method __clone
which is called for the newly created object
• Called "clone constructor"
• Allows necessary changes to be done on the newly
created object
• Example: Object holding reference to resource – the
new object must have new references, instead of
copies
• Example: Object holding reference to another object
that must not be copied
OBJECT CLONING
EXAMPLE
class A {
private $fileName;
private $fp = null;
public function open ($file) {
$this->fileName = $file;
$this->fp = fopen ($file, 'r');
}
public function close () {
if ($this->fp) {
fclose($this->fp);
$this->fp = null;
}
}
public function __clone () {
// reopen the file for the new object
if ($this->fp)
$this->fp= fopen($this->file, 'r');
}
}
SERIALIZING OBJECTS
• Serializing is the process of transforming an object into a string, that
can be stored
• This string can be used to restore the object
• Useful for storing objects in session data
• Saves only properties values and class names – no methods
• PHP provides the serialize and unserialize functions
SERIALIZING OBJECTS
• serialize ($object) – returns string, representing the object
• unserialize ($string) – returns new object, that is restored from
the serialized string
• unserialize requires the class to be defined before calling it
SERIALIZING OBJECT –
EXAMPLE
class A {
public $var;
public function myPrint () { echo $this->var; }
}
$obj = new A;
$obj->var = 10;
$data = serialize ($obj);
// store $data in a file
file_put_contents ('data.dat', $data);
// …
// in a new page:
$data = file_get_contents ('data.dat');
$obj = unserialize ($data);
$obj->myPrint (); // prints 10
SERIALIZING METHODS
• Before serializing and after unserializing PHP checks if
the class has the magic methods __sleep and
__wakeup
• __sleep allows the class to commit pending data,
cleanup or define what needs to be stored if the
object is very large
• Should return array with names of properties to be
stored
• __wakeup allows the class to restore connections or
other re-initialization
__SLEEP AND __WAKEUP
class Connection {
protected $link;
private $server, $user, $pass, $db;
public function __construct($server, $user,
$pass, $db) {
$this->server = $server;
$this->user = $user;
$this->pass = $pass;
$this->db = $db;
$this->connect();
}
private function connect () {
$this->link = mysql_connect (
$this->server, $this->user,
$this->pass);
mysql_select_db($this->db, $this->link);
}
// continues on next slide
__SLEEP AND __WAKEUP
// continues from previous slide
public function __sleep () {
// skip serializing $link
return array ('server', 'user',
'pass', 'db');
}
public function __wakeup () {
$this->connect();
}
}
NAMESPACES
• Namespaces in PHP are designed to resolve scope
problems in large PHP libraries
• Simplify development in object oriented
environment
• Clears the code – no long classes names
• In PHP all classes declarations are global
• Namespaces allow to have two classes with
same name
• Old approach was adding prefixes to class names
(Like the mysql_* functions)
• Available since PHP 5.3
NAMESPACE DEFINITION
• Namespaces are declared with the namespace keyword
• Should be always in the beginning of the file
<?
namespace Project;
class MyTemplate { … }
function print_headers () { … }
…
?>
• Namespace can contain classes, constants, functions but
no free code
NAMESPACES
• Classes, function and etc. in a namespace are automatically
prefixed with the name of the namespace
• So in the example we would use Project::MyTemplate to access
the class
• Constants in namespaces are defined with const keyword, not with
define
NAMESPACES – EXAMPLE
// file Project.php
namespace Project;
// declare base classes and etc.
…
// file project/db.php;
namespace Project::DB;
// declare DB interface for work with database
…
// file project/db/mysql.php
namespace Project::DB::MySQL;
// implement the DB interface for mysql
…
// file project/db/oracle.php
Namespace Project::DB::Oracle;
// implement the DB interface for Oracle
…
// somewhere in the project
require "project/db/mysql.php";
$a = new Project::DB::MySQL::Connection();
Project::DB::MySQL::connect();
USING NAMESPACES
• The use operator allows aliasing namespaces
names
use Project::DB::MySQL as DBLink;
$x = new DBLink::Connection();
DBLink::connect();
• If new name is not specified the namespace is
imported in the current context (global
namespace)
use Project::DB::MySQL;
$x = new MySQL::Connection();
MySQL::connect();
• Even if aliased, every class and function can be
accessed at any time by full name
AUTOLOADING CLASSES
• Usually every class is declared in separate file
• In big object oriented projects on every page you may have to
include dozens of files
• You can define __autoload function that is called when trying
to access class that is not defined
• It can include the necessary file for the class
AUTOLOAD EXAMPLE
<?
function __autoload ($class_name) {
$name = "includes/".$class_name.".inc.php";
if (file_exists ($name))
include $name;
else
echo 'Class not found';
}
?>
• Exceptions, thrown in __autoload cannot be caught and
result in fatal error
LIMITATION OF SELF::
• Example:
class A {
public static function whoami () {
echo __CLASS__;
}
public static function test () {
self::whoami();
}
}
class B extends A {
public static function whoami () {
echo __CLASS__;
}
}
B::test(); // outputs 'A' ?!
LATE STATIC BINDING
• PHP 5.3 introduces the late static binding which allows to
reference the called class in context of static
• In practice – this adds static:: scope
• So if in the above example we use static::whoami() in the
test() method body we get output 'B'