JJHH
JJHH
Marcus Börger
PHP|tek 2006
Overview
; What is OOP?
; Encapsulation
; Inheritance
; Polymorphism
; This promotes
; Extensibility
; Reusability
; Code Consolidation
; Abstraction
; Responsibility
function foo_to_xml($foo) {
// generic stuff
// foo-specific stuff
}
function bar_to_xml($bar) {
// generic stuff
// bar specific stuff
}
foreach($entries as $entry) {
switch($entry[’type’]) {
case 'professional':
display_professional_entry($entry);
break;
case 'personal':
display_personal_entry($entry);
break;
}
}
foreach($entries as $entry) {
$entry->display();
}
<?php
$obj $ref $dup
class Object {};
Instance 1 Instance 2
$obj = new Object();
$ref = $obj;
Class Object
$dup = clone $obj;
?>
<?php
class Object {
function __construct() {}
function __destruct() {}
}
$obj = new Object();
unset($obj);
?>
Marcus Börger Master OOP in PHP 5 25
Constructors and Destructors
; Parents must be called manually
<?php
class Base {
function __construct() {}
function __destruct() {}
}
class Object extends Base {
function __construct() {
parent::__construct();
}
function __destruct() {
parent::__destruct();
}
}
$obj = new Object();
unset($obj);
?>
<?php
$obj1 $obj2
class Object {
var $prop = "Hello\n";
} Instance 1 Instance 2
$prop $prop
$obj1 = new Object;
$obj1->prop = "Hello World\n";
Class Object
$obj2 = new Object;
$prop/default
echo $obj2->prop; // Hello
?>
Marcus Börger Master OOP in PHP 5 27
Static members
; Static methods and properties
; Bound to the class not to the object
; Only exists once per class rather than per instance
; Can be initialized
$obj1 $obj2
<?php
class Object {
var $prop;
static $stat = "Hello\n"; Instance 1 Instance 2
static function test() { $prop $prop
echo self::$stat;
}
}
Object::test(); Class Object
$obj1 = new Object; $stat
$obj2 = new Object;
?>
<?php
class Base { Derived
public $a;
protected $b; Base
private $c; $a
} $b
class Derived extends Base { $c
public $a;
public $b; $a
private $c; $b
} $c
?> Base::$c
class Base {
protected function __construct() {
}
}
class Derived extends Base {
// constructor is still protected
static function getBase() {
return new Base; // Factory pattern
}
}
class Three extends Derived {
public function __construct() {
}
}
Marcus Börger Master OOP in PHP 5 31
Clone visibility
; A protected __clone prevents external cloning
class Base {
protected function __clone() {
}
}
class Derived extends Base {
public function __clone($that) {
// some object cloning code
}
public static function copyBase($that) {
return clone $that;
}
}
class Base {
private final function __clone() {
}
}
class Derived extends Base {
// public function __clone($that) {
// some object cloning code
// }
// public static function copyBase($that) {
// return clone $that;
// }
}
class Base {
const greeting = "Hello\n";
}
echo Base::greeting;
echo Derived::greeting;
Derived::func();
class Base {
final function invariant() { echo "Hello\n"; }
}
class Line {
function draw() {};
}
class Polygon {
protected $lines; Line Ellipse
function draw() {
foreach($this->lines as $line)
$line->draw();
} $lines
}
class Rectangle extends Polygon { Polygon Circle
function draw() {};
}
class Ellipse {
function draw() {};
}
class Circle extends Ellipse { Rectangle
function draw() {
parent::draw();
}
}
; Virtual properties
; Handled by interceptor methods
; Static properties
; Bound to the class rather than to the instance
$o = new Object;
echo $o;
class Object {
protected $virtual = array();
function __get($name) {
return @$this->virtual[$name];
}
function __set($name, $value) {
$this->virtual[$name] = $value;
}
function __unset($name, $value) {
unset($this->virtual[$name]);
}
function __isset($name, $value) {
return isset($this->virtual[$name]);
}
function __call($func, $params) {
echo 'Could not call ' . __CLASS__ . '::' . $func . "\n";
}
}
Marcus Börger Master OOP in PHP 5 42
Typehinting
; PHP 5 allows to easily force a type of a parameter
; PHP does not allow NULL for typehints
; Typehints must be inherited as given in base class
; PHP 5.1 offers typehinting with arrays
; PHP 5.2 offers optional typhinted parameters (= NULL)
class Object {
public function compare(Object $other) {
// Some code here
}
public function compare2($other) {
if (is_null($other) || $other instanceof Object) {
// Some code here
}
}
}
<?php
function __autoload($class_name)
{
require_once(
dirname(__FILE__) . '/' . $class_name . '.p5c');
}
?>
<?php
spl_autoload_register('spl_autoload');
if (function_exists('__autoload')) {
spl_autoload_register('__autoload');
}
?>
<?php
try {
// your code
throw new Exception();
}
catch (Exception $e) {
// exception handling
}
?>
<?php
class Object
{
function __construct( & $failure)
{
$failure = true;
}
}
$error = false;
$o = new Object($error);
if (!$error) {
// error handling, NOTE: the object was constructed
unset($o);
}
?>
Marcus Börger Master OOP in PHP 5 54
Constructor failure
; In 5 constructors do not return the created object
; Exceptions allow to handle failed constructors
<?php
class Object
{
function __construct()
{
throw new Exception;
}
}
try {
$o = new Object;
}
catch (Exception $e) {
echo "Object could not be instantiated\n";
}
?>
Marcus Börger Master OOP in PHP 5 55
Convert Errors to Exceptions
; Implementing PHP 5.1 class ErrorException
<?php
if (!class_exists(' ErrorException', false)) {
class ErrorException extends Exception
{
protected $severity;
function __construct($msg,$code,$errno,$file,$line)
{
parent::__construct($msg, $code);
$this->severity = $errno;
$this->file = $file;
$this->line = $line;
}
function getSeverity() {
return $this->severity;
}
}
}
?>
set_error_handler('ErrorsToExceptions');
?>
<html><body>
<?php
$ok = false;
$db = new PDO('CONNECTION');
if ($db) {
$res = $db->query('SELECT data');
if ($res) {
$res2 = $db->query('SELECT other');
if ($res2) {
// handle data
$ok = true; // only if all went ok
}
}
}
if (!$ok) echo '<h1>Service currently unabvailable</h1>';
?>
</body></html>
<html><body>
<?php
try {
$db = new PDO('CONNECTION');
$db->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
$res = $db->query('SELECT data');
$res2 = $db->query('SELECT other');
// handle data
}
catch (Exception $e) {
echo '<h1>Service currently unabvailable</h1>';
error_log($e->getMessage());
}
?>
</body></html>
Marcus Börger Master OOP in PHP 5 59
SPL Exceptions
; SPL provides a standard set of exceptions
; Class Exception must be the root of all exceptions
; RuntimeException
; Length exceeded
class Foo {
public $prop;
function Func($name) {
echo "Hello $name";
}
}
ReflectionClass::export('Foo');
ReflectionObject::export(new Foo);
ReflectionMethod::export('Foo', 'func');
ReflectionProperty::export('Foo', 'prop');
ReflectionExtension::export('standard');
class Test {
function __construct($x, $y = NULL) {
$this->x = $x;
$this->y = $y;
}
}
function new_object_array($cls, $args = NULL) {
return call_user_func_array(
array(new ReflectionClass($cls),'newInstance'),
$args);
}
new_object_array('stdClass');
new_object_array('Test', array(1));
new_object_array('Test', array(1, 2));
; Use CLI:
php --re SPL
php --rc ArrayAccess
Marcus Börger Master OOP in PHP 5 75
ArrayAccess
; Allows for creating objects that can be
transparently accessed by array syntax.
; When combined with the iterator interface, it
allows for creating ‘arrays with special properties’.
interface ArrayAccess {
// @return whether $offset is valid (true/false)
function offsetExists($offset);
class Object {
public $prop1 = "Hello ";
public $prop2 = "World\n";
}
?>
; Iterators
; only know one element at a time
; only require memory for the current element
; forward access only
; Access done by method calls
; Containers
; require memory for all elements
; allow to access any element directly
; can create external Iterators or are internal Iterators
Marcus Börger Master OOP in PHP 5 86
The basic concepts
; Iterators can be internal or external
also referred to as active or passive
Iterator
IteratorAggregate
+ rewind () : void
+ valid () : boolean
+ getIterator () : Iterator + current () : mixed
+ key () : mixed
+ next () : void
Iterator
IteratorAggregate
+ rewind () : void
+ valid () : boolean
+ getIterator () : Iterator + current () : mixed
+ key () : mixed
+ next () : void
IteratorImpl
AggregateImpl
+ <<Implement>> rewind () : void
+ <<Implement>> valid () : boolean
+ <<Implement>> getIterator () : Iterator + <<Implement>> current () : mixed
+ <<Implement>> key () : mixed
+ <<Implement>> next () : void
<?php
$o = new ArrayIterator(array(1, 2, 3));
$o->rewind();
while ($o->valid()) {
$key = $o->key();
$val = $o->current();
// some code
$o->next();
}
?>
<?php
$o = new ArrayIterator(array(1, 2, 3));
foreach($o as $key => $val) {
// some code
}
?>
<?php
$it = get_resource();
foreach(new
for ($it->rewind();
Filter($it,
$it->valid();
$filter_param)
$it->next())
as $key=>$val)
{ {
//
$value
access
= $it->current();
filtered data only $key = $it->key();
}
?>
Marcus Börger Master OOP in PHP 5 91
Debug Session
<?php <?php
class ArrayIterator { PHP 5.1 $a = array(1, 2, 3);
protected $ar; $o = new ArrayIterator($a);
function __construct(Array $ar) { foreach($o as $key => $val) {
$this->ar = $ar; echo "$key => $va\n";
} }
function rewind() { ?>
rewind($this->ar);
}
fucntion valid() { 0 => 1
return !is_null(key($this->ar)); 1 => 2
} 2 => 3
function key() {
return key($this->ar);
}
fucntion current() {
return current($this->ar);
}
function next() {
next($this->ar);
}
}
?>
What about:
; Buffered result sets
; Lazy Initialization
; Directories
<?php
class KeyFilter extends FilterIterator
{
private $rx;
function __construct(Iterator $it, $regex) {
parent::__construct($it);
$this->rx = $regex;
}
function accept() {
return ereg($this->rx,$this->getInnerIterator()->key());
}
function getRegex() {
return $this->rx;
}
protected function __clone($that) {
// disallow clone
}
}
?>
; A name
; Iterator Pattern
; Factory Pattern
foreach($entries as $entry) {
$entry->display();
}
function attach($obj) {
foreach($this->storage as $o) {
if ($o === $obj) return;
}
$this->storage[] = $obj;
}
function detatch($obj) {
foreach($this->storage as $k => $o) {
if ($o === $obj) {
unset($this->storage[$k]);
return;
}
}
}
}
Marcus Börger Master OOP in PHP 5 109
Observer Pattern
Implementation
class MySubject implements Subject {
protected $observers;
public function __construct() {
$this->observer = new ObjectStorage;
}
public function attach(Observer $o) {
$this->observers->attach($o);
}
public function detach(Observer $o) {
$this->observers->detach($o);
}
public function notify() {
foreach($this->observers as $o) $o->update($this);
}
}
class MyObserver implements Observer {
public function update(Subject $s) {
// do logging or some other action
}
}
; Concrete Examples: logging facilities: email,
debugging, SOAP message notifications.
Marcus Börger Master OOP in PHP 5 110
Reference
; Everythining about PHP
http://php.net
; These slides
http://talks.somabo.de
; SPL Documentaion & Examples
http://php.net/~helly/php/ext/spl
http://cvs.php.net/php-src/ext/spl/examples
http://cvs.php.net/php-src/ext/spl/internal
; George Schlossnagle
Advanced PHP Programming
; Andi Gutmans, Stig Bakken, Derick Rethans
PHP 5 Power Programming