100% found this document useful (2 votes)
3K views499 pages

PHP - Classes and Objects - Manual

xx
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
100% found this document useful (2 votes)
3K views499 pages

PHP - Classes and Objects - Manual

xx
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 499

[edit] Last updated: Sat, 16 Jun 2012

Classes and Objects


Table of Contents
Introduction
The Basics
Properties
Class Constants
Autoloading Classes
Constructors and Destructors
Visibility
Object Inheritance
Scope Resolution Operator (::)
Static Keyword
Class Abstraction
Object Interfaces
Traits
Overloading
Object Iteration
Magic Methods
Final Keyword
Object Cloning
Comparing Objects
Type Hinting
Late Static Bindings
Objects and references
Object Serialization
OOP Changelog

User Contributed Notes

Classes and Objects

wbcarts at juno dot com 22-May-2012 05:00


PHP Class TERMINOLOGY
If you find that your code lacks structure, organization, and/or is hard to maintain... PHP Classes may be what you need. But
first, some terminology -- terms are in UPPERCASE:
<?php
class MyClass
{
// This is the CLASS DEFINITION (everything in the curly brackets).
// $myVar is DECLARED, but it is not INITIALIZED (assigned a value).
protected $myVar;

public function __construct($value = 'What?')


{
$this->setMyVar($value); // $myVar will now be INITIALIZED
}
public function setMyVar($value)
{
if(!is_string($value))
{
$value = (string)'Non-String type passed in argument';
}
$this->myVar = $value;
}
}
?>
The class definition is like a blueprint. Imagine an architect who goes to the job site carrying a big roll of papers with
drawings on them. Those drawings represent a design which is meant 'to be built', and they are used throughout the entire
construction process. Once the project is done, then people occupy the buliding and commense their work. One crucial difference
between a CLASS DEFINITION and a blueprint though is, that a class definition does say what does and what doesn't go on with
the project after it is designed and built.
We have a CLASS DEFINITON at this stage -- PHP is happy -- but it does nothing for us yet. We need to INSTANTIATE (make real
MyClass object(s)) and have those INSTANCE(S) follow the design and rules outlined in the CLASS DEFINITION.
<?php
// INSTANTIATE (to build or create) objects with the 'new' operator.
$mc1 = new MyClass(); // $mc1 is now an INSTANCE (built or created, materialized).
$mc2 = new MyClass('Hello World'); // $mc2 is now an INSTANCE (built or created, materialized).
$mc3 = new MyClass('Take that!'); // $mc3 is now an INSTANCE (built or created, materialized).
$mc4 = new MyClass(true); // $mc4 is now an INSTANCE (built or created, materialized).
?>
Now it is time to put the INSTANCES to work. According to our CLASS DEFINITION, all we can do is set the value of $myVar with
the setMyVar() function.
<?php
$mc1->setMyVar(''); // Ok
$mc2->setMyVar(''); // Ok
$mc3->setMyVar(''); // Ok
$mc4->setMyVar(''); // Ok
?>
Try putting a non INSTANCE to work:
<?php
$youTrickyLittleBitch->setMyVar('You like that?');
?>
That throws: 'Fatal error: Call to a member function setMyVar() on a non-object'. This means that the variable was not
INSTANTIATED with the proper CLASS DEFINITON, therefore it is not an INSTANCE of that class, therefore illegal to even try.

dances_with_peons at live dot com 18-Jan-2011 02:36


As of PHP 5.3, $className::funcName() works fine.
<?php
class test
{
public static function run() { print "Works\n"; }
}
$className = 'test';
$className::run();
?>
on my system, prints "Works". May work with earlier versions of PHP as well. Even if it doesn't, there's always
<?php
$className = 'test';
call_user_func(array($className, 'run'));
?>
The point is, there's no need for eval.

dances_with_peons at live dot com 18-Jan-2011 02:30


As of PHP 5.3, $className::funcName() works fine.
<?php
class test
{
public static function run() { print "Works\n"; }
}
$className = 'test';
$className::run();
?>
on my system, prints "Works". It may work with earlier versions of PHP as well.

corpus-deus at softhome dot net 26-Nov-2010 08:27


With regards to Singleton patterns (and variable class names) - try:
<?php
class MyClass {
// singleton instance
private static $instance;
// private constructor function
// to prevent external instantiation
private __construct() { }
// getInstance method

public static function getInstance() {


if(!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
//...
}
?>

suleman dot saleh at gmail dot com 25-Oct-2010 11:41


Using php abstract classes we must have to implement all their functions in child classes other wise it will make automatically
child class as a concrete

DavMe 01-Oct-2010 12:03


When you have a class name in a variable and want to create a new instance of that class, you can simply use:
<?php
$className = "ClassName";
$instance = new $className();
?>
If, however, you have a class that is part of a singleton pattern where you cannot create it with new and need to use:
<?php
$instance = ClassName::GetInstance();
?>
...you quickly discover that it fails miserably with a variable.
Fail Example:
<?php
$className = "ClassName";
$instance = $className::GetInstance();
?>
After a few days of head pounding, I finally put together this workaround:
<?php
$className = "ClassName";
eval('$instance = '.$className.'::GetInstance();');
?>
I hope this saves you some effort and if anyone knows of a non-eval method to accomplish this, please share!
Thanks!

midir 02-Mar-2009 07:40


There are a couple of tricks you can do with PHP's classes that programmers from C++, etc., will find very peculiar, but which
can be useful.
You can create instances of classes without knowing the class name in advance, when it's in a variable:
<?php

$type = 'cc';
$obj = new $type; // outputs "hi!"
class cc {
function __construct() {
echo 'hi!';
}
}
?>
You can also conditionally define them by wrapping them in if/else blocks etc, like so:
<?php
if (expr) {
class cc {
// version 1
}
} else {
class cc {
// version 2
}
}
?>
It makes up for PHP's lack of preprocessor directives. The caveat is that the if/else code body must have been executed before
you can use the class, so you need to pay attention to the order of the code, and not use things before they're defined.

redrik at gmail dot com 31-Dec-2008 01:08


Maybe someone will find these classes, which simulate enumeration, useful.
<?php
class Enum {
protected $self = array();
public function __construct( /*...*/ ) {
$args = func_get_args();
for( $i=0, $n=count($args); $i<$n; $i++ )
$this->add($args[$i]);
}

public function __get( /*string*/ $name = null ) {


return $this->self[$name];
}

public function add( /*string*/ $name = null, /*int*/ $enum = null ) {


if( isset($enum) )
$this->self[$name] = $enum;
else
$this->self[$name] = end($this->self) + 1;
}
}
class DefinedEnum extends Enum {
public function __construct( /*array*/ $itms ) {
foreach( $itms as $name => $enum )
$this->add($name, $enum);

}
}
class FlagsEnum extends Enum {
public function __construct( /*...*/ ) {
$args = func_get_args();
for( $i=0, $n=count($args), $f=0x1; $i<$n; $i++, $f *= 0x2 )
$this->add($args[$i], $f);
}
}
?>
Example usage:
<?php
$eFruits = new Enum("APPLE", "ORANGE", "PEACH");
echo $eFruits->APPLE . ",";
echo $eFruits->ORANGE . ",";
echo $eFruits->PEACH . "\n";
$eBeers = new DefinedEnum("GUINESS" => 25, "MIRROR_POND" => 49);
echo $eBeers->GUINESS . ",";
echo $eBeers->MIRROR_POND . "\n";
$eFlags = new FlagsEnum("HAS_ADMIN", "HAS_SUPER", "HAS_POWER", "HAS_GUEST");
echo $eFlags->HAS_ADMIN . ",";
echo $eFlags->HAS_SUPER . ",";
echo $eFlags->HAS_POWER . ",";
echo $eFlags->HAS_GUEST . "\n";
?>
Will output:
1, 2, 3
25, 49
1,2,4,8 (or 1, 10, 100, 1000 in binary)

Jeffrey 08-Oct-2008 11:51


Why should anyone learn what classes and objects are? The short answer is to clarify and simplify code. Take this regular
script:
<?php
$item_name = 'Widget 22';
$item_price = 4.90;
$item_qty = 2;
$item_total = ($item_price * $item_qty);
echo "You ordered $item_qty $item_name @ \$$item_price for a total of: \$$item_total.";
?>
You ordered 2 Widget 22 @ $4.9 for a total of: $9.8.
You can see clearly that you have to "define and set" the data, "perform a calculation", and explicitly "write" the results for a total of 5 written statements. But the more you look at it, the more it needs fixin'. If you attempt to do that, your
code can get really ugly, really fast - and remember, this is just a simple script! Here's the same program in OOP with all
the fixin's:
<?php
class Item {
protected $name, $price, $qty, $total;
public function __construct($iName, $iPrice, $iQty) {
$this->name = $iName;

$this->price = $iPrice;
$this->qty = $iQty;
$this->calculate();
}
protected function calculate() {
$this->price = number_format($this->price, 2);
$this->total = number_format(($this->price * $this->qty), 2);
}
public function __toString() {
return "You ordered ($this->qty) '$this->name'" . ($this->qty == 1 ? "" : "s") .
" at \$$this->price, for a total of: \$$this->total.";
}
}
echo (new Item("Widget 22", 4.90, 2));
?>
You ordered (2) 'Widget 22's at $4.90, for a total of: $9.80.
By loading class Item (which houses all the improvements we made over the first script) into PHP first, we went from having to
write 5 statements in the first script, to writing only 1 statement "echo new Item" in the second.

Jason 07-Jul-2008 10:34


For real quick and dirty one-liner anonymous objects, just cast an associative array:
<?php
$obj = (object) array('foo' => 'bar', 'property' => 'value');
echo $obj->foo; // prints 'bar'
echo $obj->property; // prints 'value'
?>
... no need to create a new class or function to accomplish it.

ranema at ubuntu dot polarhome dot com 30-Mar-2008 07:49


Sometimes you just forget to close handles, links, etc and sometimes you are just lazy to do that. PHP 5 OOP can do it
automatically by using destructors:
<?php
class MySqlDriver {
private $_Link;
public function __construct( <...> ) {
$this->_Link = mysql_connect( <...> );
}
// this will be called automatically at the end of scope
public function __destruct() {
mysql_close( $this->_Link );
}
}

$_gLink = new MySqlDriver( <...> );


// and you don't need to close the link manually
?>

osculabond at gmail dot com 06-Oct-2006 11:20


A better way to simulate an enum in php5:
<?php
final class Days {
const Sunday = 0x00000001;
const Monday = 0x00000010;
const Tuesday = 0x00000100;
const Wednesday = 0x00001000;
const Thursday = 0x00010000;
const Friday = 0x00100000;
const Saturday = 0x01000000;
const Unknown = 0x00000000;
// ensures that this class acts like an enum
// and that it cannot be instantiated
private function __construct(){}
}
?>
This will allow you to do things like:
<?php
$day_to_email = Days::Thursday;
if($day_to_email == Days::Wednesday) echo "Wednesday<br />";
if($day_to_email == Days::Thursday) echo "Thursday<br />";
if($day_to_email == Days::Friday) echo "Friday<br />";
?>
Which would output:
Thursday
Or if you wanted to get a little fancier you could also do the following:
<?php
$days_to_email = Days::Monday | Days::Wednesday | Days::Friday;
if($days_to_email & Days::Monday) echo "Monday<br />";
if($days_to_email & Days::Tuesday) echo "Tuesday<br />";
if($days_to_email & Days::Wednesday) echo "Wednesday<br />";
if($days_to_email & Days::Thursday) echo "Thursday<br />";
if($days_to_email & Days::Friday) echo "Friday<br />";
?>
Which would output:
Monday
Wednesday
Friday

S b. 27-May-2005 09:50
We can't create easily anonymous objects like in JavaScript.

JS example :
var o = {
aProperty : "value",
anotherProperty : [ "element 1", "element 2" ] } ;
alert(o.anotherProperty[1]) ; // "element 2"
So I have created a class Object :
<?php
class Object {
function __construct( ) {
$n = func_num_args( ) ;
for ( $i = 0 ; $i < $n ; $i += 2 ) {
$this->{func_get_arg($i)} = func_get_arg($i + 1) ;
}
}
}
$o = new Object(
'aProperty', 'value',
'anotherProperty', array('element 1', 'element 2')) ;
echo $o->anotherProperty[1] ; // "element 2"
?>
You must feel free to make it better :)

spam at afoyi dot com 20-Mar-2005 05:18


You can call a function defined in an inherited class from the parent class. This works in both PHP 4.3.6 and 5.0.0:
<?php
class p {

function p() {
print "Parent's constructor\n";
}

function p_test() {
print "p_test()\n";
$this->c_test();
}
}
class c extends p {

function c() {
print "Child's constructor\n";
parent::p();
}

function c_test() {
print "c_test()\n";
}
}
$obj = new c;
$obj->p_test();

?>
Outputs:
Child's constructor
Parent's constructor
p_test()
c_test()

farzan at ifarzan dot com 05-Oct-2004 04:04


PHP 5 is very very flexible in accessing member variables and member functions. These access methods maybe look unusual and
unnecessary at first glance; but they are very useful sometimes; specially when you work with SimpleXML classes and objects. I
have posted a similar comment in SimpleXML function reference section, but this one is more comprehensive.
I use the following class as reference for all examples:
<?php
class Foo {
public $aMemberVar = 'aMemberVar Member Variable';
public $aFuncName = 'aMemberFunc';

function aMemberFunc() {
print 'Inside `aMemberFunc()`';
}
}
$foo = new Foo;
?>
You can access member variables in an object using another variable as name:
<?php
$element = 'aMemberVar';
print $foo->$element; // prints "aMemberVar Member Variable"
?>
or use functions:
<?php
function getVarName()
{ return 'aMemberVar'; }
print $foo->{getVarName()}; // prints "aMemberVar Member Variable"
?>
Important Note: You must surround function name with { and } or PHP would think you are calling a member function of object
"foo".
you can use a constant or literal as well:
<?php
define(MY_CONSTANT, 'aMemberVar');
print $foo->{MY_CONSTANT}; // Prints "aMemberVar Member Variable"
print $foo->{'aMemberVar'}; // Prints "aMemberVar Member Variable"
?>

You can use members of other objects as well:


<?php
print $foo->{$otherObj->var};
print $foo->{$otherObj->func()};
?>
You can use mathods above to access member functions as well:
<?php
print $foo->{'aMemberFunc'}(); // Prints "Inside `aMemberFunc()`"
print $foo->{$foo->aFuncName}(); // Prints "Inside `aMemberFunc()`"
?>

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Introduction
Starting with PHP 5, the object model was rewritten to allow for better performance and more features. This was
a major change from PHP 4. PHP 5 has a full object model.
Among the features in PHP 5 are the inclusions of visibility, abstract and final classes and methods, additional
magic methods, interfaces, cloning and typehinting.
PHP treats objects in the same way as references or handles, meaning that each variable contains an object
reference rather than a copy of the entire object. See Objects and References

Tip
See also the Userland Naming Guide.

User Contributed Notes

Introduction

There are no user contributed notes for this page.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

The Basics
class
Basic class definitions begin with the keyword class, followed by a class name, followed by a pair of curly
braces which enclose the definitions of the properties and methods belonging to the class.
The class name can be any valid label which is a not a PHP reserved word. A valid class name starts with a
letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it
would be expressed thus: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.
A class may contain its own constants, variables (called "properties"), and functions (called "methods").
Example #1 Simple Class definition
<?php
classSimpleClass
{
//propertydeclaration
public$var='adefaultvalue';
//methoddeclaration
publicfunctiondisplayVar(){
echo$this->var;
}
}
?>

The 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 possibly another object, if
the method is called statically from the context of a secondary object).
Example #2 Some examples of the $this pseudo-variable
<?php
classA
{
functionfoo()
{
if(isset($this)){
echo'$thisisdefined(';
echoget_class($this);
echo")\n";
}else{
echo"\$thisisnotdefined.\n";
}
}
}
classB
{
functionbar()
{
//Note:thenextlinewillissueawarningifE_STRICTisenabled.
A::foo();
}
}

$a=newA();
$a->foo();
//Note:thenextlinewillissueawarningifE_STRICTisenabled.
A::foo();
$b=newB();
$b->bar();
//Note:thenextlinewillissueawarningifE_STRICTisenabled.
B::bar();
?>

The above example will output:


$this
$this
$this
$this

is
is
is
is

defined (A)
not defined.
defined (B)
not defined.

new
To create an instance of a class, the new keyword must be used. An object will always be created 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).
If a string containing the name of a class is used with new, a new instance of that class will be created. If the
class is in a namespace, its fully qualified name must be used when doing this.
Example #3 Creating an instance
<?php
$instance=newSimpleClass();
//Thiscanalsobedonewithavariable:
$className='Foo';
$instance=new$className();//Foo()
?>

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.
Example #4 Object Assignment
<?php
$instance=newSimpleClass();
$assigned=$instance;
$reference=&$instance;
$instance->var='$assignedwillhavethisvalue';
$instance=null;//$instanceand$referencebecomenull

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

The above example will output:


NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
string(30) "$assigned will have this value"
}

PHP 5.3.0 introduced a couple of new ways to create instances of an object:


Example #5 Creating new objects
<?php
classTest
{
staticpublicfunctiongetNew()
{
returnnewstatic;
}
}
classChildextendsTest
{}
$obj1=newTest();
$obj2=new$obj1;
var_dump($obj1!==$obj2);
$obj3=Test::getNew();
var_dump($obj3instanceofTest);
$obj4=Child::getNew();
var_dump($obj4instanceofChild);
?>

The above example will output:


bool(true)
bool(true)
bool(true)

extends
A class can inherit the methods and properties of another class by using the keyword extends in the class
declaration. It is not possible to extend multiple classes; a class can only inherit from one base class.
The inherited methods and properties can be overridden by redeclaring them with the same name defined in the
parent class. However, if the parent class has defined a method as final, that method may not be overridden. It
is possible to access the overridden methods or static properties by referencing them with parent::.
When overriding methods, the parameter signature should remain the same or PHP will generate an
error. This does not apply to the constructor, which allows overriding with different parameters.

E_STRICT

level

Example #6 Simple Class Inheritance


<?php
classExtendClassextendsSimpleClass
{
//Redefinetheparentmethod
functiondisplayVar()
{
echo"Extendingclass\n";
parent::displayVar();
}
}
$extended=newExtendClass();
$extended->displayVar();
?>

The above example will output:


Extending class
a default value

User Contributed Notes

The Basics

ccheeboon at yahoo dot com 11-Jun-2012 06:32


there are time we would like an object to self destruct if the initializing argument provided during object creation, dictate
the object should exist at all.
<?php
class TestClass
{
private $have_girlfren=false;
//
private function __construct( $have_girlfren )
{
echo "sixth day<br>
";
$this->have_girlfren=$have_girlfren;
$this->existenceRequirement();
}
//
private function existenceRequirement()
{
if( $this->have_girlfren==false )
{
echo 'i want to die<br>
';
$this->__destruct();

throw new Exception();
}
}
///////////////////////
function __destruct()

{
echo "i am dead<br>
";
}
//////////////////
static function getNewInstance( $have_girlfren)
{
try{
$new_obj=new TestClass( $have_girlfren);
return $new_obj;

}
catch(Exception $e)
{

unset($new_obj);
echo "rest in peace<br>
";
return false;
}
}
//
function gotGirlFren()
{
return $this->have_girlfren;
}
}
$test_obj=TestClass::getNewInstance( false );
if( $test_obj )
echo "bye test oby closing<br>
";
else
echo "instance commit suicide<br>
";
echo "--------------<br>
";
echo "-the end--";
?>

Jeffrey 21-May-2012 10:36


The PHYSICS OF THE SYSTEM
You cannot take the PHYSICS out of any SYSTEM (or environment) -- man-made OR natural. In every system, there lies the laws of
physics (the laws of nature). For example, a moving object -- in a natural environment OR in a lab -- is always subject to the
same forces that exist anywhere. Even a computer program has an environment, for example:
<?php
?>
Even though it had a very short life, it had an ENVIRONMENT which had POTENTIAL TO DO WORK, which made it a good candidate for
a useful SYSTEM. If we think about a 3-Dimensional space as an environment, it is easy to imagine putting 'things' or
'objects' in that space AND doing things to them.
In the next invocation of PHP below, I am going to:
1. Create a 3-Dimensional space or ENVIRONMENT -- just by using the '<?php' tag.

2. Define the SYSTEM we want to use -- laws, rules, policies, structure, properties etc. -- with valid PHP class definitions.
3. Instantiate objects with the 'new' operator so we can poke it for a while.
4. Output some data to see if they obey the rules we wrote.
5. Here we go!
<?php
// 1. check, ENVIRONMENT created.
class Wheel
{
public $cir = 3.0; // circumference in feet.
public $rpm = 0.0; // rotations (spins) per minute.
public function __toString()
{
return 'Wheel [' .
'cir=' . number_format($this->cir, 2) . ' ft, ' .
'rpm=' . $this->rpm .
']';
}
}
// Wheel defined...
class Speedometer
{
public $wheel;
public function __construct(Wheel $wheel)
{
$this->wheel = $wheel;
}
public function getSpeed()
{
$speed = 0.0;
$wheel = $this->wheel;
if($wheel->rpm != 0.0)
{
$fpm = $wheel->cir * $wheel->rpm; // feet per minute
$fph = $fpm * 60; // feet per hour
$speed = $fph / 5280; // MPH = $fph / feet per mile
}
return $speed;
}
public function __toString()
{
return 'Speedometer [' .
'speed=' . number_format($this->getSpeed(), 2) . ' MPH, ' .
'wheel=' . $this->wheel .
']';
}
}
// Speedometer defined.
// 2. check, SYSTEM created.
$wheel = new Wheel();
$speedometer = new Speedometer($wheel);

// 3. check, Objects instantiated.


while($wheel->rpm <= 1500)
{
echo $speedometer . "<br>\n";
$wheel->rpm += 100;
}
// 4. check, data outputted.
?>
Speedometer [speed=0.00 MPH, wheel=Wheel [cir=3.00 ft, rpm=0]]
Speedometer [speed=3.41 MPH, wheel=Wheel [cir=3.00 ft, rpm=100]]
Speedometer [speed=6.82 MPH, wheel=Wheel [cir=3.00 ft, rpm=200]]
... etc ...
... etc ...
Speedometer [speed=51.14 MPH, wheel=Wheel [cir=3.00 ft, rpm=1500]]
5. check, there it went.

Manish Gupta 22-Oct-2011 10:07


Some thing that may be obvious to the seasoned PHP programmer, but may surprise someone coming over from C++:
<?php
class Foo
{
$bar = 'Hi There';
public function Print(){
echo $bar;
}
}
?>
Gives an error saying Print used undefined variable. One has to explicitly use (notice the use of <?php $this->bar ?>):
<?php
class Foo
{
$bar = 'Hi There';
public function Print(){
echo this->$bar;
}
}
?>
<?php echo $this->bar; ?> refers to the class member, while using $bar means using an uninitialized variable in the local
context of the member function.

Marcus 05-Feb-2011 11:00


Here's another simple example.
<?php
// PHP 5

// class definition
class Bear {
// define properties
public $name;
public $weight;
public $age;
public $sex;
public $colour;
// constructor
public function __construct() {
$this->age = 0;
$this->weight = 100;
}
// define methods
public function eat($units) {
echo $this->name." is eating ".$units." units of food... ";
$this->weight += $units;
}
public function run() {
echo $this->name." is running... ";
}
public function kill() {
echo $this->name." is killing prey... ";
}
public function sleep() {
echo $this->name." is sleeping... ";
}
}
// extended class definition
class PolarBear extends Bear {
// constructor
public function __construct() {
parent::__construct();
$this->colour = "white";
$this->weight = 600;
}
// define methods
public function swim() {
echo $this->name." is swimming... ";
}
}
?>

Doug 07-Oct-2010 07:29


What is the difference between $this and self ?
Inside a class definition, $this refers to the current object, while self refers to the current class.
It is necessary to refer to a class element using self ,

and refer to an object element using $this .


Note also how an object variable must be preceded by a keyword in its definition.
The following example illustrates a few cases:
<?php
class Classy {
const STAT = 'S' ; // no dollar sign for constants (they are always static)
static $stat = 'Static' ;
public $publ = 'Public' ;
private $priv = 'Private' ;
protected $prot = 'Protected' ;
function __construct( ){ }
public function showMe( ){
print '<br> self::STAT: ' . self::STAT ; // refer to a (static) constant like this
print '<br> self::$stat: ' . self::$stat ; // static variable
print '<br>$this->stat: ' . $this->stat ; // legal, but not what you might think: empty result
print '<br>$this->publ: ' . $this->publ ; // refer to an object variable like this
print '<br>' ;
}
}
$me = new Classy( ) ;
$me->showMe( ) ;
/* Produces this output:
self::STAT: S
self::$stat: Static
$this->stat:
$this->publ: Public
*/
?>

ben dot corne at gmail dot com 26-Apr-2010 12:35


method calling context aware. By this I mean it will get treated differently while being in a new statement compared to being
in a regular call.
Example:
<?php
class Foo {
private $className = 'Bar';

public function make() {


return new $this->className();
}

public function callClassName() {


$this->className();
}
public function className() {
echo "foo\n";
}
};

class Bar {
public function hello() {
echo "bar\n";
}
};
$foo = new Foo();
$bar = $foo->make();
echo "expecting 'bar': ";
$bar->hello();
echo "expecting 'foo': ";
$foo->callClassName();
?>
even tough $this->className() is written two times in exactly the same way, the one contained in a new statement gets the
className field and the other performs the actual method.

Anonymous 06-Nov-2009 06:54


It is also simple to get or set a property with a name determined at runtime:
<?php
$e=new E();
$e->{"foo"} = 1; // using a runtime name
// is the same as doing:
// $e->foo = 1;
?>

moty66 at gmail dot com 16-Aug-2009 07:59


I hope that this will help to understand how to work with static variables inside a class
<?php
class a {
public static $foo = 'I am foo';
public $bar = 'I am bar';

public static function getFoo() { echo self::$foo; }


public static function setFoo() { self::$foo = 'I am a new foo'; }
public function getBar() { echo $this->bar; }
}
$ob = new a();
a::getFoo(); // output: I am foo
$ob->getFoo(); // output: I am foo
//a::getBar(); // fatal error: using $this not in object context
$ob->getBar(); // output: I am bar
// If you keep $bar non static this will work
// but if bar was static, then var_dump($this->bar) will output null
// unset($ob);
a::setFoo(); // The same effect as if you called $ob->setFoo(); because $foo is static
$ob = new a(); // This will have no effects on $foo
$ob->getFoo(); // output: I am a new foo

?>
Regards
Motaz Abuthiab

alex c 07-Aug-2009 12:17


ok this really basic but I always forget this. I always get an error like:
Fatal error: Call to a member function on a non-object
when i deal with oops
if it were me finding the error i'd search the internet for hours and then it would occur to me, I'm putting my class operator
inside a function, but i would define the class in global file.
so like this:
test.php
<?
include(class.php);
$class = new newclassname;
function function1(){
$class->dofunc();
}
?>
you'll get some die errors and try and do this with function1,
function function1(){
newclassname::dofunc();
}
but if you're using $this inside your class then you'll get another error on non object
so basically, all you need to do is:
function function1(){
$class = new newclassname;
$class->dofunc();
}
or
function function1(){
global $class;
$class->dofunc();
}
i know it's simple, but it always gets me!

the_french_cow at hotmail dot com 14-Jul-2009 06:54


For those of us who are new to inheritance, private functions are not visible in an inherited class. Consider:
<?php
class A {

protected function func1() {


echo("I'm func1 in A!<br/>");
}
private function func2() {
echo("I'm func2 in A!<br/>");
}
}

class B extends A {
public function func3() {
echo("I'm func3 in B!<br/>");
$this->func1();
$this->func2(); // Call to private function from extended class results in a fatal error
}
}

$b = new B;
$b->func3(); // Ends in a fatal error
// OR
$b->func1(); // Call to protected function from outside world results in a fatal error
?>
If you want a function to be accessible in class B but not to the outside world, it must be declared as protected.

Notes on stdClass 09-Jul-2009 03:26


stdClass is the default PHP object. stdClass has no properties, methods or parent. It does not support magic methods, and
implements no interfaces.
When you cast a scalar or array as Object, you get an instance of stdClass. You can use stdClass whenever you need a generic
object instance.
<?php
// ways of creating stdClass instances
$x = new stdClass;
$y = (object) null; // same as above
$z = (object) 'a'; // creates property 'scalar' = 'a'
$a = (object) array('property1' => 1, 'property2' => 'b');
?>
stdClass is NOT a base class! PHP classes do not automatically inherit from any class. All classes are standalone, unless they
explicitly extend another class. PHP differs from many object-oriented languages in this respect.
<?php
// CTest does not derive from stdClass
class CTest {
public $property1;
}
$t = new CTest;
var_dump($t instanceof stdClass); // false
var_dump(is_subclass_of($t, 'stdClass')); // false
echo get_class($t) . "\n"; // 'CTest'
echo get_parent_class($t) . "\n"; // false (no parent)
?>
You cannot define a class named 'stdClass' in your code. That name is already used by the system. You can define a class named
'Object'.

You could define a class that extends stdClass, but you would get no benefit, as stdClass does nothing.
(tested on PHP 5.2.8)

webmaster at oehoeboeroe dot nl 03-May-2009 05:03


If you pass $this by reference and then assign a new value to it, it will not behave as you might expect as illustrated by
this example:
<?php
class TestClass
{
public $data;

function setData(&$data) {
$this->data =& $data;
}
function hasData(&$data) {
$saved = $data;
$data = true;
$result = $this->data === true;
$data = $saved;
return $result;
}

function isDataOf(&$object) {
return $object->hasData($this);
}
}
$o1 = new TestClass;
$o2 = new TestClass;
$o1->setData($o2);
$o2->setData($o1);
var_dump($o1->hasData($o2)); // true as expected
var_dump($o2->hasData($o1)); // true as expected
var_dump($o1->isDataOf($o2)); // false even though $o1 is in fact the data of $o2
var_dump($o2->isDataOf($o1)); // false even though $o2 is in fact the data of $o1
?>
You can make this example work by replacing the hasData method with:
<?php
function hasData(&$data) {
return $data === $this->data;
}
?>
However, although I've not tested this, I've been told that Zend Engine 1, i.e. PHP 4, will choke on the === parameter when
comparing recursing objects.

ialsoagree 23-Apr-2009 08:03


Unfortunately, Arpit's solution creates a new class and leaves the old class inaccessible. If you need access to members of the
class you are in you'll be unable to get such access. This can be a huge problem.
However, there is a solution:

<?php
class MyClass {
public $message = 'Hello';
public function MyClassFunction() {
function innerFunction(&$this_thing, $message = null) {
$this_thing->message = (!is_null($message)) ? $message : $this_thing->message;
$this_thing->echo_something();
}
innerFunction($this); // echoes 'Hello'
innerFunction($this, '<br/>New Message'); // echoes '<br/>New Message'
}

public function echo_something() {


echo $this->message;
}
}
$class = new MyClass;
$class->MyClassFunction();
?>
By passing $this as a variable by reference, you can access members of the class and even update them. If you don't want to be
able to update them, you can simply pass $this to the function but not as a reference.

Arpit 06-Feb-2009 06:14


//try this code if you define a new class inside an object method than we can refer to "$class->message"
//unset this instance doesn't affected the previous one
//it will not report a fatal error
<?php
class MyClass {
public $message = 'Hello';
public function MyClassFunction() {
function InnerFunction() {
$class = new MyClass;
print_r($class);
echo $class->message;
unset($class);//unset this doesn't affected the previous one or we can also use different name $classNew=new MyClass;
}
innerFunction();
}
}
$class = new MyClass;
$class->MyClassFunction();
?>

ialsoagree 02-Feb-2009 04:23


I think it's worth mentioning that if you define a function inside of an object method, that function cannot refer to "$this" doing so will result in PHP reporting a fatal error:
Fatal error: Using $this when not in object context

<?php
class MyClass {
public $message = 'Hello';
public function MyClassFunction() {
function InnerFunction() {
echo $this->message; // Reports a fatal error
}
innerFunction();
}
}
$class = new MyClass;
$class->MyClassFunction();
?>
This issue cannot be solved by using the Scope Resolution Operator if you're trying to access a variable:
<?php
class MyClass {
public $message = 'Hello';
public function MyClassFunction() {
function InnerFunction() {
echo MyClass::message; // Reports a fatal error
}
innerFunction();
}
}
$class = new MyClass;
$class->MyClassFunction();
?>
Additionally, you can NOT create a public function to access that variable:
<?php
class MyClass {
public $message = 'Hello';
public function MyClassFunction() {
function InnerFunction() {
MyClass::echoSomething();
}
innerFunction();
}
public function echoSomething() {
echo $this->message; // Reports a fatal error
}
}
$class = new MyClass;
$class->MyClassFunction();
?>
Note that in this last case, the error is generated on the line below echoSomething function declaration, not at
MyClass::echoSomething();

However, it is worth noting that when called directly, echoSomething works fine:
<?php
class MyClass {
public $message = 'Hello';
public function MyClassFunction() {
function InnerFunction() {
MyClass::echoSomething();
}
innerFunction();
}
public function echoSomething() {
echo $this->message; // Echoes 'Hello'
}
}
$class = new MyClass;
$class->echoSomething();
?>

hugo (@) apres (dot) net 16-Jan-2009 08:37


A simple approach to Multiple Inheritance
You can give yourself something approaching multiple inheritance with the following class:
<?php
class inheritance{
var $bases = array();
static function error_die( $errno, $errstr, $errfile, $errline ) {
$backtrace = debug_backtrace();
$detail = $backtrace[4];
var_dump( $backtrace );
echo '<b>Fatal Error</b>: '.$errstr.' of class <b>'.$detail["class"].'</b> in <b>'.$detail["file"].'</b> on line
<b>'.$detail["line"].'</b><br/>';
die();
}
private function fatal( $text ) {
set_error_handler( array( 'inheritance', 'error_die' ) );
trigger_error( $text, E_USER_ERROR );
restore_error_handler();
}
function __call( $name, $args ) {
if( $this->bases )
foreach( $this->bases as $base )
if( method_exists( $base, $name ) )
return $base->$name( $args );
$this->fatal( "Call to undefined method <b>".$name."</b>" );
}
function __set( $name, $value ) {
if( $this->bases )

foreach( $this->bases as $base )


if( property_exists( $base, $name ) ) {
$base->$name = $value;
return;
}
}

function __get( $name ) {


if( $this->bases )
foreach( $this->bases as $base )
if( property_exists( $base, $name ) )
return $base->$name;
}
function __isset( $name ) {
if( $this->bases )
foreach( $this->bases as $base )
if( property_exists( $base, $name ) )
return isset( $base->$name );
}
function __unset( $name ) {
if( $this->bases )
foreach( $this->bases as $base )
if( property_exists( $base, $name ) ) {
unset( $base->$name );
return;
}
}
function inherits( $name, $args = '' ) {
return array_unshift( $this->bases, new $name( $args ) );
}
}
?>
Most of the qualities of multiple inheritance provided by this class are revealed by the following code:
<?php //test inheritance
class base0 {
public $base0var;
public $basevar;
function base0declare() {
echo 'I am base 0';
}
function basedeclare() {
self::base0declare() {
}
}
class base1 extends base0 { // simple linear inheritance here
public $base1var;
public $basevar;
function based1declare() {
echo 'I am base 1';

}
function basedeclare() {
self::base1declare()
}
}
class base2
public $base2var;
public $basevar;
function based2declare() {
echo 'I am base 2';
}
function basedeclare() {
self::base2declare
}
}
?>
Multiple inheritance is achieved by extending the inheritance class, and then in the __construct function placing calls to the
"inherits" method of the inheritance class. Each call pushes an instance of the inherited class into an array var which
functions as a LIFO stack. Using the magic methods, any failed method call, property set, get, isset or unset is intercepted by
the inheritance base class which then attempts to resolve the reference. Object method name conflicts are resolved simply by
the later inheritance masking the scope of the earlier inherited method. I recognize there are shortcomings to the approach I
offer here, but it works for all my current multiple inheritance needs and offers simplicity and ease of understanding as
benefits.
<?php
class base_test extends inheritance { // multiple inheritance
function __construct() {
$this->inherits( 'base1' );
$this->inherits( 'base2' );
}
} ?>
Here are some code fragments you can try out to test things.
<?php
$testobj = new base_test();
var_dump( $testobj );
$testobj->base2declare();
$testobj->base1declare();
$testobj->base0declare();
$testobj->basedeclare();
$testobj->base2var = 27;
echo $testobj->base2var;
?>
I'd be interested in hearing any comments.

chris (@) xeneco (dot) co (dot) uk 27-Nov-2008 03:25


Regarding object inheritance:
I hope this helps someone, it should help if you're new to OOPS

<?php
class A {

public $x = 'A';
public function foo() {
$b = new B;
$b->bar();
return $this->x;
}
}
class B extends A {
public function bar() {
$this->x = 'B';
}
}
$a = new A
echo $a->foo(); //A
?>
I was doing something similar to this (example is greatly simplified to show logic) and spent a long while trying to work out
why I would always get 'A' and never get 'B'. Now, after a few weeks, I have revisited the problem and have worked out why:
The code 'new B' creates a new instance of class B. While class B extends class A, it is a new object and not an extension of
the object created by 'new A'
The value of $x is set to 'B' within the object $b, but not in object $a.
If within A::foo(), one was to access $b->x then one would obtain the vale 'B', for example
<?php
class C {

public $x = 'C';
public function foo() {
$c = new C;
$c->bar();
$this->x = $c->$x
return $this->x;
}
}
class D extends C {
public function bar() {
$this->x = 'D';
}
}
$c = new C
echo $c->foo(); //D
?>

Jeffrey 08-Oct-2008 03:49


A PHP Class can be used for several things, but at the most basic level, you'll use classes to "organize and deal with likeminded data". Here's what I mean by "organizing like-minded data". First, start with unorganized data.
<?php
$customer_name;
$item_name;
$item_price;
$customer_address;
$item_qty;
$item_total;
?>
Now to organize the data into PHP classes:
<?php
class Customer {
$name; // same as $customer_name
$address; // same as $customer_address
}
class Item {
$name; // same as $item_name
$price; // same as $item_price
$qty; // same as $item_qty
$total; // same as $item_total
}
?>
Now here's what I mean by "dealing" with the data. Note: The data is already organized, so that in itself makes writing new
functions extremely easy.
<?php
class Customer {
public $name, $address; // the data for this class...
// function to deal with user-input / validation
// function to build string for output
// function to write -> database
// function to read <- database
// etc, etc
}
class Item {
public $name, $price, $qty, $total; // the data for this class...
// function to calculate total
// function to format numbers
// function to deal with user-input / validation
// function to build string for output
// function to write -> database
// function to read <- database
// etc, etc
}
?>
Imagination that each function you write only calls the bits of data in that class. Some functions may access all the data,

while other functions may only access one piece of data. If each function revolves around the data inside, then you have
created a good class.

wbcarts at juno dot com 20-Aug-2008 06:11


CLASSES and OBJECTS that represent the "Ideal World"
Wouldn't it be great to get the lawn mowed by saying $son->mowLawn()? Assuming the function mowLawn() is defined, and you have
a son that doesn't throw errors, the lawn will be mowed.
In the following example; let objects of type Line3D measure their own length in 3-dimensional space. Why should I or PHP have
to provide another method from outside this class to calculate length, when the class itself holds all the neccessary data and
has the education to make the calculation for itself?
<?php
/*
* Point3D.php
*
* Represents one locaton or position in 3-dimensional space
* using an (x, y, z) coordinate system.
*/
class Point3D
{
public $x;
public $y;
public $z; // the x coordinate of this Point.
/*
* use the x and y variables inherited from Point.php.
*/
public function __construct($xCoord=0, $yCoord=0, $zCoord=0)
{
$this->x = $xCoord;
$this->y = $yCoord;
$this->z = $zCoord;
}
/*
* the (String) representation of this Point as "Point3D(x, y, z)".
*/
public function __toString()
{
return 'Point3D(x=' . $this->x . ', y=' . $this->y . ', z=' . $this->z . ')';
}
}
/*
* Line3D.php
*
* Represents one Line in 3-dimensional space using two Point3D objects.
*/
class Line3D
{
$start;
$end;
public function __construct($xCoord1=0, $yCoord1=0, $zCoord1=0, $xCoord2=1, $yCoord2=1, $zCoord2=1)
{

$this->start = new Point3D($xCoord1, $yCoord1, $zCoord1);


$this->end = new Point3D($xCoord2, $yCoord2, $zCoord2);
}
/*
* calculate the length of this Line in 3-dimensional space.
*/
public function getLength()
{
return sqrt(
pow($this->start->x - $this->end->x, 2) +
pow($this->start->y - $this->end->y, 2) +
pow($this->start->z - $this->end->z, 2)
);
}
/*
* The (String) representation of this Line as "Line3D[start, end, length]".
*/
public function __toString()
{
return 'Line3D[start=' . $this->start .
', end=' . $this->end .
', length=' . $this->getLength() . ']';
}
}
/*
* create and display objects of type Line3D.
*/
echo '<p>' . (new Line3D()) . "</p>\n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 0)) . "</p>\n";
echo '<p>' . (new Line3D(0, 0, 0, 100, 100, 100)) . "</p>\n";
?>
<-- The results look like this -->
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=1, y=1, z=1), length=1.73205080757]
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=0), length=141.421356237]
Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=100), length=173.205080757]
My absolute favorite thing about OOP is that "good" objects keep themselves in check. I mean really, it's the exact same thing
in reality... like, if you hire a plumber to fix your kitchen sink, wouldn't you expect him to figure out the best plan of
attack? Wouldn't he dislike the fact that you want to control the whole job? Wouldn't you expect him to not give you
additional problems? And for god's sake, it is too much to ask that he cleans up before he leaves?
I say, design your classes well, so they can do their jobs uninterrupted... who like bad news? And, if your classes and
objects are well defined, educated, and have all the necessary data to work on (like the examples above do), you won't have to
micro-manage the whole program from outside of the class. In other words... create an object, and LET IT RIP!

ashraf dot samhouri at hotmail dot com 24-May-2008 06:35


@info -- 20-April
This is because you requested class "b" before defining it, not because you defined class "b" before "a". It doesn't make a
difference which class you define first.

info at youwanttoremovethisvakantiebaas dot nl 20-Apr-2008 03:40


if you do this
<?php
$x = new b();
class b extends a {}
class a { }
?>
PHP will tell you "class b not found", because you've defined class b before a. However, the error tells you something
different.... Got me a little confused :)

david dot schueler at tel-billig dot de 15-Feb-2008 06:16


If you just want to create a new object that extends another object and you want to copy all variables from the father object,
you may use this piece of code:
<?php
$father =& new father();
$father->a_var = "Hello World.";
$son = new son($event);
$son->say_hello();
class father {
public $a_var;
}
class son extends father {
public function __construct($father_class) {
foreach ($father_class as $variable=>$value) {
$this->$variable = $value;
}
}
public function say_hello() {
echo "Son says: ".$this->a_var;
}
}
?>
This outputs:
Son says: Hello World.
So you dont have to clone the entire object to get the contents of the variables from the father object.

aaron at thatone dot com 15-Dec-2007 06:46


I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by
reference. But I think I've figured out what's going on.
First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is
one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name
that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to

another data slot.


Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly.
Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect.
So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.
What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable,
that other variable gets a copy of the same object handle. This means that both variables can change the state of the same
object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other
variable.
<?php
// Assignment of an object
Class Object{
public $foo="bar";
};
$objectVar = new Object();
$reference =& $objectVar;
$assignment = $objectVar
//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>
$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it
behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those
changes also show up under $assignment, because it is pointing at that same Object instance.
<?php
$objectVar->foo = "qux";
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );
//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>
But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL.

This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data
slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.
<?php
$objectVar = null;
print_r($objectVar);
print_r($reference);
print_r($assignment);
//
// $objectVar --->+---------+
// | NULL |
// $reference --->+---------+
//
// +---------+
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
?>

alan at alan-ng dot net 09-Oct-2007 09:41


The following odd behavior happens in php version 5.1.4 (and presumably some other versions) that does not happen in php
version 5.2.1 (and possibly other versions > 5.1.4).
<?php
$_SESSION['instance']=...;
$instance=new SomeClass;
?>
The second line will not only create the $instance object successfully, it will also modify the value of $_SESSION['instance']!
The workaround I arrived at, after trial and error, was to avoid using object names which match a $_SESSION array key.
This is not intended to be a bug report, since it was apparently fixed by version 5.2.1, so it's just a workaround suggestion.

Dan Dascalescu 26-Oct-2006 11:00


If E_STRICT is enabled, the first example will generate the following error (and a few others akin to it):
Non-static method A::foo() should not be called statically on line 26
The example should have explicitly declared the methods foo() and bar() as static:
class A

static function foo()

{
...

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Properties
Class member variables are called "properties". You may also see them referred to using other terms such as
"attributes" or "fields", but for the purposes of this reference we will use "properties". They are defined by using
one of the keywords public, protected, or private, followed by a normal variable declaration. This declaration
may include an initialization, but this initialization must be a constant value--that is, it must be able to be
evaluated at compile time and must not depend on run-time information in order to be evaluated.
See Visibility for more information on the meanings of public, protected, and private.
Note:
In order to maintain backward compatibility with PHP 4, PHP 5 will still accept the use of the keyword var in
property declarations instead of (or in addition to) public, protected, or private. However, var is no
longer required. In versions of PHP from 5.0 to 5.1.3, the use of var was considered deprecated and would
issue an E_STRICT warning, but since PHP 5.1.3 it is no longer deprecated and does not issue the warning.
If you declare a property using var instead of one of public, protected, or private, then PHP 5 will treat
the property as if it had been declared as public.
Within class methods the properties, constants, and methods may be accessed by using the form $this>property (where property is the name of the property) unless the access is to a static property within the
context of a static class method, in which case it is accessed using the form self::$property. See Static Keyword
for more information.
The pseudo-variable $this is available inside any class method when that 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 possibly
another object, if the method is called statically from the context of a secondary object).
Example #1 property declarations
<?php
classSimpleClass
{
//invalidpropertydeclarations:
public$var1='hello'.'world';
public$var2=<<<EOD
helloworld
EOD;
public$var3=1+2;
public$var4=self::myStaticMethod();
public$var5=$myVar;
//validpropertydeclarations:
public$var6=myConstant;
public$var7=array(true,false);
//ThisisallowedonlyinPHP5.3.0andlater.
public$var8=<<<'EOD'
helloworld
EOD;
}
?>

Note:

There are some nice functions to handle classes and objects. You might want to take a look at the
Class/Object Functions.
Unlike heredocs, nowdocs can be used in any static data context, including property declarations.
Example #2 Example of using a nowdoc to initialize a property
<?php
classfoo{
//AsofPHP5.3.0
public$bar=<<<'EOT'
bar
EOT;
}
?>

Note:
Nowdoc support was added in PHP 5.3.0.

User Contributed Notes

Properties

Anonymous 17-Apr-2012 09:16


In case this saves anyone any time, I spent ages working out why the following didn't work:
class MyClass
{
private $foo = FALSE;
public function __construct()
{
$this->$foo = TRUE;
echo($this->$foo);
}
}
$bar = new MyClass();
giving "Fatal error: Cannot access empty property in ...test_class.php on line 8"
The subtle change of removing the $ before accesses of $foo fixes this:
class MyClass
{
private $foo = FALSE;
public function __construct()
{
$this->foo = TRUE;
echo($this->foo);

}
}
$bar = new MyClass();
I guess because it's treating $foo like a variable in the first example, so trying to call $this->FALSE (or something along
those lines) which makes no sense. It's obvious once you've realised, but there aren't any examples of accessing on this page
that show that.

Anonymous 11-Mar-2011 03:18


$this can be cast to array. But when doing so, it prefixes the property names/new array keys with certain data depending on
the property classification. Public property names are not changed. Protected properties are prefixed with a space-padded
'*'. Private properties are prefixed with the space-padded class name...
<?php
class test
{
public $var1 = 1;
protected $var2 = 2;
private $var3 = 3;
static $var4 = 4;

public function toArray()


{
return (array) $this;
}
}
$t = new test;
print_r($t->toArray());
/* outputs:
Array
(
[var1] => 1
[ * var2] => 2
[ test var3] => 3
)
*/
?>
This is documented behavior when converting any object to an array (see </language.types.array.php#language.types.array.casting>
PHP manual page). All properties regardless of visibility will be shown when casting an object to array (with exceptions of a
few built-in objects).
To get an array with all property names unaltered, use the 'get_object_vars($this)' function in any method within class scope
to retrieve an array of all properties regardless of external visibility, or 'get_object_vars($object)' outside class scope to
retrieve an array of only public properties (see: </function.get-object-vars.php> PHP manual page).

zzzzBov 04-Jun-2010 09:21


Do not confuse php's version of properties with properties in other languages (C++ for example). In php, properties are the
same as attributes, simple variables without functionality. They should be called attributes, not properties.

Properties have implicit accessor and mutator functionality. I've created an abstract class that allows implicit property
functionality.
<?php
abstract class PropertyObject
{
public function __get($name)
{
if (method_exists($this, ($method = 'get_'.$name)))
{
return $this->$method();
}
else return;
}

public function __isset($name)


{
if (method_exists($this, ($method = 'isset_'.$name)))
{
return $this->$method();
}
else return;
}

public function __set($name, $value)


{
if (method_exists($this, ($method = 'set_'.$name)))
{
$this->$method($value);
}
}

public function __unset($name)


{
if (method_exists($this, ($method = 'unset_'.$name)))
{
$this->$method();
}
}
}
?>
after extending this class, you can create accessors and mutators that will be called automagically, using php's magic methods,
when the corresponding property is accessed.

Anonymous 17-Nov-2009 07:51


As of PHP 5.3.0, heredocs can also be used in property declarations.
<?php
class foo {
// As of PHP 5.3.0
public $bar = <<<EOT
bar
EOT;
}
?>

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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 property, a result of a mathematical
operation, or a function call.
It's also possible for interfaces to have constants. Look at the interface documentation for examples.
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
classMyClass
{
constconstant='constantvalue';
functionshowConstant(){
echoself::constant."\n";
}
}
echoMyClass::constant."\n";
$classname="MyClass";
echo$classname::constant."\n";//AsofPHP5.3.0
$class=newMyClass();
$class->showConstant();
echo$class::constant."\n";//AsofPHP5.3.0
?>

Example #2 Static data example


<?php
classfoo{
//AsofPHP5.3.0
constbar=<<<'EOT'
bar
EOT;
}
?>

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

Note:
Nowdoc support was added in PHP 5.3.0.

User Contributed Notes

Class Constants

ryan at derokorian dot com 07-Jun-2012 03:21


It may seem obvious, but class constants are always publicly visible. They cannot be made private or protected. I do not see it
state that in the docs anywhere.

tmp dot 4 dot longoria at gmail dot com 04-Jun-2011 01:52


it's possible to declare constant in base class, and override it in child, and access to correct value of the const from the
static method is possible by 'get_called_class' method:
<?php
abstract class dbObject
{
const TABLE_NAME='undefined';

public static function GetAll()


{
$c = get_called_class();
return "SELECT * FROM `".$c::TABLE_NAME."`";
}
}
class dbPerson extends dbObject
{
const TABLE_NAME='persons';
}
class dbAdmin extends dbPerson
{
const TABLE_NAME='admins';
}
echo dbPerson::GetAll()."<br>";//output: "SELECT * FROM `persons`"
echo dbAdmin::GetAll()."<br>";//output: "SELECT * FROM `admins`"
?>

dexen dot devries at gmail dot com 02-Feb-2011 01:42


Summary: use ReflectionObject to access class const in PHP older than 5.3.
In versions <= 5.2 you can't use the $object::constMember syntax. Accessing via class name or the `self' operator doesn't
resolve the right class in case of inheritance (for the C++ folks, it behaves like a NON-virtual method). The only working (if
ugly) solution to access seems to be to use the Reflection extension:
<?php
class Foo {
const a = 7;
const x = 99;
}
class Bar extends Foo {
const a = 42; /* overrides the `a = 7' in base class */
}
$b = new Bar();
$r = new ReflectionObject($b);

echo $r->getConstant('a'); # prints `42' from the Bar class


echo "\n";
echo $r->getConstant('x'); # prints `99' inherited from the Foo class
?>

jakub dot lopuszanski at nasza-klasa dot pl 14-Nov-2010 11:20


Suprisingly consts are lazy bound even though you use self instead of static:
<?php
class A{
const X=1;
const Y=self::X;
}
class B extends A{
const X=1.0;
}
var_dump(B::Y); // float(1.0)
?>

anonymous 27-Sep-2010 06:32


Most people miss the point in declaring constants and confuse then things by trying to declare things like functions or arrays
as constants. What happens next is to try things that are more complicated then necessary and sometimes lead to bad coding
practices. Let me explain...
A constant is a name for a value (but it's NOT a variable), that usually will be replaced in the code while it gets COMPILED
and NOT at runtime.
So returned values from functions can't be used, because they will return a value only at runtime.
Arrays can't be used, because they are data structures that exist at runtime.
One main purpose of declaring a constant is usually using a value in your code, that you can replace easily in one place
without looking for all the occurences. Another is, to avoid mistakes.
Think about some examples written by some before me:
1. const MY_ARR = "return array(\"A\", \"B\", \"C\", \"D\");";
It was said, this would declare an array that can be used with eval. WRONG! This is just a string as constant, NOT an array.
Does it make sense if it would be possible to declare an array as constant? Probably not. Instead declare the values of the
array as constants and make an array variable.
2. const magic_quotes = (bool)get_magic_quotes_gpc();
This can't work, of course. And it doesn't make sense either. The function already returns the value, there is no purpose in
declaring a constant for the same thing.
3. Someone spoke about "dynamic" assignments to constants. What? There are no dynamic assignments to constants, runtime
assignments work _only_ with variables. Let's take the proposed example:
<?php
/**
* Constants that deal only with the database
*/
class DbConstant extends aClassConstant {
protected $host = 'localhost';
protected $user = 'user';
protected $password = 'pass';

protected $database = 'db';


protected $time;
function __construct() {
$this->time = time() + 1; // dynamic assignment
}
}
?>
Those aren't constants, those are properties of the class. Something like "this->time = time()" would even totally defy the
purpose of a constant. Constants are supposed to be just that, constant values, on every execution. They are not supposed to
change every time a script runs or a class is instantiated.
Conclusion: Don't try to reinvent constants as variables. If constants don't work, just use variables. Then you don't need to
reinvent methods to achieve things for what is already there.

Anonymous 13-Nov-2009 12:03


Note that since constants are tied to the class definition, they are static by definition and cannot be accessed using the ->
operator.
A side effect of this is that it's entirely possible for a class constant to have the same name as a property (static or
object):
<?php
class Foo
{
const foo = 'bar';
public $foo = 'foobar';
const bar = 'foo';
static $bar = 'foobar';
}
var_dump(foo::$bar); // static property
var_dump(foo::bar); // class constant
$bar = new Foo();
var_dump($bar->foo); // object property
var_dump(bar::foo); // class constant
?>

cwreace at yahoo dot com 06-Oct-2008 06:22


A useful technique I've found is to use interfaces for package- or application-wide constants, making it easy to incorporate
them into any classes that need access to them:
<?php
interface AppConstants
{
const FOOBAR = 'Hello, World.';
}
class Example implements AppConstants
{
public function test()
{
echo self::FOOBAR;
}

}
$obj = new Example();
$obj->test(); // outputs "Hello, world."
?>
I realize the same could be done simply by defining the constant in a class and accessing it via "class_name::const_name", but
I find this a little nicer in that the class declaration makes it immediately obvious that you accessing values from the
implemented interface.

wbcarts at juno dot com 12-Sep-2008 12:12


Use CONST to set UPPER and LOWER LIMITS
If you have code that accepts user input or you just need to make sure input is acceptable, you can use constants to set upper
and lower limits. Note: a static function that enforces your limits is highly recommended... sniff the clamp() function below
for a taste.
<?php
class Dimension
{
const MIN = 0, MAX = 800;
public $width, $height;
public function __construct($w = 0, $h = 0){
$this->width = self::clamp($w);
$this->height = self::clamp($h);
}
public function __toString(){
return "Dimension [width=$this->width, height=$this->height]";
}
protected static function clamp($value){
if($value < self::MIN) $value = self::MIN;
if($value > self::MAX) $value = self::MAX;
return $value;
}
}
echo (new Dimension()) . '<br>';
echo (new Dimension(1500, 97)) . '<br>';
echo (new Dimension(14, -20)) . '<br>';
echo (new Dimension(240, 80)) . '<br>';
?>
- - - - - - - Dimension [width=0, height=0] - default size
Dimension [width=800, height=97] - width has been clamped to MAX
Dimension [width=14, height=0] - height has been clamped to MIN
Dimension [width=240, height=80] - width and height unchanged
- - - - - - - Setting upper and lower limits on your classes also help your objects make sense. For example, it is not possible for the width
or height of a Dimension to be negative. It is up to you to keep phoney input from corrupting your objects, and to avoid
potential errors and exceptions in other parts of your code.

elmar huebschmann 02-Jul-2008 06:12


The major problem of constants is for me, you cant use them for binary flags.
<?php
class constant {
const MODE_FLAG_1 = 1;
const MODE_FLAG_2 = 2;
const MODE_FLAG_3 = 4;
const DEFAULT_MODE = self::FLAG_1 | self::FLAG_2
private function foo ($mode=self::DEFAULT_MODE) {
// some operations
}
}
?>
This code will not work because constants can't be an calculation result. You could use
<?php
const DEFAULT_MODE = 3;
?>
instead, but we use flags to be value indipendent. So you would miss target with it. Only way is to use defines like ever
before.

riku at helloit dot fi 13-Feb-2008 03:24


pre 5.3 can refer a class using variable and get constants with:
<?php
function get_class_const($class, $const){
return constant(sprintf('%s::%s', $class, $const));
}
class Foo{
const BAR = 'foobar';
}
$class = 'Foo';
echo get_class_const($class, 'BAR');
//'foobar'
?>

nrg1981 {AT} hotmail {DOT} com 05-Oct-2007 06:19


If you have a class which defines a constant which may be overridden in child definitions, here are two methods how the parent
can access that constant:
<?php
class Weather
{
const danger = 'parent';

static function getDanger($class)


{
// Code to return the danger field from the given class name
}
}
class Rain extends Weather
{
const danger = 'child';
}
?>
The two options to place in the parent accessor are:
eval('$danger = ' . $class . '::danger;');

or:
$danger = constant($class . '::danger');
I prefer the last option, but they both seem to work.
So, why might this be useful? Well, in my case I have a page class which contains various common functions for all pages and
specific page classes extend this parent class. The parent class has a static method which takes an argument (class name) and
returns a new instantiation of the class.
Each child class has a constant which defines the access level the user must have in order to view the page. The parent must
check this variable before creating and returning an instance of the child - the problem is that the class name is a variable
and $class::danger will treat $class as an object.

michikono at symbol gmail dot com 07-Dec-2006 08:58


In realizing it is impossible to create dynamic constants, I opted for a "read only" constants class.
<?php
abstract class aClassConstant {
/**
* Setting is not permitted.
*
* @param string constant name
* @param mixed new value
* @return void
* @throws Exception
*/
final function __set($member, $value) {
throw new Exception('You cannot set a constant.');
}

/**
* Get the value of the constant
*
* @param string constant name
* @return void
*/
final function __get($member) {
return $this->$member;
}

}
?>
The class would be extended by another class that would compartmentalize the purpose of the constants. Thus, for example, you
would extend the class with a DbConstant class for managing database related constants, that might look like this:
<?php
/**
* Constants that deal only with the database
*/
class DbConstant extends aClassConstant {

protected $host = 'localhost';


protected $user = 'user';
protected $password = 'pass';
protected $database = 'db';
protected $time;

/**
* Constructor. This is so fully dynamic values can be set. This can be skipped and the values can be directly assigned for
non dynamic values as shown above.
*
* @return void
*/
function __construct() {
$this->time = time() + 1; // dynamic assignment
}
}
?>
You would use the class like thus:
<?php
$dbConstant = new DbConstant();
echo $dbConstant->host;
?>
The following would cause an exception:
<?php
$dbConstant = new DbConstant();
$dbConstant->host = '127.0.0.1'; // EXCEPTION
?>
It's not pretty, nor ideal, but at least you don't pollute the global name space with long winded global names and it is
relatively elegant.
Variables must be *protected*, not public. Public variables will bypass the __get and __set methods!! This class is, by design,
not meant to be extended much further than one level, as it is really meant to only contain constants. By keeping the constant
definition class seperate from the rest of your classes (if you are calling this from a class), you minimize the possibility of
accidental variable assignment.
Managing this instance may be a slight pain that requires either caching a copy of the instance in a class variable, or using
the factory pattern. Unfortunately, static methods can't detect the correct class name when the parent name is used during the
call (e.g., DbConstant::instance()). Thus there is no elegant, inheriting solution to that problem. Thus, it is easier to
simply manage a single instance that is declared using conventional notation (e.g., new DbConstant...).
- Michi Kono

webmaster at chaosonline dot de 24-Sep-2006 04:57


Since constants of a child class are not accessible from the parent class via self::CONST and there is no special keyword to
access the constant (like this::CONST), i use private static variables and these two methods to make them read-only accessible
from object's parent/child classes as well as statically from outside:
<?php
class b extends a {
private static $CONST = 'any value';
public static function getConstFromOutside($const) {
return self::$$const;
}
protected function getConst($const) {
return self::$$const;
}
}
?>
With those methods in the child class, you are now able to read the variables from the parent or child class:
<?php
class a {
private function readConst() {
return $this->getConst('CONST');
}
abstract public static function getConstFromOutside($const);
abstract protected function getConst($const);
}
?>
From outside of the object:
<?php
echo b::getConstFromOutside('CONST');
?>
You maybe want to put the methods into an interface.
However, class b's attribute $CONST is not a constant, so it is changeable by methods inside of class b, but it works for me
and in my opinion, it is better than using real constants and accessing them by calling with eval:
<?php
protected function getConst($const) {
eval('$value = '.get_class($this).'::'.$const.';');
return $value;
}
?>

sw at knip dot pol dot lublin dot pl 05-Jul-2006 12:14


It might be obvious,
but I noticed that you can't define an array as a class constant.
Insteed you can define AND initialize an static array variable:
<?php

class AClass {
const an_array = Array (1,2,3,4);
//this WILL NOT work
// and will throw Fatal Error:
//Fatal error: Arrays are not allowed in class constants in...
public static $an_array = Array (1,2,3,4);
//this WILL work
//however, you have no guarantee that it will not be modified outside your class
}
?>

17-Jun-2005 09:29
It's important to note that constants cannot be overridden by an extended class, if you with to use them in virtual functions.
For example :
<?php
class abc
{
const avar = "abc's";
function show()
{
echo self::avar . "\r\n";
}
};
class def extends abc
{
const avar = "def's";
function showmore ()
{
echo self::avar . "\r\n";
$this->show();
}
};
$bob = new def();
$bob->showmore();
?>
Will display:
def's
abc's
However, if you use variables instead the output is different, such as:
<?php
class abc
{
protected $avar = "abc's";
function show()
{
echo $this->avar . "\r\n";
}

};
class def extends abc
{
protected $avar = "def's";
function showmore ()
{
echo $this->avar . "\r\n";
$this->show();
}
};
$bob = new def();
$bob->showmore();
?>
Will output:
def's
def's

caliban at darklock dot com 15-Dec-2004 10:55


Lest anyone think this is somehow an omission in PHP, there is simply no point to having a protected or private constant.
Access specifiers identify who has the right to *change* members, not who has the right to read them:
<?php
// define a test class
class Test
{
public static $open=2;
protected static $var=1;
private static $secret=3;
}
$classname="Test";
// reflect class information
$x=new ReflectionClass($classname);
$y=array();
foreach($x->GetStaticProperties() as $k=>$v)
$y[str_replace(chr(0),"@",$k)]=$v;
// define the variables to search for
$a=array("open","var","secret","nothing");
foreach($a as $b)
{
if(isset($y["$b"]))
echo "\"$b\" is public: {$y["$b"]}<br/>";
elseif(isset($y["@*@$b"]))
echo "\"$b\" is protected: {$y["@*@$b"]}<br/>";
elseif(isset($y["@$classname@$b"]))
echo "\"$b\" is private: {$y["@$classname@$b"]}<br/>";
else
echo "\"$b\" is not a static member of $classname<br/>";
}
?>
As you can see from the results of this code, the protected and private static members of Test are still visible if you know
where to look. The protection and privacy are applicable only on writing, not reading -- and since nobody can write to a

constant at all, assigning an access specifier to it is just redundant.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Autoloading Classes
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.

Tip
spl_autoload_register() provides a more flexible alternative for autoloading classes. For
this reason, using __autoload() is discouraged and may be deprecated or removed in the
future.

Note:
Prior to 5.3.0, exceptions thrown in the __autoload function could not be caught in the catch block and
would result in a fatal error. From 5.3.0+ exceptions thrown in the __autoload function can be caught in the
catch block, with 1 provision. If throwing a custom exception, then the custom exception class must be
available. The __autoload function may be used recursively to autoload the custom exception class.

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){
include$class_name.'.php';
}
$obj=newMyClass1();
$obj2=newMyClass2();
?>

Example #2 Autoload other example


This example attempts to load the interface ITest.

<?php
function__autoload($name){
var_dump($name);
}
classFooimplementsITest{
}
/*
string(5)"ITest"
Fatalerror:Interface'ITest'notfoundin...
*/
?>

Example #3 Autoloading with exception handling for 5.3.0+


This example throws an exception and demonstrates the try/catch block.
<?php
function__autoload($name){
echo"Wanttoload$name.\n";
thrownewException("Unabletoload$name.");
}
try{
$obj=newNonLoadableClass();
}catch(Exception$e){
echo$e->getMessage(),"\n";
}
?>

The above example will output:


Want to load NonLoadableClass.
Unable to load NonLoadableClass.

Example #4 Autoloading with exception handling for 5.3.0+ - Missing custom exception
This example throws an exception for a non-loadable, custom exception.
<?php
function__autoload($name){
echo"Wanttoload$name.\n";
thrownewMissingException("Unabletoload$name.");
}
try{
$obj=newNonLoadableClass();
}catch(Exception$e){
echo$e->getMessage(),"\n";
}
?>

The above example will output:

Want to load NonLoadableClass.


Want to load MissingException.
Fatal error: Class 'MissingException' not found in testMissingException.php on line 4

See Also
unserialize()
unserialize_callback_func
spl_autoload()
spl_autoload_register()

User Contributed Notes

Autoloading Classes

shaftouille 12-Jan-2012 01:14


I think there shouldn't be tests in an autoload callback function, this callback will trigger because the class you're trying
to load is not defined... in any case if your class is not defined, the code must fail. Therefore an autoload function should
be like :
<?php
spl_autoload_register(function($className)
{
require(str_replace('\\', '/', ltrim($className, '\\')) . '.php');
});
?>
As the "require" function uses the include_path, the folders for the autoinclusion should be added using set_include_path,
let's say your index.php is located in a "public" directory and your MVC classes are in "core", the index.php should be :
<?php
define('ROOT_DIR', realpath(__DIR__ . '/..'));
set_include_path(ROOT_DIR . PATH_SEPARATOR . get_include_path());
?>
And of course you want to catch the loading errors, so you can use class_exists :
<?php
$className = '\core\Controller\Hello\World';
if (!class_exists($className))
{
throw new ErrorException('Class Not Found !');
}
else
{
$object = new $className();
}
?>
This code sample will autoload the "World.php" file located in your "core/Controller/Hello" directory, assuming that your class
declaration is like :
<?php

namespace coreControllerHello;
class World
{
function __construct()
{
echo "Helloworld";
}
}
?>

qfox at ya dot ru 16-Nov-2011 02:48


More simpler example of using spl_autoload_register in 5.3:
<?php
spl_autoload_register(function($classname) /* usign $app */ {
# ... your logic to include classes here
});
?>

Nic 25-Aug-2011 12:22


Autoloading camel case classes, ie. loading "controller/product/detail.php" from "ControllerProductDetail":
<?php
// Autoloading
function __autoload($class) {
$path = strtolower(preg_replace('/([a-z])([A-Z])/', '$1/$2', $class));
if(file_exists(DIR_APPLICATION . $path . '.php')) {
require_once(DIR_APPLICATION . $path . '.php');
}
}
?>

bimal at sanjaal dot com 05-Jun-2011 11:58


When multiple scripts try to use __autoload(), there is a collision.
I experienced it while upgrading the Smarty and my own autoload function.
So, the better way is to avoid __autoload() and use spl_register_autoload() instead. If you have written this already, just
rename your function to something like __autoload_my_classes, and in the next, call spl_autoload_register as:
<?php
function __autoload_my_classes($classname)
{
# ... your logic to include classes here
}
spl_autoload_register('__autoload_my_classes');
?>
You can assign multiple functions to spl_autoload_register() by calling it repeatedly with different function names. Be sure to
limit your every function to include a CLASS file.

rahj_1986 at (yahoo) dot com 30-May-2011 10:22


in my case i use config.php and put all the settings there including the _autoload functions. Just include the config.php in
all of your php file. Heres how:

config.php:
<?php
function __autoload($classname) {
include_once("classfolder/" . $classname . ".php");
}
?>
ClassFolder: with SampleClass.php
<?php
class SampleClass {
public function hello_rahj() {
echo "Hello rahj!";
}
}
?>
In your Typical Php File: e.g. Index.php
<?php
include("config.php")
$hello = new SampleClass();
$hello->hello_rahj(); // outputs Hello rahj!
?>
When using the __autoload functions, Make Sure you use a Proper naming Convention.
Hope this Helps!

superzouz at hotmail dot com 01-May-2011 04:19


After a while trying to get __autoload() to work, I used spl_register_autoload instead. __autoload() unexplainably failed so I
gave up on it.

T dot Alexander Lystad tal at lystadonline dot no 11-Feb-2011 07:19


This is an example of how I used autoloading in my application:
<?php
spl_autoload_register(function ($className) {
$possibilities = array(
APPLICATION_PATH.'beans'.DIRECTORY_SEPARATOR.$className.'.php',
APPLICATION_PATH.'controllers'.DIRECTORY_SEPARATOR.$className.'.php',
APPLICATION_PATH.'libraries'.DIRECTORY_SEPARATOR.$className.'.php',
APPLICATION_PATH.'models'.DIRECTORY_SEPARATOR.$className.'.php',
APPLICATION_PATH.'views'.DIRECTORY_SEPARATOR.$className.'.php',
$className.'.php'
);
foreach ($possibilities as $file) {

if (file_exists($file)) {
require_once($file);
return true;
}
}
return false;
});
?>

b dot rense at gmail dot com 01-Dec-2010 08:54


php autoloading is a b*tch, nevertheless, i think the following class is a pretty good solution.
<?php
class autoload_autoloader {
public static $instance;
private $_src=array('application/controllers/', 'application/models/', 'application/views/helpers/', 'library/');
private $_ext=array('.php', 'class.php', 'lib.php');

/* initialize the autoloader class */


public static function init(){
if(self::$instance==NULL){
self::$instance=new self();
}
return self::$instance;
}

/* put the custom functions in the autoload register when the class is initialized */
private function __construct(){
spl_autoload_register(array($this, 'clean'));
spl_autoload_register(array($this, 'dirty'));
}

/* the clean method to autoload the class without any includes, works in most cases */
private function clean($class){
global $docroot;
$class=str_replace('_', '/', $class);
spl_autoload_extensions(implode(',', $this->_ext));
foreach($this->_src as $resource){
set_include_path($docroot . $resource);
spl_autoload($class);
}
}

/* the dirty method to autoload the class after including the php file containing the class */
private function dirty($class){
global $docroot;
$class=str_replace('_', '/', $class);
foreach($this->_src as $resource){
foreach($this->_ext as $ext){
@include($docroot . $resource . $class . $ext);
}
}
spl_autoload($class);
}
}

?>
Obviously you still have to include this class the dirty way, for example:
<?php
$path='../';
$docroot=$_SERVER['DOCUMENT_ROOT'] . implode('/',array_slice(explode('/',$_SERVER['PHP_SELF']),0,-2)) . '/';
include($path . 'library/autoload/autoloader.php');
autoload_autoloader::init();
?>
please note that this autoloader class does require the $docroot variable which is the absolute path of the root of your
application, you can set it manually or copy the code i used.
my directory structure looks like this:
- www/
+ myapp/
+ application/
+ controllers/
+ models/
+ views/
+ helpers/
+ library/
+ autoload/
- autoloader.php

fka at fatihkadirakin dot com 31-Jul-2010 06:16


Or you can use this, without using any "require/include":
<?php
class autoloader {
public static $loader;
public static function init()
{
if (self::$loader == NULL)
self::$loader = new self();
return self::$loader;
}
public function __construct()
{
spl_autoload_register(array($this,'model'));
spl_autoload_register(array($this,'helper'));
spl_autoload_register(array($this,'controller'));
spl_autoload_register(array($this,'library'));
}
public function library($class)
{
set_include_path(get_include_path().PATH_SEPARATOR.'/lib/');
spl_autoload_extensions('.library.php');
spl_autoload($class);
}

public function controller($class)


{
$class = preg_replace('/_controller$/ui','',$class);

set_include_path(get_include_path().PATH_SEPARATOR.'/controller/');
spl_autoload_extensions('.controller.php');
spl_autoload($class);
}
public function model($class)
{
$class = preg_replace('/_model$/ui','',$class);

set_include_path(get_include_path().PATH_SEPARATOR.'/model/');
spl_autoload_extensions('.model.php');
spl_autoload($class);
}
public function helper($class)
{
$class = preg_replace('/_helper$/ui','',$class);
set_include_path(get_include_path().PATH_SEPARATOR.'/helper/');
spl_autoload_extensions('.helper.php');
spl_autoload($class);
}
}
//call
autoloader::init();
?>

takingsides at gmail dot com 30-Jun-2010 08:15


file_exists would work perfectly fine, unless people intentionally create directories ending with ".php". However sometimes
classes can be called either "MyClass.php" or "MyClass.class.php"...
I have a number of configuration constants defined (before the autoload function) i.e:
<?php
// in: config.php
define('DEV_MODE', 1);
$error_reporting = error_reporting(DEV_MODE ? E_ALL : 0);
define('CONF_DIR_LIB', '/path/to/classes/');
?>
Finally inside the config.php after my constants, i define the autoload...
A. DEV_MODE when 1 or true, will show all errors.
B. DEV_MODE when 0 or false, will supress ALL errors including those thrown from inside classes.
<?php
// also in: config.php
function __autoload($f)
{
if (($f1 = file_exists($c1 = CONF_DIR_LIB . "$f.class.php"))

|| ($f2 = file_exists($c2 = CONF_DIR_LIB . "$f.php")))


if (DEV_MODE)
include_once ($f1 ? $c1 : $c2);
else
@include_once ($f1 ? $c1 : $c2);
}
?>
I hope this helps anyone :)

DaWG 12-May-2010 09:21


Be careful with the use of file_exists, if there were a directory with the name ($classname . "php") then file_exists would
return true. (is_file "may" be preferred, YMMV).
<?php
if (is_file($className . '.php')) { ...
?>

ej at campbell dot name 03-Apr-2010 11:21


You don't need exceptions to figure out if a class can be autoloaded. This is much simpler.
<?php
//Define autoloader
function __autoload($className) {
if (file_exists($className . '.php')) {
require_once $className . '.php';
return true;
}
return false;
}
function canClassBeAutloaded($className) {
return class_exists($className);
}
?>

tom at r dot je 11-Mar-2010 03:30


To find out whether a class can be autoloaded, you can use autoload in this way:
<?php
//Define autoloader
function __autoload($className) {
if (file_exists($className . '.php')) require $className . '.php';
else throw new Exception('Class "' . $className . '" could not be autoloaded');
}
function canClassBeAutloaded($className) {
try {
class_exists($className);
return true;
}
catch (Exception $e) {
return false;
}
}
?>

Anonymous 08-Feb-2010 03:35


It's worth to mention, if your operating system is case-sensitive you need to name your file with same case as in source code
eg. MyClass.php instead of myclass.php

EastGhostCom 23-Dec-2009 09:04


IMPORTANT: Look into spl_autoload_register() which lets you manage a stack of several __autoload() functions.

khan at swcombine dot com 05-Nov-2009 05:38


As an addendum to #91119 I would suggest adding class_exists() into that solution. I've just implemented autoloading based on
the code provided there and ran into a problem where a file had the same name as a class, existed in the directory structure
prior to the file that had the actual class and as a result was being included first and resulting in a 'class not found'
error.
<?php
if(file_exists($path)) {
require_once $path;
if(class_exists($class_name)) {
return;
}
}
?>

h762017(at)stud(dot)u-szeged(dot)hu 20-Aug-2009 07:24


Hi,
Because the scripting engine just find the class declaration in the body of the __autoload() function, you also can declare the
missing class in the __autoload() function. (No need to include or require a file.)
Let's see the following code:
Example 1.:
<?php
function __autoload($className){
echo "Now loading: $className<br />";

class SuperClass {
}
}
class DerivedClass extends SuperClass {
}
class AnotherDerivedClass extends SuperClass {
}
?>
The scripting engine will found the SuperClass class.
Example 2.:

You also can do it with the eval function, and if you dinamycally declare the class, you don't get a Fatal Error, and you can
do many interesting things with the eval function;)
<?php
function __autoload($className){
echo "Now loading: $className<br />";

eval("class $className {}");


}
class DerivedClass extends SuperClass {
}
class AnotherDerivedClass extends SuperClass {
}
?>

Peminator 07-Jul-2009 07:01


My idea for autoloading FUNCTIONS however only in a weird way :
<?php
function ex($parms)
{
$argvar = func_get_args();
$func = $argvar[0];
$funcargs = array_slice($argvar,1);

if (function_exists($func))
{
$returnvalue = call_user_func_array($func,$funcargs);
}
else
{
$funcpath = "scripts/".$func.".php";
require_once($funcpath);

if (function_exists($func))
{
$returnvalue = call_user_func_array($func,$funcargs);
}
else
{
die "SORRY $func IS NOT USABLE";
}
}

// return returned value :-)


return $returnvalue;
}
?>
USAGE EXAMPLE:
must be caled using the X function giving the real function as first parameter, like:
$result = ex("add",1,2);
// returns 3 if add function defined in add.php sums the first and second parameter..

ranskills at yahoo dot co dot uk 26-May-2009 04:02


This custom autoload function allows for the flexibility to add directories from which the classes are expected to be found and
loads classes/interfaces with different file naming formats. Additionally, it handles classes included in the include path and
files in the PEAR package/directory.
You can check this blog entry for a video tutorial http://ranskills.com/blog/.
<?php
/**
*
* @param string $className Class or Interface name automatically
* passed to this function by the PHP Interpreter
*/
function autoLoader($className){
//Directories added here must be
//relative to the script going to use this file.
//New entries can be added to this list
$directories = array(
'',
'classes/'
);
//Add your file naming formats here
$fileNameFormats = array(
'%s.php',
'%s.class.php',
'class.%s.php',
'%s.inc.php'
);
// this is to take care of the PEAR style of naming classes
$path = str_ireplace('_', '/', $className);
if(@include_once $path.'.php'){
return;
}

foreach($directories as $directory){
foreach($fileNameFormats as $fileNameFormat){
$path = $directory.sprintf($fileNameFormat, $className);
if(file_exists($path)){
include_once $path;
return;
}
}
}
}
spl_autoload_register('autoLoader');
?>

contact at casual-web dot com 29-Apr-2009 09:22


Hi,
To include all classes from differents directories, you can specify the path in the name of class.The replace a caracter of
your choice by '/'. Here I used "_".
ex : the class : dir1_dir2_myclass.class.php will be in dir1/dir2/

<?php
function __autoload($className) {

$fullclasspath="";

// get separated directories
$pathchunks=explode("_",$className);

//re-build path without last item


for($i=0;$i<(count($pathchunks)-1);$i++) {
$fullclasspath.=$pathchunks[$i].'/';
}

require_once '../../'.$fullclasspath.$className.'.class.php';
}
?>*
bye
CasualWeb

roman dot drapeko at gmail dot com 05-Apr-2009 04:33


Hi there,
I have developed a small script, that can scan recursively folders and files ang generate array of associations between
classes/interfaces and their locations. It accepts several incoming parameters and it's very simple to use.
An example of generated array is shown bellow.
<?php
$autoload_list = array (
'classes' => array (
'A' => array ('path' => 'Project/Classes/Children/A.php',
'extends' => array (), 'implements' => array ('I1')),
'C' => array ('path' => 'Project/Classes/C.php',
'extends' => array ('B'), 'implements' => array ('I1', 'I3')),
),
'interfaces' => array (
'I2' => array ('path' => 'Project/Interfaces/blablabla.php', 'extends' => array ('I1')),
'I1' => array ('path' => 'Project/Interfaces/I1.php', 'extends' => array ()),
),
);
?>
When you know names and their locations, you know everything to load these classes.
It uses regular expressions to identify if class/interfaces is located in the current file.
I tried to post the code, but it's very long. You can download the script from http://wp.drapeko.com/store/php-autoloadingfiles/.

claude dot pache at gmail dot com 11-Mar-2009 07:04


About static classes that need initialisation before use (problem discussed by adam at greatbigmassive dot net and kalkamar at
web dot de below).

Simple problems have often simple solutions. Here is my approach:


First, my __autoload function is very simple:
<?php
function __autoload ($class_name)
{
if (preg_match('|^\w+$|', $class_name))
include "./packages/$class_name.php";
}
?>
(The "if/preg_match" line is just a simple yet robust security check. Moreover I use "include" and not
"require"/"require_once", so that if the file is not found, the __autoload function does nothing, and my script dies eventually
with a meaningful "Class 'foo' not found" fatal error.)
Now, when I define a class "foo" which requires initialisation before use, I just write the initialisation code after the
definition of the class in the file "packages/foo.php":
<?php
/** Content of file "packages/foo.php" **/
class foo
{
/* definition of the class is found here */
}
/* initialisation code of the class is found here. */
/** End of file "packages/foo.php" **/
?>
That's it. No need for an <? init() ?> or a <? __construct() ?> method.

jarret dot minkler at gmail dot com 07-Mar-2009 10:55


You should not have to use require_once inside the autoloader, as if the class is not found it wouldn't be trying to look for
it by using the autoloader.
Just use require(), which will be better on performance as well as it does not have to check if it is unique.

adam at greatbigmassive dot net 25-Feb-2009 03:31


I've been playing with the idea of automatically running the __construct() function after initiating a static/singleton class.
As we know, it doesn't run unless you create new instance() of the class which doesn't happen on the singleton method.
I've seen the methods of using the "getInstance" call but this is a manual call that I wanted to avoid. As an additional idea
I've done this and would be interested in opinions. Seems to work for me and my framework and it means I don't have to run the
__construct() manually via the internal "new self" method. Obviously, in this case, I probably don't even need to call the
booter function __construct() but for relationship recognition I have.
Basic idea
---------Make the __construct() protected instead of private.
This means an extended class can access/override it.
Then, in autoload, I use eval to extend the class I've just initiated which simply runs the parent __construct() if it exists..
<?php
function __autoload($class){
require_once(INC_FILES."/class/class.".$class.".php");

if(method_exists($class,'__construct')){
eval("class al_$class extends $class{function __construct(){parent::__construct();}}new al_$class;");
}
return true;
}
?>

pinochet dot pl at gmail dot com 04-Jan-2009 01:11


To use autoload function with namespaces you should remember to define it in main scope in "\" namespace.

zachera 31-Dec-2008 04:55


I found out a neat way to centralize one single class which will give accessibility to other classes. I also added a parameter
to the __construct method which would be an array of classes you want loaded. This isn't completely necessary, but it will
stop "excessive memory" if you're loading a bunch of unused classes.
<?php
class Bot {
private $classes = array (
'Socket' => "connection/class.Socket.php",
'Input' => "io/class.Input.php",
'Output' => "io/class.Output.php",
'Parse' => "io/parse/class.Parse.php"
);
public $Socket, $Input, $Output, $Parse; // Accessible by other classes
public function __construct($load=false){
if(is_array($load)){
foreach($load as $class){
if(isset($this->classes[$class])){
require($this->classes[$class]);
$this->$class = new $class($this);
}
}
} else {
foreach($this->classes as $class => $path){
require($path);
$this->$class = new $class($this);
}
}
}
}
?>

kalkamar at web dot de 07-Oct-2008 10:23


Because static classes have no constructor I use this to initialize such classes.
The function init will (if available) be called when you first use the class.
The class must not be included before, otherwise the init-function wont be called as autoloading is not used.
<?php
function __autoload($class_name)
{
require_once(CLASSES_PATH.$class_name.'.cls.php');
if(method_exists($class_name,'init'))
call_user_func(array($class_name,'init'));
return true;

}
?>
I use it for example to establish the mysql-connection on demand.
It is also possilbe do add a destructor by adding this lines to the function:
<?php
if(method_exists($class_name,'destruct'))
register_shutdown_function(array($class_name,'destruct'));
?>

jbarker at erepublic dot com 17-Sep-2008 08:34


In a subclass, I was trying to call an overridden parent method with an arbitrary number of arguments:
<?php
call_user_func_array(array('parent', 'someNonStaticMethod'), $args);
?>
It turns out this triggers an E_STRICT level warning. So I changed to this:
<?php
call_user_func_array(array($this, 'parent::someNonStaticMethod'), $args);
?>
This doesn't trigger any warnings, but it has the undesirable (if not downright buggy) effect of calling my __autoload()
function with the argument 'parent'. I had to modify __autoload() to handle this special situation:
<?php
function __autoload($cls)
{
if ('parent' != $cls)
{
require("class.$cls.php");
}
}
?>
Tested on Linux with PHP 5.1.6 and 5.2.5.

andrzeje from wit.edu.pl 13-Sep-2008 08:18


Throwing versions of __autoload based on eval will fail if __autoload will be caled with interface name.
<?php
/* eval+throw __autoload
*/
class Cls implements Iface {/* ... */}; // Error
?>

sebasg37 at gmail dot com 23-Aug-2008 04:09


When __autoload doesn't seem to work or if you are in PHP 4:
<?php
$include_paths = explode( PATH_SEPARATOR , get_include_path() );
foreach( $include_paths as $path ) {
if( is_dir( $path ) ) {
$d = opendir( $path );

while (false !== ($f = readdir($d))) {


if( ereg( "^.*\.php$" , $f ) && strstr( $path , ABS_PATH ) ) { ## avoid PEAR and other files for automatic
requirement
require_once $f;
}
}
closedir($d);
}
}
// replace ABS_PATH with your app root
?>

matias dot cohen at gmail dot com 01-Aug-2008 04:33


Another way of throwing exceptions inside an __autoload() function:
<?php
function myExceptionHandler($e) {
// Add code here
}
set_exception_handler('myExceptionHandler');
function __autoload($class) {
if (class_exists($class, false) || interface_exists($class, false)) {
return;
}
try {
@require_once('path/to/' . $class . '.php');
if (!class_exists($class, false) || !interface_exists($class, false)) {
throw new Exception('Class ' . $class . ' not found');
}
}
catch (Exception $e) {
myExceptionHandler($e);
}
}
?>

chris (at) xeneco (dot) co (dot) uk 04-Jul-2008 06:21


I'm very taken with the autoload function, and thought I would share with you my implementation of it:
<?php
function __autoload($class_name) {
//my settings class is a singleton instance that has parsed an ini file containing the locations of all classes
$settings = Settings::Load();
$classes = $settings->getSettings('classes');
$path = $classes[$class_name];

if(file_exists($path)) {
require_once($path);
return true;
} else {

clearstatcache();
$classes = $settings->ReLoadSettings();
$path = $classes['classes'][$class_name];
}

if(file_exists($path)) {
require_once($path);
return true;
} else {
die("The requested library,".$class_name.", could not be found at ".$classes[$class_name][$i].". Please check your ini
file");
}
}
?>

Chris Continanza 29-Apr-2008 11:43


Decided to warm up to autoload,
but wanted it to use the include_path.
Good default behavior.
function __autoload($class_name) {
$include_path = get_include_path();
$include_path_tokens = explode(':', $include_path);

foreach($include_path_tokens as $prefix){
$path = $prefix . '/' . $class_name . '.php';
if(file_exists($path)){
require_once $path;
return;
}
}
}

james dot dot dot dunmore at gmail dot com 18-Apr-2008 04:43
Andrew: 03-Nov-2006 12:26
That seems a bit messy to me, this is a bit neater:
<?php
function __autoload($class_name)
{
//class directories
$directorys = array(
'classes/',
'classes/otherclasses/',
'classes2/',
'module1/classes/'
);

//for each directory
foreach($directorys as $directory)
{
//see if the file exsists
if(file_exists($directory.$class_name . '.php'))
{
require_once($directory.$class_name . '.php');
//only require the class once, so quit after to save effort (if you got more, then name them something else

return;
}
}
}

jjfitzgerald at gmail dot com 30-Jan-2008 07:39


Regardless of the situation you're in (developing a web-app or writing some code that may use someone else's web-app), always
a good idea not to use __autoload() but instead write a differently-named function and register it as an autoloader:
<?php
function class_autoloader($c) {
if(file_exists(dirname(__FILE__). "/classes/{$c}.php") && include_once(dirname(__FILE__). "/classes/{$c}.php")) {
return true;
} else {
trigger_error("Could not load class '{$c}' from file '{$c}.php'", E_USER_WARNING);
return false;
}
}
spl_autoload_register("class_autoloader");
?>
Using spl_autoload_register(), the function class_autoloader() will now be used when classes are instantiated, just like
__autoload() does, but without the potential conflict with other web-apps __autoload() function.

muratyaman at gmail dot com 28-Jan-2008 07:57


__autoload() function can be very useful to optimize your code esp. when you have so many classes.
Unlike class extensions, optional parameters with class restrictions may not load your class.
<?php
class bClass{
function fun($p1, aClass $p2=NULL){
//do something
}
}
//depending on the usage
$b = new bClass();
$b->fun('No!');//this will not load class file for aClass
$b->fun('Really?', new aClass('Yes!'));//this will
?>
So, it's very encouraging to use classes everywhere!
Even encapsulating your functions inside simple classes to use like static modules, will help a lot!
Let's say, you have <b>50k</b> lines of code inside <b>100</b> classes/files.. If you need a simple task to do very quickly,
you should not be loading all of those files, except the ones you need.
Though, it may be dangerous on some cases regarding the dependencies, load order, etc. Carefully design your classes.

Mexi-Fry 16-Jan-2008 05:19

Seems like a strange layer of obscurity to me (to be honest). It would be really handy if that could be implemented and
remain in memory though, enabling pages to instantiate classes without having to repeatedly include documents. Being able to
construct an object without having to include the document that contained it (AND without having to include that function in
some form on each document) would be very nice.

boltclock aInACircle NOVALISTIC dot com 11-Jan-2008 09:31


You can allow __autoload() to throw exceptions without resulting in fatal errors by trying class_exists(), literally.
<?php
function __autoload($class)
{
if (file_exists($file = "./inc/$class.php"))
{
include($file);
}
else
{
throw new Exception("Class $class not found");
}
}
// By 'literally', I mean this
try
{
// Since the second argument defaults to true, __autoload()
// will be called from this function
class_exists('MyClass');
}
catch (Exception $e)
{
// Catch the exception and handle it as usual
die($e->getMessage());
}
// Safely initialize an object from the class
$class = new MyClass();
?>

ostapk 19-Dec-2007 02:46


To sandrejev at gmail dot com below:
if you create the exception in the __autoload() and serialize it, then when you try to access the same missing class later (in
another place in the code), then the exception will contain invalid stack trace.
Also, here's an excellent blog post that discusses the consequences of using eval() as well as provides an example to handle
static method calls and namespaces: http://www.onphp5.com/article/61

richard [at ] xanox [dot] net 05-Dec-2007 07:46


I've made this little script here which looks in a dir, and loads all the classed, and includes their files.
$myDirectory = opendir("required/classes");
// get each entry

while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
// close directory
closedir($myDirectory);
// count elements in array
$indexCount = count($dirArray);
sort($dirArray);
for($index=0; $index < $indexCount; $index++) {
if($dirArray[$index] != '.' AND $dirArray[$index] != '..') {
include("required/classes/$dirArray[$index]");
$classname = strtolower($dirArray[$index]);
$classname = str_replace('.php','',$classname);
$classinit = str_replace('.php','',$dirArray[$index]);
$$classname = new $classinit;
}
}

rojoca 04-Oct-2007 08:38


Be careful when using eval (as always) in __autoload. The following:
<?php
echo 'Start->';
function __autoload($class) {
eval('class ' . $class . ' {};');
}
$class = 'Class1{}; echo "uh oh"; class Class2';
$obj = new $class;
echo 'end';
?>
outputs:
Start->uh oh
You can use preg_replace to clean up $class to prevent executing abitrary code but in this case you won't be able to throw a
catchable exception and your script will end with a fatal error.

christian.reinecke at web.de 23-Sep-2007 09:28


do not use is_subclass_of() in your __autoload() function to identify a class type and thereby its path (f.e exceptions).
is_subclass_of() needs to know the class, but you want to check BEFORE you include the class.

knoopx at gmail dot com 06-Sep-2007 12:56


Quick and easiest way to be able to throw exceptions on __autoload() method:
<?php

function __autoload($class_name) {
find_file($class_name); //your own routine to locate the class file
if (!class_exists($class_name, false)) {
eval("class $class_name {}");
throw new Exception('Class not found');
}
}
?>

rlee0001 at sbcglobal dot net 30-Aug-2007 01:16


If you would like __autoload to throw an exception when the class cannot be loaded instead of causing a fatal error, consider
this:
<?php
function __autoload ($className)
{
$fileName = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
$status = (@include_once $fileName);

if ($status === false) {
eval(sprintf('class %s {func' . 'tion __construct(){throw new Project_Exception_AutoLoad("%s");}}', $className,
$className));
}
}
$pageController = 'Project_My_Class'; // "Project/My/Class.php"
try {
$obj = new $pageController();
} catch (Project_Exception_AutoLoad $e) {
header('HTTP/1.0 404 Not Found');
printf('<h1>Not Found</h1><p>The requested page %s was not found on this server.</p><hr /><em>$id$</em>',
$_SERVER['REQUEST_URI']);
}
?>

emcmanus at gmail dot com 16-Jul-2007 06:04


Note: if you're experiencing unexpected "failed opening required 'filename.php' (include..." errors:
If you placed your autoload function in an external file which you're requiring at the head of every script, be cautious of
some odd behavior regarding PHP's idea of the current working directory.
I ran into some unexpected path issues when my include file was placed in a subdirectory directory. The solution to my problems
was to make sure that the autoload script being included is in the same directory as the calling script.

peter dot gooman at gmail dot com 17-Jun-2007 08:33


Before you start using __autload, remember that it holds no scope/namespace. This means that if you are depending on third
party applications and they have an autoload function defined and so do you, your application will error.
To remedy this, everyone should look at the spl_autoload functions, eg: spl_autoload_register. This function allows more than
one custom functions to be called through the default spl_autoload (default __autoload) handler.

Andrea Giammarchi 21-Mar-2007 03:54

Another workaround for Exception problem (Klaus Schneider style)


<?php
define('CLASS_DIR', 'php/classes/');
function __autoload($name) {
if($exists = !class_exists($name) && file_exists($class = CLASS_DIR.$name.'.class.php'))
require $class;
elseif(!$exists) {
eval('class '.$name.' extends Exception {}');
throw new $name('[__autoload] this file doesn\'t exists: '.$class);
}
}
try {
new Undefined;
}
catch(Undefined $e) {
echo $e->getMessage();
}
// You should use generic Exception too
catch(Exception $e) {
echo $e->getMessage();
}
?>

Klaus Schneider 01-Mar-2007 07:35


I just stumbled over one quite nice solution to the __autoload-exception problem. It allows for any kind of exception to be
thrown inside __autoload().
It appears one has to define the requested class (using "eval", which is not nice but inevitable here) and after that can
simply throw an exception (and catch it if so desired):
<?php
function __autoload($className)
{
// Do your stuff to load a class here, set $ok if everything went fine.
if (! $ok) {
eval("class $className{};");
throw new Exception('My message');
} // if
}
try {
UndefinedClass::undefinedFunction();
} catch (Exception $ex) {
echo $ex->getMessage();
} // try/catch
?>
Output: "My Message".
:-)

david dot thalmann at gmail dot com 02-Feb-2007 07:19


Note to Ricos posting:
A lot of useless Coding. However, I improved the code, so now it will be able to find any folders ("." and ".." will not being

tested... oO) and search as deep as possible. Now it will find CLASS_DIR/foo/bar.class.php also like
CLASS_DIR/foo/bar/baz/buz/fii/and/so/on/class.php
Warning: This code will check ALL dirs who're "deeper" / "lower" than the class dir, so prevent deeply hidden files (or use
just a few folders).
Improved Version:
<?php
// change this, if this code isn't "higher" than ALL classfiles
define("CLASS_DIR", dirname(__FILE__));
/**
* autoload classes (no need to include them one by one)
*
* @uses classFolder()
* @param $className string
*/
function __autoload($className) {
$folder = classFolder($className);
if($folder)
require_once($folder.$className.".class.php");
}
/**
* search for folders and subfolders with classes
*
* @param $className string
* @param $sub string[optional]
* @return string
*/
function classFolder($className, $sub = "/") {
$dir = dir(CLASS_DIR.$sub);

if(file_exists(CLASS_DIR.$sub.$className.".class.php"))
return CLASS_DIR.$sub;
while(false !== ($folder = $dir->read())) {
if($folder != "." && $folder != "..") {
if(is_dir(CLASS_DIR.$sub.$folder)) {
$subFolder = classFolder($className, $sub.$folder."/");

if($subFolder)
return $subFolder;
}
}
}
$dir->close();
return false;
}
?>

Rico 04-Jan-2007 05:00


This autoload function searches for the class Location before requiring it. So there's no need of putting the classes all in
one folder.

Requirements:
- the subfolders must be at least 3 letters long
- the filenames must be in the form CLASSNAME.class.php
Note:
- in this example the main class folder is 'lib'
define('ROOT_DIR', dirname(__FILE__).'/');
function __autoload($className) {
$folder=classFolder($className);
if($folder) require_once($folder.'/'.$className.'.class.php');
}
function classFolder($className,$folder='lib') {
$dir=dir(ROOT_DIR.$folder);
if($folder=='lib' && file_exists(ROOT_DIR.$folder.'/'.$className.'.class.php')) return $folder;
else {
while (false!==($entry=$dir->read())) {
$checkFolder=$folder.'/'.$entry;
if(strlen($entry)>2) {
if(is_dir(ROOT_DIR.$checkFolder)) {
if(file_exists(ROOT_DIR.$checkFolder.'/'.$className.'.class.php')) return $checkFolder;
else {
$subFolder=classFolder($className,$checkFolder);
if($subFolder) return $subFolder;
}
}
}
}
}
$dir->close();
return 0;
}

sandrejev at gmail dot com 08-Nov-2006 11:23


Here is the most complete version of __autoload exception i guess.
The best thing is that it can throw any exception plus the exception is fully functional.
<?php
class AutoloadException extends Exception { }
class AutoloadExceptionRetranslator extends Exception
{
public function __construct($serializedException)
{
throw unserialize($serializedException);
}
}
function __autoload($classname)
{
if(!file_exists($classname))
{
$autoloadException = serialize(new AutoloadException("Class $classname could not be found"));
return eval("
class $classname

{
function __construct(\$a=0, \$b=0, \$c=0, \$d=0, \$e=0, \$f=0, \$g=0, \$h=0, \$i=0)
{
throw new AutoloadExceptionRetranslator('$autoloadException');
}
}
");
}
else
{
require_once $classname;
}
}
try
{
$anyObject = new AnyNonExistantClass();
}
catch (AutoloadException $e)
{
print_r($e->getTrace());
}
?>

andrew dot delete dot cornes at gmail dot delete dot com 03-Nov-2006 04:26
If you'd like '__autoload()' to support multiple class folders, each containing multiple class files (one per class), you may
want to try something like this (file '__autoload.php'):
<?php
define('CLASS_FILENAME_SUFFIX', '.class.php');
function __autoload($className)
{
$__autoloadAbsolutePath = dirname(__FILE__);
// 'pathStart' is your web application root folder.
// (This may or may not be where '__autoload.php'
// resides; let's assume here that it resides one
// level 'below' the web app root.)
$pathStart = $__autoloadAbsolutePath .
DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR;
// 'classPath' is a list of class folders to look in.
// (In this example, there's just one: 'classlibs/lib1'.
// To add more, simply append them; start with
// 'PATH_SEPARATOR . $pathStart .', and off you go...)
$classPath = PATH_SEPARATOR . $pathStart .
'classlibs' . DIRECTORY_SEPARATOR . 'lib1';
// Add list of class folders to 'include_path' for the
// forthcoming 'require()' (or similar directive).
$oldIncludePath = get_include_path();
set_include_path($oldIncludePath . $classPath);
require_once($className . CLASS_FILENAME_SUFFIX);
// Reinstate initial 'include_path'.

set_include_path($oldIncludePath);
}
?>
As your web application develops, new paths containing class files can be added into the '$classPath' variable within
'__autoload()'. If hard-coding the '$classPath' variable isn't to your taste, you could arrange for its value to come from
'outside' in whatever way you like.
Any comments gratefully received.

Chris Corbyn (chris AT w3style.co.uk) 08-Sep-2006 06:23


I'm sure this is needed by more than me.
My objective was to allow __autoload() to be easily extended in complex systems/frameworks where specific libraries etc may
need loading differently but you don't want to hard-code little adjustments into your working __autoload() to allow this to
happen.
Using a ServiceLocator object with some static methods and properties to allow loosely coupled locators to be attached to it
you can swap/change and add to the functionality of your __autoload() at runtime.
The core stuff:
<?php
/**
* Defines the methods any actual locators must implement
* @package ServiceLocator
* @author Chris Corbyn
*/
interface Locator
{
/**
* Inform of whether or not the given class can be found
* @param string class
* @return bool
*/
public function canLocate($class);
/**
* Get the path to the class
* @param string class
* @return string
*/
public function getPath($class);
}
/**
* The main service locator.
* Uses loosely coupled locators in order to operate
* @package ServiceLocator
* @author Chris Corbyn
*/
class ServiceLocator
{
/**
* Contains any attached service locators
* @var array Locator
*/
protected static $locators = array();


/**
* Attach a new type of locator
* @param object Locator
* @param string key
*/
public static function attachLocator(Locator $locator, $key)
{
self::$locators[$key] = $locator;
}
/**
* Remove a locator that's been added
* @param string key
* @return bool
*/
public static function dropLocator($key)
{
if (self::isActiveLocator($key))
{
unset(self::$locators[$key]);
return true;
}
else return false;
}
/**
* Check if a locator is currently loaded
* @param string key
* @return bool
*/
public static function isActiveLocator($key)
{
return array_key_exists($key, self::$locators);
}
/**
* Load in the required service by asking all service locators
* @param string class
*/
public function load($class)
{
foreach (self::$locators as $key => $obj)
{
if ($obj->canLocate($class))
{
require_once $obj->getPath($class);
if (class_exists($class)) return;
}
}
}
}
/**
* PHPs default __autload
* Grabs an instance of ServiceLocator then runs it
* @package ServiceLocator
* @author Chris Corbyn
* @param string class
*/
function __autoload($class)
{
$locator = new ServiceLocator();

$locator->load($class);
}
?>
An example Use Case:
<?php
require 'ServiceLocator.php';
//Define some sort of service locator to attach...
class PearLocator implements Locator
{
protected $base = '.';

public function __construct($directory='.')


{
$this->base = (string) $directory;
}

public function canLocate($class)


{
$path = $this->getPath($class);
if (file_exists($path)) return true;
else return false;
}

public function getPath($class)


{
return $this->base . '/' . str_replace('_', '/', $class) . '.php';
}
}
// ... attach it ...
ServiceLocator::attachLocator(new PearLocator(), 'PEAR');
// ... and code away....
$foo = new Foo_Test();
?>

gonix 03-Aug-2006 06:39


in response to alexey at renatasystems dot org:
You may add ``global $somedata;`` before ``$somedata = 'Some data';`` and it should work as expected.
file bar.class.php:
<?php
global $somedata;
$somedata = 'Some data'; /* global scope in common way */
class bar {
function __construct()
{
global $somedata; /* reference to global scope variable */


if ( isset($somedata) )
{
var_dump($somedata);
}
else
{
die('No data!');
}
}
}
?>
'common way':
<?php
require 'bar.class.php';
$foo = new bar();
?>
'__autoload way':
<?php
function __autoload($classname)
{
require $classname . '.class.php';
}
$foo = new bar();
?>
Both 'comon way' and '__autoload way' should give same result:
string(9) "Some data"

alexey at renatasystems dot org 06-Jul-2006 12:15


While using an "autoloading" method you should pay attention to variables scope. Because of new file will be included INSIDE of
magic function __autoload - all of declared in such file global scope variables will be only available within this function and
nowhere else. This will cause strange behaviour in some cases. For example:
file bar.class.php:
<?php
$somedata = 'Some data'; /* global scope in common way */
class bar {
function __construct()
{
global $somedata; /* reference to global scope variable */

if ( isset($somedata) )
{
var_dump($somedata);
}

else
{
die('No data!');
}
}
}
?>
Attempt to load this file in common way:
<?php
require 'bar.class.php';
$foo = new bar();
?>
this will output (as expected):
string(9) "Some data"
But in case of __autoload:
<?php
function __autoload($classname)
{
require $classname . '.class.php';
}
$foo = new bar();
?>
you could expect that this script will return the same but no, it will return "No data!", because defenition of $somedata after
requiring treats as local within user-defined function __autoload().

RQuadling at GMail dot com 08-Mar-2006 12:55


An issue I've had with using the __autoload function is getting it into the application.
You have to have the function included in every topmost script. This is a pain if the entire application is OOP and an "app"
can be just a component of another "app".
A solution I've found is to use php.ini's auto_prepend_file setting.
Mine is set to ...
auto_prepend_file = auto_loader.php
The auto_loader.php script contains a single function. The __autoload() function.
The include_dir path IS examined to find this file, so you can just put it with the rest of your includable files.
A useful additional facility here is that you could log which classes are used by a script at runtime. Very useful if you have
object factories and can't know the load at design time.
Also, assigning the uncaught exception handler and the error handlers in this file means your entire site WILL have some global

protection without you having to deal with it on a script by script basis.


If you do not have access to the PHP.INI file, or you are running on a shared server, you may not be able to set this
property. In those cases, you may be able to set the value using .htaccess. (NOTE: UNTESTED as I don't use Apache).
<IfModule mod_php5.c>
php_value auto_prepend_file "auto_loader.php"
</IfModule>
You COULD therefore have a different set of rules per subdomain (if you have multiple subdomains, say, live, test, beta, devel)
or whatever takes your fancy.
For more details on this see the "Description of core php.ini directives" (http://www.php.net/manual/en/ini.core.php)

dave60 /at/ gmail /dot/ com 29-Dec-2005 01:25


In reply to quetzalcoatl:
Generally, I would advise for each class to have it's own file, and hold nothing besides that class. Just define __autoload()
in a/the infrastructure file -- a/the file that does the behavioral logic, and there should be no need to redefine it in a
class' file.

me at mydomain dot com 11-Nov-2005 04:07


You can enable this behaviour for undefined classes while unserializing objects by setting the .ini-variable
'unserialize_callback_func' to '__autoload'.

php at kaiundina dot de 20-Sep-2005 11:42


The autoload-feature allows to add the behavior of static constructors (like in C#). Static constructors should be called on
the first occurence of a class reference - typically a 'new' operator or a static call to a class's operation.
They can be used used to initialize complex static properties.
And here is an easy and save way how it can be done:
Content of MyClass.class.php5:
<?php
// demo class persisting of a static and a dynamic constructor
class MyClass
{

// static constructor operation


public static function _construct()
{
// just say hello
echo '<div>static constructor</div>';
}

// default dynamic constructor operation


public function __construct()
{
// just say hello
echo '<div>dynamic constructor</div>';
}

?>
Content of index.php5:
<?php
// declare handler for any unknown class request
function __autoload($aClassName)
{
// load the class
require_once ($aClassName . '.class.php5');
// create a reference to the static constructor's operation
$staticConstructorReference = array($aClassName, '_construct');

// if the static constructor was declared properly...


if (is_callable($staticConstructorReference))
{
// call the static constructor
call_user_func($staticConstructorReference);
}
}
// create an example object to see both constructors being executed
$article = new MyObject();
?>

scott at webscott dot com 04-May-2005 05:40


__autoload() seems to work when saving objects as session variables as well:
classLoader.php
<?php
function __autoload($className) {
require_once("$className.php");
}
?>
testClass.php
<?php
class testClass {
function __construct($propValue) {
$this->prop1 = $propValue;
}
function showProp() {
return $this->prop1;
}
}
?>
page1.php
<?php
require_once('classLoader.php');
session_start();
$_SESSION['testObj'] = new testClass('foo');
echo '<a href="page2.php">Go to page 2</a>';
?>

page2.php
<?php
require_once('classLoader.php');
session_start();
echo $_SESSION['testObj']->showProp(); // displays foo
?>
Works with multiple session objects as well. Tested on a Win2k/IIS machine.

trini0 01-Feb-2005 08:04


Be careful with using that eval() trick within __autoload().
If you use reflection in your code, the so called trick,
*can* provide ill side effects.
For example ->
$reflection = new reflectionClass('some_class');
if (FALSE === $reflection->isSubClassOf('another_class'))
{
throw new Exception('Class "some_class" must extend base class "another_class"');
}
If the real class "another_class" doesnt exist at the time, or "some_class" doesn't extend "another_class", with the reflection
test, the so called eval() trick, creates a dummy "another_class",
thereby making the reflection test useless...

petyo()architect . bg 30-Jan-2005 01:27


The following function may be useful if you want to simulate namespaces and autoloading behavior:
define ("CLASS_ROOT", '/classes/');
function __autoload ($className)
{
require_once CLASS_ROOT.str_replace('_', '/', $className).'.class.php';
}
Then you will just have to use the folder structure and name the classes accordingly. If you want to have a class named Page,
which will be in the pseudo namespace System.Web.UI, create a directory named System in /classes, then create Web, then UI,
then name the class System_Web_UI_Page. Kind of long to type if you don't have autocomplete, but at least you will not have to
manage the loading of all the classes' definitions.

thomas dot revell at uwe dot ac dot uk 27-Jan-2005 06:31


If you want to throw an exception if a class isn't defined yet, use class_exists ():
<?php
// See if the class is defined
if (!class_exists ($className, false)) {
throw new Exception ("Class $className is not defined.");
}
?>
The second parameter indicates whether or not the __autoload () function should be called before checking for the class's
existence.

nhartkamp at eljakim dot N0SP4M dot nl 11-Dec-2004 09:14

The following might provide a good work-around for throwing exceptions from the __autoload function when a file containing the
correct class doesn't exists.
function __autoload ($class_name) {
$file = 'system/objects/' . $class_name . '.inc.php';
if (!file_exists ($file)) {
return eval ("class $class_name {" .
" function $class_name () {" .
" throw new Exception ();" .
" }" .
"}");
}
require_once ($file);
}
Cheers,
Nolan

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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
classBaseClass{
function__construct(){
print"InBaseClassconstructor\n";
}
}
classSubClassextendsBaseClass{
function__construct(){
parent::__construct();
print"InSubClassconstructor\n";
}
}
$obj=newBaseClass();
$obj=newSubClass();
?>

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.
Unlike with other methods, PHP will not generate an E_STRICT level error message when __construct() is
overridden with different parameters than the parent __construct() method has.
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer
be treated as constructor. This change doesn't affect non-namespaced classes.
Example #2 Constructors in namespaced classes
<?php
namespaceFoo;
classBar{
publicfunctionBar(){
//treatedasconstructorinPHP5.3.0-5.3.2
//treatedasregularmethodasofPHP5.3.3
}
}
?>

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 there are no other references to a particular object, or in any order
during the shutdown sequence.
Example #3 Destructor Example
<?php
classMyDestructableClass{
function__construct(){
print"Inconstructor\n";
$this->name="MyDestructableClass";
}
function__destruct(){
print"Destroying".$this->name."\n";
}
}
$obj=newMyDestructableClass();
?>

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.
The destructor will be called even if script execution is stopped using exit(). Calling exit() in a destructor will
prevent the remaining shutdown routines from executing.
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.

User Contributed Notes

Constructors and Destructors

Per Persson 09-May-2012 01:57


As of PHP 5.3.10 destructors are not run on shutdown caused by fatal errors.
For example:
<?php
class Logger
{
protected $rows = array();
public function __destruct()

{
$this->save();
}
public function log($row)
{
$this->rows[] = $row;
}
public function save()
{
echo '<ul>';
foreach ($this->rows as $row)
{
echo '<li>', $row, '</li>';
}
echo '</ul>';
}
}
$logger = new Logger;
$logger->log('Before');
$nonset->foo();
$logger->log('After');
?>
Without the $nonset->foo(); line, Before and After will both be printed, but with the line neither will be printed.
One can however register the destructor or another method as a shutdown function:
<?php
class Logger
{
protected $rows = array();
public function __construct()
{
register_shutdown_function(array($this, '__destruct'));
}

public function __destruct()


{
$this->save();
}

public function log($row)


{
$this->rows[] = $row;
}

public function save()


{
echo '<ul>';
foreach ($this->rows as $row)
{
echo '<li>', $row, '</li>';
}
echo '</ul>';
}

}
$logger = new Logger;
$logger->log('Before');
$nonset->foo();
$logger->log('After');
?>
Now Before will be printed, but not After, so you can see that a shutdown occurred after Before.

philipwaynerollins at gmail dot com 21-Dec-2011 08:51


With the destructor if you're going to write to a file make sure you have the full file path and not just the filename, it
seems PHP switches the working directory to the apache root directory when exiting the script.

kapsonfire at gmx dot de 05-Dec-2011 01:50


If you use __destruct in your script manually it's not automatically unset the $vars inside the the script.
For that you can use following script to clean up the class.
<?php
public function __destruct() {
foreach ($this as $key => $value) {
unset($this->$key);
}
}
?>

david dot scourfield at llynfi dot co dot uk 12-Aug-2011 04:17


Be aware of potential memory leaks caused by circular references within objects. The PHP manual states "[t]he destructor
method will be called as soon as all references to a particular object are removed" and this is precisely true: if two objects
reference each other (or even if one object has a field that points to itself as in $this->foo = $this) then this reference
will prevent the destructor being called even when there are no other references to the object at all. The programmer can no
longer access the objects, but they still stay in memory.
Consider the following example:
<?php
header("Content-type: text/plain");
class Foo {

/**
* An indentifier
* @var string
*/
private $name;
/**
* A reference to another Foo object
* @var Foo
*/
private $link;
public function __construct($name) {
$this->name = $name;

}
public function setLink(Foo $link){
$this->link = $link;
}
public function __destruct() {
echo 'Destroying: ', $this->name, PHP_EOL;
}
}
// create two Foo objects:
$foo = new Foo('Foo 1');
$bar = new Foo('Foo 2');
// make them point to each other
$foo->setLink($bar);
$bar->setLink($foo);
// destroy the global references to them
$foo = null;
$bar = null;
// we now have no way to access Foo 1 or Foo 2, so they OUGHT to be __destruct()ed
// but they are not, so we get a memory leak as they are still in memory.
//
// Uncomment the next line to see the difference when explicitly calling the GC:
// gc_collect_cycles();
//
// see also: http://www.php.net/manual/en/features.gc.php
//
// create two more Foo objects, but DO NOT set their internal Foo references
// so nothing except the vars $foo and $bar point to them:
$foo = new Foo('Foo 3');
$bar = new Foo('Foo 4');
// destroy the global references to them
$foo = null;
$bar = null;
// we now have no way to access Foo 3 or Foo 4 and as there are no more references
// to them anywhere, their __destruct() methods are automatically called here,
// BEFORE the next line is executed:
echo 'End of script', PHP_EOL;
?>
This will output:
Destroying: Foo 3
Destroying: Foo 4
End of script
Destroying: Foo 1
Destroying: Foo 2
But if we uncomment the gc_collect_cycles(); function call in the middle of the script, we get:
Destroying: Foo 2

Destroying: Foo 1
Destroying: Foo 3
Destroying: Foo 4
End of script
As may be desired.
NOTE: calling gc_collect_cycles() does have a speed overhead, so only use it if you feel you need to.

misha at gmail dot com 08-Jul-2011 12:30


This is kinda weird to me as it is not obvious behavior....
Initiating constructor having no arguments, using call with parameters will not throw error/warning.
<?php
class A {
# no arguments constructor
function __construct() {
echo "WierdoO";
}
}
$param = 1;
$a = new A( $param );
?>
// Output "WierdoO"
Notice that this anomaly is observed only for No Argument Constructor case.

boukeversteeg at gmail dot com 11-Apr-2011 07:12


Php 5.3.3 had a very strange bug, related to __destruct, but this bug was fixed in 5.3.6. This bug happened to me and it took
me forever to figure it out, so I wanted to share it.
In short, don't unset properties in __destruct():
<?php
class Foobar {
public $baz;
function __destruct() {
# Don't do either of these, if $baz also has a __destruct()!
$this->baz = null;
unset($this->baz);

# Instead, don't clear it at all, or do this:
$this->baz->__destruct();
}
}
?>
If you made this mistake, this might happen in php<5.3.6:
<?php
# Some function that throws an exception
function fail($foobar) {
throw new Exception("Exception A!");

}
$foobar = new Foobar();
$foobar->baz = new Foobar();
try {
fail($foobar); // Send foobar to func that throws an Exception
} catch( Exception $e ) {
print $e->getMessage(); // Exception A will be caught and printed, as expected.
}
$foobar = null; // clearing foobar, and its property $baz
try {
print 'Exception B:';// this will be printed
// output stops here.
throw new Exception("Exception B!");
} catch( Exception $e ) {
print $e->getMessage(); // doesn't happen
}
print 'End'; // this won't be printed
?>

phenixdoc at gmail dot com 11-Mar-2011 04:26


multiple constructors with type signetures (almost overloading):
<?php
public function __construct() {
$args = func_get_args();
$argsStr = '';
foreach ($args as $arg) {
$argsStr .= '_' . gettype($arg);
}
if (method_exists($this, $constructor = '__construct' . $argsStr))
call_user_func_array(array($this, $constructor), $args);
else
throw new Exception('NO CONSTRUCTOR: ' . get_class() . $constructor, NULL, NULL);
}
public function __construct_integer($a) {}
public function __construct_string($a) {}
public function __construct_integer_string($a, $b) {}
public function __construct_string_integer($a, $b) {}
?>

gratcypalma at gmail dot com 19-Nov-2010 11:46


here is my multiple constructor.
<?php
class foo {
protected $mam = 'mamam';
function __construct() {
echo 'foo';
}
}
class bar extends foo {

function __construct() {
parent:: __construct(); // use parent method to call parent class
echo 'bar';
}
}
class foobar extends bar {
function __construct() {
parent:: __construct();
echo 'foobar';
}
}
$show = new foobar();
/* result is foobarfoobar */
?>

rayro at gmx dot de 14-Sep-2010 03:35


the easiest way to use and understand multiple constructors:
<?php
class A
{
function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this,$f='__construct'.$i)) {
call_user_func_array(array($this,$f),$a);
}
}

function __construct1($a1)
{
echo('__construct with 1 param called: '.$a1.PHP_EOL);
}

function __construct2($a1,$a2)
{
echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
}

function __construct3($a1,$a2,$a3)
{
echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
}
}
$o = new A('sheep');
$o = new A('sheep','cat');
$o = new A('sheep','cat','dog');
// results:
// __construct with 1 param called: sheep
// __construct with 2 params called: sheep,cat
// __construct with 3 params called: sheep,cat,dog
?>

maramirezc WHERE star-dev DOTTED com 21-Jul-2010 02:14

Another way to emulate multiple constructors:


<?php
class MyClass {
// use a unique id for each derived constructor,
// and use a null reference to an array,
// for optional parameters
function __construct($id="", $args=null) {
// parent constructor called first ALWAYS
parent::__construct();
echo "main constructor\n";
// avoid null or other types
$id = (string) $id;
// allow default constructor
if ($id == "") {
$id = "default";
}
// just in case, use lowercase id
$id = "__cons_" . strtolower($id);
$rc = new ReflectionClass("MyClass");
if (!$rc->hasMethod($id) {
echo "constructor $id not defined\n";
}
else {
// using "method references"
$this->$id($args);
}
$rc = null;
} // function __construct
// ALWAYS HAVE A default constructor,
// that ignores arguments
function __cons_default($args=null) {
echo "Default constructor\n";
}
// may have other constructors that expect different
// argument types or argument count
function __cons_min($args=null) {
if (! is_array($args) || count($args) != 2) {
echo "Error: Not enough parameters (Constructor min(int $a, int $b)) !!!\n";
}
else {
$a = (int) $args[0];
$b = (int) $args[1];
$c = min($a,$b);
echo "Constructor min(): Result = $c\n";
}
}
// may use string index (associative array),
// instead of integer index (standard array)

function __cons_fullname($args=null) {
if (! is_array($args) || count($args) < 2) {
echo "Error: Not enough parameters (Constructor fullname(string $firstname, string $lastname)) !!!\n";
}
else {
$a = (string) $args["firstname"];
$b = (string) $args["lastname"];
$c = $a . " " . $b;
echo "Constructor fullname(): Result = $c\n";
}
}
} // class
// --> these two lines are the equivalent
$obj1 = new TestClass();
$obj2 = new TestClass("default");
// --> these two are specialized
// should be read as "$obj3 = new TestClass, min(99.7, 99.83);"
$obj3 = new TestClass("min", array(99.7, 99.83));
// should be read as "$obj4 = new TestClass, fullname("John", "Doe");"
$obj4 = new TestClass("fullname", array("firstname" => "John", "lastname" => "Doe"));
// --> these two lack parameters
$obj5 = new TestClass("min", array());
$obj6 = new TestClass("fullname");
?>

alon dot peer at gmail dot com 20-Jun-2010 02:39


Another way to overcome PHP's lack of multi constructors support is to check for the constructor's parameters' type and variate
the operation accordingly. This works well when the number of parameters stays the same in all your constructors' needs.
Example:
<?php
class Articles {
private $_articles_array;
public function __construct($input) {
if (is_array($input)) {
// Initialize articles array with input.
}
else if ($input instanceof SimpleXMLElement) {
// Initialize articles array by parsing the XML.
}
else {
throw new Exception('Wrong input type');
}
}
}

?>

Anonymous 10-Jun-2010 04:50


Be careful when using a class as reference or copy in another one in regard of the __destruct() method:
<?php
class MyMainClass {
private $tables = array();
public function __construct() {
echo "Create ",get_class($this), " Object!<br>";
}
public function __destruct() {
echo "Destroy ",get_class($this)," Object!<br>";
}
public function &getSubClass($name) {
if(!isset($this->tables[$name])) {
# This will result in NOT calling the __destruct() method when
# unsetting an objct of MyMainClass
$this->tables[$name] = new MySubClass($this, $name);
# If you clone the class (for testing) it will work as expected
// $this->tables[$name] = new MySubClass(clone $this, $name);
}
return $this->tables[$name];
}
}
class MySubClass {
private $name = null;
private $main_class = null;
public function __construct(MyMainClass &$main_class, $name) {
echo "Create ",get_class($this), " '$name' Object!<br>";
$this->name = $name;
$this->main_class = $main_class;
}
public function __destruct() {
echo "Destroy ",get_class($this)," '$this->name' Object!<br>";
}
}
$my = new MyMainClass($logger);
$my->getSubClass('bar');
$my->getSubClass('foo');
unset($my);
echo "_____End of skript reached!_____<br>";
?>
This will result in:
Create MyMainClass Object!
Create MySubClass 'bar' Object!
Create MySubClass 'foo' Object!
_____End of Skript reached!_____
Destroy MyMainClass Object!
Destroy MySubClass 'bar' Object!
Destroy MySubClass 'foo' Object!

Anonymous 14-Apr-2010 11:07

If you are not aware of the parameter list, you could use the following in __construct to call up the chain:
<?php
$args = func_get_args();
call_user_func_array(array($this, 'parent::__construct'), $args);
?>

thomasrutter 27-Feb-2010 03:20


The manual page says that throwing an exception from a destructor causes a fatal error; I've found that this only happens when
the exception is _uncaught_ within the context of that destructor. If you catch it within that same destructor it seems to be
fine.
This is equally true of other contexts, such as:
- shutdown functions set with register_shutdown_function
- destructors
- custom session close functions
- custom error handlers
- perhaps other similar contexts
An exception normally 'bubbles up' to higher and higher contexts until it is caught, but because a destructor or shutdown
function is called not within execution flow but in response to a special PHP event, the exception is unable to be traced back
any further than the destructor or shutdown function in which it is called.

Jonathon Hibbard 09-Jan-2010 04:32


Please be aware of when using __destruct() in which you are unsetting variables...
Consider the following code:
<?php
class my_class {
public $error_reporting = false;
function __construct($error_reporting = false) {
$this->error_reporting = $error_reporting;
}
function __destruct() {
if($this->error_reporting === true) $this->show_report();
unset($this->error_reporting);
}
?>
The above will result in an error:
Notice: Undefined property: my_class::$error_reporting in my_class.php on line 10
It appears as though the variable will be unset BEFORE it actually can execute the if statement. Removing the unset will fix
this. It's not needed anyways as PHP will release everything anyways, but just in case you run across this, you know why ;)

jon at fatcatsoftware dot net 03-Dec-2009 01:33


I'm not sure why this was happening, but I had an instance were the __destruct was being called BEFORE my __construct in a
certain class.
I'm using a Factory Class where I would call this statement to grab the class:
<?php
public static function &getBookingSession()

{
static $instance =null;

if (is_null($instance))
{
//requiring the class file
require_once 'bookingSession.php';

//request the instance
$instance = new bookingSession();
}
return $instance;
}
?>
The __destruct was actually being called each time I grabbed this class with
<?php $session =& Factory::getBookingSession(); ?>
Only after the destruct ran once or twice the construct would run. Obviously causing some major problems.
MY SOLUTION: was to call the register shutdown function in my fake session construct, like so:
<?php
class bookingSession {
function __construct(){
$session =& Factory::getSession();
$this->setProperties( unserialize(base64_decode( $session->get('bookingSession') )) );
$this->setProperties(JRequest::get('post'));

register_shutdown_function(array($this,"destruct"));
}
*/
function destruct() {
$session =& JFactory::getSession();
$session->set( 'bookingSession', base64_encode (serialize ($this)) );
}
}
?>

ruggie0 at yahoo dot com 11-Oct-2009 04:13


For those who still ***have*** to deal with php4 (like myself, which sucks), contact at tcknetwork dot com noted below that you
can have both __constructor and function [classname] in the script, as __constructor has priority.
However, to further improve compatability, do a version check in function [classname], as I do in my classes as follows:
<?php
class Foo{
function __construct($arg){
echo $arg;
}
function Foo($arg){
if(version_compare(PHP_VERSION,"5.0.0","<")){
$this->__construct($arg);
register_shutdown_function(array($this,"__destruct"));

}
}
function __destruct(){
echo "Ack! I'm being destroyed!";
}
}
?>
This makes it much easier to use your script with fewer compatibility issues.

enrico dot modanese at alpj dot com 23-Aug-2009 07:05


It's usefull to note that parent::__construct() is executed like a standalone function called into the new one, and not like a
first part of the code. So "return" or "die()" don't have effect on following code. If you want to avoid the execution of the
child constructor you have to pass some condition from the parent. Example:
<?php
class X {
function X(){
if($_POST['break']=='yes'){return;}
}
}
class Y extends X{
function Y(){
parent::__construct();
print("Y_constructor_finished");
}
}
$_POST['break']=='yes';
$new_Y=new Y(); // will print "Y_constructor_finished"
Solution:
class X {
function X(){
if($_POST['break']=='yes'){$this->break='yes';return;}
}
}
class Y extends X{
function Y(){
parent::__construct();
if($this->break=='yes'){return;}
print("Y_constructor_finished");
}
}
$_POST['break']='yes';
$new_Y=new Y(); // will print nothing
?>

ramesh dot rips at gmail dot com 26-Jun-2009 06:49


Without __constructor constructor will call like this.
Why because, Here Class name and function name are equal.

<?php
class baseclass
{
function baseclass()
{
echo "constructor is called"."<br>" ;
}
}
class deriviedclass extends baseclass
{
function deriviedclass()
{
parent::baseclass();
}
}

$object_base=new baseclass();
$object_derive=new deriviedclass();
?>
Out put is
constructor is called
constructor is called

hyponiq at gmail dot com 20-May-2009 06:43


I just thought I'd share some valuable information that might help novice programmers/scripters in __constructor() functions.
I've been using PHP for quite a long time, as well as programming and scripting in general. Even with my quite seasoned
skillset, I still make obvious, painstaking mistakes. That said, I'd like to point out one major (albeit obvious) common
mistake that programmers and scripters (such as myself) make.
When defining the constructor for an object and using it to populate variables for use throughout the lifetime of the
application, do note that if you set a static variable AFTER a dynamic one, the static variable's (intended) contents are not
readible inside the assigning functions of a dynamic variable. (That sounded rather cryptic, so an example is in order...)
<?php
class ExampleClass
{
// assigned a static value using an expression in the constructor
public $myStaticVar;

// assigned a value through a function of the class


public $myDynamicVar;

public function __construct($myStaticVarValue)


{
// sets to nothing; $this->myStaticVar hasn't been assigned to yet
$this->myDynamicVar = $this->setSomeValue();

// sets to 'Static Variable Value in this example
$this->myStaticVar = $myStaticVarValue;
}

public function setSomeValue()


{
// returns null; $this->myStaticVar hasn't been assigned to, yet
return $this->myStaticVar;
}
}

// automatically sets $object->myStaticVar to 'Static Variable Value'


//(but only after setting $object->myDynamicVar to the unassigned $object->myStaticVar)
$object = new ExampleClass('Static Variable Value');
// outputs nothing
print $object->myDynamicVar;
?>
The above example won't print anything because you're setting the $myDynamicVar to equal the $myStaticVar, but the $myStaticVar
hasn't been (technically) assigned to, yet.
So, if you wish to reference that variable inside the assignment function of a dynamic variable, you have to declare it first
and foremost. Otherwise, its value will not be accessible yet.
The correct way...
<?php
class ExampleClass
{
// assigned a static value using an expression in the constructor
public $myStaticVar;

// assigned a value through a function of the class


public $myDynamicVar;

public function __construct($myStaticVarValue)


{
// sets to $myStaticVariable (or 'Some Static Variable Value' in this example)
$this->myStaticVar = $myStaticVarValue;

// sets to newly assigned-to $this->myStaticVariable
$this->myDynamicVar = $this->setSomeValue();
}

public function setSomeValue()


{
// returns 'Static Variable Value'
return $this->myStaticVar;
}
}
// sets $object->myStaticVar to 'Static Variable Value' automatically before $object->myDynamicVar
$object = new ExampleClass('Static Variable Value');
// outputs 'Static Variable Value'
print $object->myDynamicVar;
?>

ceo at l-i-e dot com 07-May-2009 10:38


As far as I can tell, Connection: close isn't sent until after __destruct is called in shutdown sequence.
I was hoping to get the HTTP connection closed and done, and do some slow non-output processing after that, but no luck.

bac2day1 at gmail dot com 29-Jan-2009 10:26


You can also capitalize on singleton for the connection as well.
Just add the following to your class:

<?php
class db {
//...
private static $instance;
//...
public static function singleton() {
if(!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c();
}
return self::$instance;
}
//...
}
?>

spleen 17-Oct-2008 04:35


It's always the easy things that get you Being new to OOP, it took me quite a while to figure out that there are TWO underscores in front of the word __construct.
It is __construct
Not _construct
Extremely obvious once you figure it out, but it can be sooo frustrating until you do.
I spent quite a bit of needless time debugging working code.
I even thought about it a few times, thinking it looked a little long in the examples, but at the time that just seemed
silly(always thinking "oh somebody would have made that clear if it weren't just a regular underscore...")
All the manuals I looked at, all the tuturials I read, all the examples I browsed through - not once did anybody mention
this!
(please don't tell me it's explained somewhere on this page and I just missed it, you'll only add to my pain.)
I hope this helps somebody else!

office at kitsoftware dot ro 14-Oct-2008 07:01


Should be noted that according to the NEWS (in PHP 5.3) file, in PHP 5.3, handling an exception in the __destructor should not
output a FATAL error ...

Jeffrey 09-Oct-2008 02:04


Constructor Simplicity
If your class DOES CONTAIN instance members (variables) that need to be set, then your class needs to be initialized... and you
should use __construct() to do that.
<?php
class MyClassA {
public $data1, $data2;
public function __construct($mcd1, $mcd2) {
$this->data1 = $mcd1; // INITIALIZE $data1
$this->data2 = $mcd2; // INITIALIZE $data2

}
}
$obj1 = new MyClassA("Hello", "World!"); // INSTANTIATE MyClassA
$d1 = $obj1->data1;
$d2 = $obj1->data2;
?>
If your class DOES NOT CONTAIN instance members or you DO NOT want to instantiate it, then there is no reason to initialize it
or use __construct().
<?php
class MyClassB {
const DATA1 = "Hello";
public static $data2 = "World!";
}
$obj1 = new MyClassB(); // INSTANTIATE MyClassB - NO error.
$d1 = $obj1::DATA1; // ERROR
$d2 = $obj1::data2; // ERROR
$d1 = MyClassB::DATA1; // ok
$d2 = MyClassB::$data2; // ok
?>
The fact that $obj1 is useless and cannot be used as a reference, is further evidence that MyClassB objects should not be
instantiated. NOTICE that MyClassB does not use private members or functions to make it behave that way. Rather, it is the
collective nature of all the class members + what ISN'T there.

Anonymous 09-Sep-2008 05:42


USE PARENT::CONSTRUCT() to exploit POLYMORPHISM POWERS
Since we are still in the __construct and __destruct section, alot of emphasis has been on __destruct - which I know nothing
about. But I would like to show the power of parent::__construct for use with PHP's OOP polymorphic behavior (you'll see what
this is very quickly).
In my example, I have created a fairly robust base class that does everything that all subclasses need to do. Here's the base
class def.
<?php
/*
* Animal.php
*
* This class holds all data, and defines all functions that all
* subclass extensions need to use.
*
*/
abstract class Animal
{
public $type;
public $name;
public $sound;
/*
* called by Dog, Cat, Bird, etc.
*/
public function __construct($aType, $aName, $aSound)
{

$this->type = $aType;
$this->name = $aName;
$this->sound = $aSound;
}
/*
* define the sorting rules - we will sort all Animals by name.
*/
public static function compare($a, $b)
{
if($a->name < $b->name) return -1;
else if($a->name == $b->name) return 0;
else return 1;
}
/*
* a String representation for all Animals.
*/
public function __toString()
{
return "$this->name the $this->type goes $this->sound";
}
}
?>
Trying to instantiate an object of type Animal will not work...
$myPet = new Animal("Parrot", "Captain Jack", "Kaaawww!"); // throws Fatal Error: cannot instantiate abstract class Animal.
Declaring Animal as abstract is like killing two birds with one stone. 1. We stop it from being instantiated - which means we
do not need a private __construct() or a static getInstance() method, and 2. We can use it for polymorphic behavior. In our
case here, that means "__construct", "__toString" and "compare" will be called for all subclasses of Animal that have not
defined their own implementations.
The following subclasses use parent::__construct(), which sends all new data to Animal. Our Animal class stores this data and
defines functions for polymorphism to work... and the best part is, it keeps our subclass defs super short and even sweeter.
<?php
class Dog extends Animal{
public function __construct($name){
parent::__construct("Dog", $name, "woof!");
}
}
class Cat extends Animal{
public function __construct($name){
parent::__construct("Cat", $name, "meeoow!");
}
}
class Bird extends Animal{
public function __construct($name){
parent::__construct("Bird", $name, "chirp chirp!!");
}
}
# create a PHP Array and initialize it with Animal objects
$animals = array(

new Dog("Fido"),
new Bird("Celeste"),
new Cat("Pussy"),
new Dog("Brad"),
new Bird("Kiki"),
new Cat("Abraham"),
new Dog("Jawbone")
);
# sort $animals with PHP's usort - calls Animal::compare() many many times.
usort($animals, array("Animal", "compare"));
# print out the sorted results - calls Animal->__toString().
foreach($animals as $animal) echo "$animal<br>\n";
?>
The results are "sorted by name" and "printed" by the Animal class:
Abraham the Cat goes meeoow!
Brad the Dog goes woof!
Celeste the Bird goes chirp chirp!!
Fido the Dog goes woof!
Jawbone the Dog goes woof!
Kiki the Bird goes chirp chirp!!
Pussy the Cat goes meeoow!
Using parent::__construct() in a subclass and a super smart base class, gives your child objects a headstart in life, by
alleviating them from having to define or handle several error and exception routines that they have no control over.
Notice how subclass definitions are really short - no variables or functions at all, and there is no private __construct()
method anywhere? Notice how objects of type Dog, Cat, and Bird are all sorted by our base class Animal? All the class
definitions above address several issues (keeping objects from being instantiated) and enforces the desired, consistent, and
reliable behavior everytime... with the least amount of code. In addition, new extenstions can easily be created. Each subclass
is now super easy to redefine or even extend... now that you can see a way to do it.

KK 16-May-2008 01:57
I ran into an interesting (and subtle) code error while porting some code to PHP 5.2.5 from PHP 4.4.8 that I think illustrates
a noteworthy semantic.
I have a hierarchy of classes with both styles of constructors but where one in the middle was missing the __construct()
function (it just had the old-style one that called the (nonexistent) __construct()). It worked fine in PHP4 but caused an
endless loop (and stack overflow) in PHP5. I believe what happened is that in PHP4 the old-style constructor was not called,
but in PHP5 it was (due to the "emulation" of PHP4), and since _construct() wasn't defined for that class, the call to $this>__construct() caused a looping call to the original (lowest child) constructor.

bolshun at mail dot ru 16-Apr-2008 06:13


Ensuring that instance of some class will be available in destructor of some other class is easy: just keep a reference to that
instance in this other class.

ashnazg at php dot net 12-Apr-2008 10:26


Since my last note, I've been instructed to _NEVER_ call "unset($this)", never ever ever. Since my previous testing of
behavior did not explicitly show me that it was indeed necessary, I'm inclined to trust those telling me not to do it.

ashnazg at php dot net 28-Feb-2008 02:39


While experimenting with destructs and unsets in relation to memory usage, I found what seems to be one useful way to predict
when __destruct() gets called... call it manually yourself.
I had previously assumed that explicitly calling unset($foo) would cause $foo->__destruct() to run implicitly, but that was not
the behavior I saw (php 5.2.5). The destructors weren't running until the script ended, even though I was calling unset($foo)
in the middle of my script. So, having $foo->__destruct() unset all of $foo's component objects was not helping my memory
usage since my explicit unset($foo) was _not_ triggering $foo->__destruct()'s cleanup steps.
Interestingly, what _did_ appear to happen is that calling unset($bar) from inside a destructor like $foo->__destruct() _DID_
cause $bar->__destruct() to be implicitly executed. Perhaps this is because $bar has a "parent" reference of $foo whereas $foo
does not, and the object destruction behaves differently... I don't know.
Lastly, even after explicitly calling $foo->__destruct() (even when it had "unset($this);" inside it), the reference to the
$foo object remained visible. I had to still explicitly call unset($foo) to get rid of it.
So, my advice based on the behavior I saw in my experiments:
- always unset($bar) your class's component objects from inside that class's __destruct() method; no explicit component
destructor calls seem to be required other than those unsets, though.
- always explicitly call $foo->__destruct() in your code that _uses_ your class
- always explicitly follow $foo->__destruct() with unset($foo).
This seems to be the best cleanup approach to take. Just for my own sanity, I also will always keep an unset($this) at the
end of each __destruct() method.

nerdystudmuffin at gmail dot com 09-Jan-2008 11:11


Correction to the previous poster about non public constructors. If I wanted to implement Singleton design pattern where I
would only want one instance of the class I would want to prevent instantiation of the class from outside of the class by
making the constructor private. An example follows:
class Foo {
private static $instance;
private __construct() {
// Do stuff
}
public static getInstance() {
if (!isset(self::$instance)) {
$c = __CLASS__;
$instance = new $c;
}
return self::$instance;
}
public function sayHello() {
echo "Hello World!!";
}
}
$bar = Foo::getInstance();
// Prints 'Hello World' on the screen.

$bar -> sayHello();

david at synatree dot com 29-Dec-2007 01:26


When a script is in the process of die()ing, you can't count on the order in which __destruct() will be called.
For a script I have been working on, I wanted to do transparent low-level encryption of any outgoing data. To accomplish
this, I used a global singleton class configured like this:
class EncryptedComms
{
private $C;
private $objs = array();
private static $_me;

public static function destroyAfter(&$obj)


{
self::getInstance()->objs[] =& $obj;
/*
Hopefully by forcing a reference to another object to exist
inside this class, the referenced object will need to be destroyed
before garbage collection can occur on this object. This will force
this object's destruct method to be fired AFTER the destructors of
all the objects referenced here.
*/
}
public function __construct($key)
{
$this->C = new SimpleCrypt($key);
ob_start(array($this,'getBuffer'));
}
public static function &getInstance($key=NULL)
{
if(!self::$_me && $key)
self::$_me = new EncryptedComms($key);
else
return self::$_me;
}

public function __destruct()


{
ob_end_flush();
}

public function getBuffer($str)


{
return $this->C->encrypt($str);
}
}
In this example, I tried to register other objects to always be destroyed just before this object. Like this:
class A
{
public function __construct()
{
EncryptedComms::destroyAfter($this);

}
}
One would think that the references to the objects contained in the singleton would be destroyed first, but this is not the
case. In fact, this won't work even if you reverse the paradigm and store a reference to EncryptedComms in every object you'd
like to be destroyed before it.
In short, when a script die()s, there doesn't seem to be any way to predict the order in which the destructors will fire.

Typer85 at gmail dot com 21-Dec-2007 09:33


I mentioned in my post below this one that the solution is not perfect and has some flaws.
Because my note was too big and was not allowed to be submitted, I had to write a new note here containing the flaws. If an
editor sees this, please combine both notes to allow for easier reading.
- This solution assumes that Class B and Class C extend or build upon Class AAbstract. If Class B or Class C extend from each
other or from Class A, the original problem will be encountered again.
- There will be extra overhead in including an extra file ... the dummy Class AAbstract.

Typer85 at gmail dot com 21-Dec-2007 09:31


In regards to a Class Constructor visibility ...
I too was having the same problem with Class Constructor visibility, in which I had one Class that was extended by several
other Classes. The problem that I encountered was in one of the Child Classes, I wanted a weaker visibility. Consider the
following example:
<?php
class A {

// Public Constructor ...


// No Problems Here.

public function __construct( ) {



}

// Class Function.

public function functionA( ) {



}
}
class B extends A {

// Public Constructor ...


// Same As Parent Class ...
// Again No Problems Here.

public function __construct( ) {



}

// Class Function.


public function functionB( ) {

}
}
class C extends A {

// Private Constructor ...


// Weaker Then Parent Class ...
// PHP Will Throw A Fatal Error.

private function __construct( ) {



}

// Class Function.

public function functionC( ) {



}
}
?>
Nothing new in the above example that we have not seen before. My solution to solve this problem?
Create an Abstract Class with all the functionality of Class A. Make its Class Constructor have a visibility of Protected,
then extend each of the three Classes above from that Abstract Class. In a way, the Abstract Class acts as a dummy Class to
get rid of the visibility problem:
<?php
abstract class AAbstract {

// Protected Constructor ...


// Abstract Class Can Not Be Created Anyway ...
// No Problems Here.

protected function __construct( ) {



}

// Class Function ...


// Originally In Class A ...
// Which Was Used As A Super Class.

public function functionA( ) {



}
}
class A extends AAbstract {

// Public Constructor ...


// Stronger Than Parent Class ...
// Again No Problems Here.

public function __construct( ) {


// By Moving All The Functionality Of


// Class A To Class AAbstract Class A
// Will Automatically Inherit All Of
// Its Functionality. The Only Thing
// Left To Do Is To Create A Constructor
// Which Calls Class AABstract's Constructor
// To Mimic Similar Behavior.

parent::__construct( );
}

// No Need To Redeclare functionA( )


// Since It Was Moved To Class
// AAbstract.
}
class B extends AAbstract {

// Public Constructor ...


// Stronger Than Parent Class ...
// Again No Problems Here.

public function __construct( ) {



parent::__construct( );
}

// Class Function ...


// Specific To This Class.

public function functionB( ) {



}
}
class C extends AAbstract {

// Protected Constructor ...


// Same As Parent Class ...
// Again No Problems Here.

protected function __construct( ) {



}

// Class Function ...


// Specific To This Class.

public function functionC( ) {



}
}
?>
As you can see the problem is more or less fixed. Class AAbstract acts a dummy class, containing all the original functionality
of Class A. But because it has a protected Constructor, in order to make its functionality available, Class A is redeclared as
Child Class with the only difference of it having a public Constructor that automatically calls the Parent Constructor.
Notice that Class B does not extend from Class A but also from Class AAbstract! If I wanted to change Class B's Constructor to

protected, I can easily do it! Notice that an extra Method was added to Class B ... this is because Class B has extra
functionality specific to itself. Same applies to Class C.
Why don't Class B and Class C extend from Class A? Because Class A has a public Constructor, which pretty much defies the
point of this solution.
This solution is not perfect however and has some flaws.
Good Luck,

randallgirard at hotmail dot com 26-Oct-2007 10:17


I've been working on a project for a while now, and for example in my DB handler I wanted to load var's to the objects late;
However, without doing it manually on the object itself but through a single static call. For other reasons, in my Sessions I
then wanted to end them early without registering a shutdown routine for every possible session. Hence, I needed a way to track
EVERY instance or object of the class.
(Of course in a normal website design, this would be overly coded. It's more of a framework for a CMS, Daemon service, anything
I wanna create etc...)
<?php
class example {
public static $OBJS = array();
public $id;

public function __construct() {


example::$OBJS[] = $this;
# I actually use a 'lastKey' routine here, but in this example the following should work:
$this->id = key( array_slice(example::$OBJS, count(example::$OBJS) -1, 1, true) );
}

public function __destruct() {


$this->close();
}

# unset the tracked object


private function destruct() {
if ( isset(example::$OBJS[$this->id]) )
unset(example::$OBJS[$this->id]);
}

# public shutdown routine


public function close() {
if ( isset($this->destructed) )
return;
# ...
$this->destruct();
$this->destructed = true;
}

}
?>
You could then also use register_shutdown_function(...) to call a static class method, which loops through ALL the objects and
calls the $obj->close routine.

<?php
# register a shutdown function which triggers before destructors (hence when such results are desired for a Session class, etc)
register_shutdown_function("example::destructors");

class example {

# ... see above code example

# static class method to destruct all objects


public static function destructors() {
foreach ( example::$OBJS as $obj )
$obj->destruct();
}

}
This will probably give some people new ideas, and other will probably be confused. Happy coding...
NOTE: I didnt test the code(s) above. They were a rewritten example from my frameworks.
?>

James Laver 25-Oct-2007 02:45


I recently found, while implementing a database backed session class, that PHP has an apparently less than desirably structured
destruction order. Basically, my session class which would have saved when destructed, was being destructed after one of the
classes it depends on. Apparently we cannot, therefore depend on PHP to use reverse initialisation order.
My solution was to use register_shutdown_function, which is called before any objects are killed on script end.
Quick example (if you're going to use it, I recommend tidying up the code somewhat) :
<?php
class Session
function __construct()
{
//Initialise the session here...

//Register the shutdown function


register_shutdown_function(array($this,"save"));
}
function save()
{
//Save it here
}
function __destruct()
{
//Persisting the session here will not work.
}
?>

magus do t xion a t g mail d ot c o m 11-Oct-2007 12:20


Looking through the notes I noticed a few people expressing concern that PHP5 does not support multiple constructors...
Here is an example of a method that I use which seems to work fine:

class Example
{
function __construct()
{
echo "do some basic stuff here";
}
function Example($arg)
{
echo $arg;
}
}
You then can call with or without arguments without having notices and/or warnings thrown at you... Of course this is limited
but if you don't need something complex this can help to get the job done in some situations. I believe you could also add
arguments to the __construct() function and as long as it is different than Example() 's args you would be fine. Although I
have yet to test this.

prieler at abm dot at 27-Jul-2007 12:42


i have written a quick example about the order of destructors and shutdown functions in php 5.2.1:
<?php
class destruction {
var $name;
function destruction($name) {
$this->name = $name;
register_shutdown_function(array(&$this, "shutdown"));
}
function shutdown() {
echo 'shutdown: '.$this->name."\n";
}
function __destruct() {
echo 'destruct: '.$this->name."\n";
}
}
$a = new destruction('a: global 1');
function test() {
$b = new destruction('b: func 1');
$c = new destruction('c: func 2');
}
test();
$d = new destruction('d: global 2');
?>
this will output:
shutdown: a: global 1
shutdown: b: func 1
shutdown: c: func 2
shutdown: d: global 2
destruct: b: func 1

destruct: c: func 2
destruct: d: global 2
destruct: a: global 1
conclusions:
destructors are always called on script end.
destructors are called in order of their "context": first functions, then global objects
objects in function context are deleted in order as they are set (older objects first).
objects in global context are deleted in reverse order (older objects last)
shutdown functions are called before the destructors.
shutdown functions are called in there "register" order. ;)
regards, J

fredrik at rambris dot com 16-Jul-2007 06:59


The fact that class names are case-insensitive in PHP5 also applies to constructors. Make sure you don't have any functions
named like the class *at all*.
This has bitten me a few times.
<?php
class Example extends Base
{
function example()
{
echo "This gets called";
}
}
class Base
{
function __construct()
{
echo "Not this";
}
}
?>

theubaz at gmail dot com 11-Jul-2007 04:35


What you could do is write the constructor without any declared arguments, then iterate through the arguments given and check
their types/values to determine what other function to use as the constructor.

soapthgr8 at gmail dot com 06-Jul-2007 07:46


This is just to clarify that the Singleton pattern is a bit more complex than just making the constructor private. It also
involves caching an instance of the object and always returning the cached value. So, in the previous example, the
getNewInstance() function would undermine the intent of the Singleton pattern. Instead you would just need a getInstance()
function, like so.
<?php
class A {
// cached instance
private static oInst = null;

/**
* Prevent an object from being constructed.
*/
private function __construct( ) {}
/**
* Function to return the instance of this class.
*/
public static function getInstance( ) {
if (is_null(self::$oInst)) {
self::$oInst = new A( );
}
return self::$oInst;
}
}
?>

Typer85 at gmail dot com 03-Jun-2007 07:16


I am not sure if the following is known or not, but here goes.
I am sure most are aware of the concept of making a Class Constructor private to prevent an Object of that Class from being
created as follows:
<?php
class A
{
/**
* Prevent An Object From Being Constructed.
*/
private function __construct( ) {

}
}
?>
In some code, if I try to do the following:
<?php
$Obj = new A( );
?>
PHP will fail with a fatal error. This is useful when creating Classes that are composed of only static functions or in a more
advanced example, when applying the Singleton Pattern to a Class design.
However what is not properly documented in this manual but is pretty simple to note, especially if you read the notes regarding
the Singleton Pattern, is that you can create an Object of a Class that has a private Constructor from within the Class itself.
Confused ... so am I, so allow me to provide a visual example as follows:
<?php
class A
{
/**
* Prevent An Object From Being Constructed.

*/
private function __construct( ) {

}
/**
* Function To Return An Instance Of This Class.
*/
public static function getNewInstance( ) {

return new A( );
}
}
?>
In some code, if I try to do the following:
<?php
$Obj = A::getNewInstance( );
?>
PHP in this case will not fail with a fatal error and instead the variable '$Obj' becomes an Object with an instance of Class
'A'.
This is a simple example and pretty advanced things can be done using this method. I am sure advanced developers are aware of
this so this is just a little note going out to new PHP developers.

Peter Molnar 17-May-2007 08:32


The manual says: "Destructor is called during the script shutdown so headers are always already sent."
This is obviously not true. If you instantiate a class in a function or class method, but it is not returned by the method,
nor is it saved in a global or object member variable, the object is cleaned up, and it's destructor is called. This can of
course occur before anything is printed or sent to the client.

frederic dot barboteu at laposte dot net 14-Apr-2007 07:11


The manual says:
"Like constructors, parent destructors will not be called implicitly by the engine."
This is true ONLY when a __destruct() function has been defined by the child class.
If no __destruct() function exists in the child class, the parent's one will be implicitly executed.
So be carefull if you have some ancestor executing a particular task in its __destruct() function, an you plan its childs to
execute it or not, wether you include "parent::__destruct()" or not.
If you want the child not to execute its parent __destruct() function, you must ensure that it has its own __destruct()
function, even if empty. Then the parent's one will not be executed.
This can be verified with the following code:
<?php
#
class AncestorClass {
function __destruct() {
echo '<br />AncestorClass: destructing '.get_class($this);
}
}

#
class ParentDestructClass extends AncestorClass {
function __destruct() {
echo 'ParentDestructClass: destructing itself';
parent::__destruct();
}
}
#
class EmptyDestructClass extends AncestorClass {
function __destruct() {
echo 'EmptyDestructClass: destructing itself';
}
}
#
class NoDestructClass extends AncestorClass {
}
#--echo '<hr>';
$p=new ParentDestructClass();
unset($p);
echo '<hr>';
$e=new EmptyDestructClass();
unset($e);
echo '<hr>';
$n=new NoDestructClass();
unset($n);
echo '<hr>';
?>
which displays:
--ParentDestructClass: destructing itself
AncestorClass: destructing ParentDestructClass
--EmptyDestructClass: destructing itself
--AncestorClass: destructing NoDestructClass
---

robert at lax-berlin dot de 12-Nov-2006 12:48


In response to prauscher at gmx dot net:
As tcknetwork wrote earlier, if you try to access a file from a destructor, you have to be aware that you are probably in the
webservers root directory, because the destructor already "forgot" what you working directory was. If you try to write a file
there, you will probably have no permission to do so.
Read tcknetwork's post for a solution.

maniac_warlord at web dot de 04-Nov-2006 04:50


as reported in bug 34206 the working dir is changed to the server root
the best workaround is
<?php
class Foo
{
public function bar()
{
$this->_cwd = getcwd();

}
public function __destruct()
{
chdir($this->_cwd);
}
}
?>
Be aware the booty trap!
http://bugs.php.net/bug.php?id=34206

phaxius 01-Nov-2006 09:23


Hello, I've been messing with php for about a week but am learning a lot. It occurred to me that it might be necessary in
some cases to write a class that takes a variable number of arguments. After some experimentation, this example was formed:
class variableArgs{
public $a = array();
protected $numOfArgs;
public function __construct()
{
$numOfArgs=func_num_args();
if(func_num_args()==0)
{
$numOfArgs=1;
$a[0]='No arguments passed';
$this->Arg[0]=$a[0];
}
else
for($i=0; $i<func_num_args(); $i++)
{
$a[$i]=func_get_arg($i);
$this->Arg[$i]=$a[$i];
}
}
public function showArgs()
{
echo 'showArgs() called <br />';
for ($i=0; $i<$numOfArgs; $i++)
{
echo '$i: ' . $i . '<br />';
echo $this->Arg[$i];
echo '<br />';
}
}
public function __destruct(){}
}
$test1 = new variableArgs;
$test2 = new variableArgs("arg1");
$test3 = new variableArgs("arg1", "arg2");
$test4 = new variableArgs("arg1", "arg2", "arg3");
$test1->showArgs();
$test2->showArgs();
$test3->showArgs();
$test4->showArgs();

This outputs the following:


showArgs() called
$i: 0
No arguments passed
showArgs() called
$i: 0
arg1
showArgs() called
$i: 0
arg1
$i: 1
arg2
showArgs() called
$i: 0
arg1
$i: 1
arg2
$i: 2
arg3
I have no idea how efficient this is, but it works at any rate. Hopefully this helps someone.

01-Oct-2006 11:03
This is a simple thing to bear in mind but it's also easy to forget it. When chaining object constructors and destructors,
always remember to call the superclass __construct() method in the subclass __construct() so that all superclass members are
properly initialized before you start initializing the ones belonging to your subclass.
Also, you will usually want to do your own cleanup first in your subclass __destruct() method so you will probably want to call
the superclass __destruct() as the last thing in your subclass so that you can use resources defined in the superclass during
the cleanup phase.
For example, if your superclass includes a database connection and your subclass __destruct method commits things to the
database then if you call the superclass destruct before doing so then the database connection will no longer be valid and you
will be unable to commit your changes.

chanibal at deltasoft dot int dot pl dot SPAMPROTECT 20-Aug-2006 09:56


Note that if a class contains another class, the contained class's destructor will be triggered after the destructor of the
containing class.
<?php
class contained {

protected $parent;
public function __construct(&$p) {
# $this->parent=&$p;
}

public function __destruct() {


/* unset $this->parent */
print 'contained ';
}
}

class containing {

protected $contained;
public function __construct() {
$this->contained=new contained($this);
}
public function __destruct() {
// unset($this->contained);
print 'containing ';
}
}

new containing();
?>
Will output
containing contained
After uncommenting the // comment, the output will change to
contained containing
Adding a reference from the contained class to the containing one (the # comment) will not change that, but beware, because it
can cause random errors in other destructors in the parts of the script which seem unrelated! (PHP Version 5.1.2)

prauscher at gmx dot net 14-Aug-2006 04:05


I saw no note in the manual about my function. If you want to write a file in a __destruct - function, it will fail with a
"Permission denied" Error.

Reza Mahjourian 10-Jul-2006 02:18


Peter has suggested using static methods to compensate for unavailability of multiple constructors in PHP. This works fine for
most purposes, but if you have a class hierarchy and want to delegate parts of initialization to the parent class, you can no
longer use this scheme. It is because unlike constructors, in a static method you need to do the instantiation yourself. So
if you call the parent static method, you will get an object of parent type which you can't continue to initialize with derived
class fields.
Imagine you have an Employee class and a derived HourlyEmployee class and you want to be able to construct these objects out of
some XML input too.
<?php
class Employee {
public function __construct($inName) {
$this->name = $inName;
}
public static function constructFromDom($inDom)
{
$name = $inDom->name;
return new Employee($name);
}
private $name;
}
class HourlyEmployee extends Employee {

public function __construct($inName, $inHourlyRate) {


parent::__construct($inName);
$this->hourlyRate = $inHourlyRate;
}
public static function constructFromDom($inDom)
{
// can't call parent::constructFromDom($inDom)
// need to do all the work here again
$name = $inDom->name; // increased coupling
$hourlyRate = $inDom->hourlyrate;
return new EmployeeHourly($name, $hourlyRate);
}
private $hourlyRate;
}
?>
The only solution is to merge the two constructors in one by adding an optional $inDom parameter to every constructor.

Peter Molnar 18-May-2006 06:24


There were many notes about the inability of defining multiple constructors for the class.
My solution is to define separate static methods for each type of constructor.
<?php
class Vector {
private $x;
private $y;
public function __construct() {
$this->x = 0;
$this->y = 0;
}
public static function createXY($x, $y) {
$v = new Vector();
$v->x = $x;
$v->y = $y;
return $v;
}
}
?>

ckoschmied at web dot de 07-Apr-2006 07:58


Be aware of the fact that if you create a new instance of a class like this:
$instance = new Class();
$instance will not contain a valid reference to the newly created object until the constructor is finished. So don't use
$instance while the constructor is still running.
Well, on the other side, why would you want to do it? I wanted to, and it took me some hours to figure out.
Even though it's quite obvious if you think about it :-)

jcaplan at bogus dot amazon dot com 24-Mar-2006 09:52

__construct and __destruct must be declared public in any class that you intend to instantiate with new. However, in an
abstract (or never-instantiated base) class you can declare them private or protected, and subclasses can still refer to them
via parent::__construct (!) (tested in PHP 5.1.2).

09-Feb-2006 10:55
(Refering to: caliban at darklock dot com)
To force a constructor always to be called, and still be able to define a constructor on a derived class use the model below.
Ideal for module architectures, because you only have to know the file and classname to construct an object.
<?php
class Parameter {}
abstract class BaseClass
{
protected $param;

public final function __construct( Parameter $param )


{
$this->param = $param;
$this->pseudoConstruct();
}

protected abstract function pseudoConstruct();


}
class ConcreteClass extends BaseClass
{
protected function pseudoConstruct()
{
echo __CLASS__.' constructor';
}
}
$refl = new ReflectionClass( 'ConcreteClass' );
if( !$refl->isSubclassOf( 'BaseClass' ) ) throw new Exception( 'Invalid base class!' );
$refl->newInstance( new Parameter() );
?>

jochem AT mondrian-it d_o_t nl 30-Jan-2006 04:07


at: derk AT oneindig DOT com
You can achieve identical functionality by doing this:
<?php
class Parent {
function __construct()
{
echo "Parent constructor called\\n";
}
}
class Child extends Parent {
function __construct()
{
parent::__construct();
echo " Child 'contructor' called";

}
}
$c = new Child();
?>
Added advantage is that Parent doesn't need to have the method myConstruct(), and that you're using constructors like they were
intended.

developit at mail dot ru 25-Jan-2006 02:32


as [kida at keymail dot it] said you can't weaken a visibility of constructor when extending some class. but suggested trick
that uses both old and new constructor namimg syntaxes to weaken visibility from 'protected' to 'public' seems a little bit
odd. allthough it works allright. declaring extended class as 'abstract' with 'public' constructor will do quite the same thing
in a more elegant manner and without any syntax mess.
<?php
class A
{
public function __construct()
{
//do smth
}
}
abstract class B extends A
{
public function __construct()
{
parent::__construct();
}
}
?>
thus, you avoid instanciating class B as if it had a protected contructor

aya at eh dot org 01-Dec-2005 02:20


For those who aren't already aware, PHP5 currently suffers from the classic reference counting leak. See
http://en.wikipedia.org/wiki/Reference_counting for more info.
Example code:
<?php
class Noisy
{
private $name;
public function __construct($name)
{
$this->name = $name;
echo "Noisy::__construct($this->name)\n";
}
public function __destruct()
{
echo "Noisy::__destruct($this->name)\n";
}

}

function foo($num)
{
$noisy = new Noisy($num);
//$noisy->me = $noisy; // Uncomment this line to create a cyclic reference
}
for ($i = 0; $i < 10; ++$i)
foo($i);
?>
As it stands, the destructor of class 'Noisy' will be called on '$noisy' when it goes out of scope in function 'foo', but
uncommenting the second line in function 'foo' will prevent this, and cause a memory leak.
See http://bugs.php.net/bug.php?id=33595 for a bug report, which reads as if this is not likely to get fixed in the near
future, so watch out!

derk AT oneindig DOT com 03-Nov-2005 02:02


If a constructor is not present in a child class, php5 will try to call a constructor from the parent class. This behaviour
can be used to somewhat simulate constructor chaining.
<?php
abstract class Parent {
function __construct()
{
echo "Parent constructor called\n";
$this->myConstruct();
}
}
class Child extends Parent {
function myConstruct()
{
echo " Child 'contructor' called";
}
}
$c = new Child();
?>
will output:
Parent constructor called
Child 'constructor' called

contact at tcknetwork dot com 21-Sep-2005 12:54


be careful while trying to access files with __destruct() because the base directory (getcwd()) will be the root of your server
and not the path of your script, so add before all your path called in __destruct() :
EITHER dirname($_SERVER["SCRIPT_FILENAME"])."my/path/"
OR dirname(__FILE__)."my/path/"
(be careful with includes, it will give the path of the file processed and not the main file)

php dot net at lk2 dot de 13-Aug-2005 09:50


It looks like `echo()`ed output from the __destructor() function is displayed onto screen _before_ other output that the class

may have have already sent before.


This can be misleading if you have debug info printed in the destructor but not a problem if you know it.

stanley dot turnteen at gmail dot com 05-Aug-2005 12:43


IMHO using func_get_args() is superior to constructor polymorphism, because you don't have to define constructors for every
possible way a class can be initialized.
The pattern I use looks like this; all you have to do is pass the parameters in the correct order.
<?php
class Movie
{
public $title;
public $director;
public $stars;
public $year_released;

public function __construct()


{
$args = func_get_args();

foreach(array("title", "director", "stars", "year_released") as $i)
{
if(empty($args))
{
break;
}

$this->$i = array_shift($args);
}
}

}
?>

dominics at gmail dot com 10-Jul-2005 07:12


If you're using E_STRICT error reporting, PHP will tell you if you define both __construct() and an old-style constructor (a
function with the same name as the class) together in a class. Note that this occurs even if the old constructor function is
abstract or final (for instance, if you were intending to only use it in a sub-class). Be wary of this if you're trying to
implement the 'command' design pattern.
The solution? Either turn E_STRICT off (and possibly forgo some other important notices), rename your function (and possibly
make things a little more complicated), or look at using an interface.

rocco at bluora dot com dot au 16-Apr-2005 08:29


Before PHP reaches the point where it calls the __destruct functions, it has already done a session_write_close() so you can no
longer write anything to the session.
I wanted it to copy some variables from my class into the session once the script had finished but now having to get the last
function to call a SaveToSession() function.
In php versions 5.0.2 and 5.0.4

contact at tcknetwork dot com 15-Apr-2005 08:45


Note that php5 use in priority __construct() instead of [classname](). So you could build a constructed/destructed class for
php4/5 very easily using this.
<?
class test {
function test() {
$this->__construct();
register_shutdown_function(array($this,"__destruct"));
}
function __construct() {
echo "construct\n";
}
function __destruct() {
echo "destruct\n";
}
};
$t=new test();
?>
In case you use unset($t) in php4, the destructor is not called. so be careful.

apfelsaft 30-Mar-2005 01:59


at the end of a script all remaining objects aren't in fact destructed. it is only their __destruct() method, which will be
called. the objects still exist after that.
so, if your database connection object has no __destruct() or at least it doesn't disconnects the database, it will still work.
in general, there is no need to disconnect the database (especially for persistent connections).

04-Mar-2005 03:48
> To caliban at darklock dot com: Why not just define
> a dummy constructor
Because you don't always get to modify your base classes. Once you get beyond the "build to suit" range of software
development, you end up having to work with other people's code, and sometimes you just plain can't change it. When Bob is in
charge of making changes to that object, you can't add a dummy constructor. You have to tell Bob to do it, and until Bob does
it, you don't get it. So if you want to hit your deadlines, you don't count on Bob caring enough about your job to make the
changes you want... you work around it. It might be convenient for *you* to have a constructor on that object, but when you're
only one of several thousand people that are using it, your convenience isn't generally among the design criteria.
Smaller projects where you can add whatever you want wherever you want will not have this problem, in which case the dummy
constructor is indeed a better solution.

24-Feb-2005 01:08
To caliban at darklock dot com: Why not just define a dummy constructor <?PHP function __construct() {} ?> in the base class?
This adds little overhead, and allows you to both extend the class worry-free and later add construct functionality to the base
class.
And now, about destructors: I haven't seen this clarified anywhere in the manual, but object destructors are called implicitly
at script shutdown for all objects that still exist at that Tpoint. his happens *after* any shutdown functions set with <?PHP
register_shutdown_function() ?> have been called.
Objects appear to be destructed in the order they were defined, which means you have to be careful with destruct methods that
rely on the functionality of other objects (e.g. on a database-handler) as they will have shut down already.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Visibility
The visibility of a property or method can be defined by prefixing the declaration with the keywords public,
protected or private. Class members declared public can be accessed everywhere. Members declared protected
can be accessed only within the class itself and by inherited and parent classes. Members declared as private
may only be accessed by the class that defines the member.

Property Visibility
Class properties must be defined as public, private, or protected. If declared using var, the property will be
defined as public.
Example #1 Property declaration
<?php
/**
*DefineMyClass
*/
classMyClass
{
public$public='Public';
protected$protected='Protected';
private$private='Private';
functionprintHello()
{
echo$this->public;
echo$this->protected;
echo$this->private;
}
}
$obj=newMyClass();
echo$obj->public;//Works
echo$obj->protected;//FatalError
echo$obj->private;//FatalError
$obj->printHello();//ShowsPublic,ProtectedandPrivate

/**
*DefineMyClass2
*/
classMyClass2extendsMyClass
{
//Wecanredeclarethepublicandprotectedmethod,butnotprivate
protected$protected='Protected2';
functionprintHello()
{
echo$this->public;
echo$this->protected;
echo$this->private;
}
}
$obj2=newMyClass2();
echo$obj2->public;//Works
echo$obj2->private;//Undefined

echo$obj2->protected;//FatalError
$obj2->printHello();//ShowsPublic,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 may be defined as public, private, or protected. Methods declared without any explicit visibility
keyword are defined as public.
Example #2 Method Declaration
<?php
/**
*DefineMyClass
*/
classMyClass
{
//Declareapublicconstructor
publicfunction__construct(){}
//Declareapublicmethod
publicfunctionMyPublic(){}
//Declareaprotectedmethod
protectedfunctionMyProtected(){}
//Declareaprivatemethod
privatefunctionMyPrivate(){}
//Thisispublic
functionFoo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
$myclass=newMyClass;
$myclass->MyPublic();//Works
$myclass->MyProtected();//FatalError
$myclass->MyPrivate();//FatalError
$myclass->Foo();//Public,ProtectedandPrivatework

/**
*DefineMyClass2
*/
classMyClass2extendsMyClass
{
//Thisispublic
functionFoo2()

{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();//FatalError
}
}
$myclass2=newMyClass2;
$myclass2->MyPublic();//Works
$myclass2->Foo2();//PublicandProtectedwork,notPrivate
classBar
{
publicfunctiontest(){
$this->testPrivate();
$this->testPublic();
}
publicfunctiontestPublic(){
echo"Bar::testPublic\n";
}

privatefunctiontestPrivate(){
echo"Bar::testPrivate\n";
}
}
classFooextendsBar
{
publicfunctiontestPublic(){
echo"Foo::testPublic\n";
}

privatefunctiontestPrivate(){
echo"Foo::testPrivate\n";
}
}
$myFoo=newfoo();
$myFoo->test();//Bar::testPrivate
//Foo::testPublic
?>

Visibility from other objects


Objects of the same type will have access to each others private and protected members even though they are
not the same instances. This is because the implementation specific details are already known when inside those
objects.
Example #3 Accessing private members of the same object type
<?php
classTest
{
private$foo;
publicfunction__construct($foo)
{
$this->foo=$foo;

}
privatefunctionbar()
{
echo'Accessedtheprivatemethod.';
}
publicfunctionbaz(Test$other)
{
//Wecanchangetheprivateproperty:
$other->foo='hello';
var_dump($other->foo);
//Wecanalsocalltheprivatemethod:
$other->bar();
}
}
$test=newTest('test');
$test->baz(newTest('other'));
?>

The above example will output:


string(5) "hello"
Accessed the private method.

User Contributed Notes

Visibility

IgelHaut 30-May-2012 01:48


<?php
class test {
public $public = 'Public var';
protected $protected = 'protected var';
private $private = 'Private var';

public static $static_public = 'Public static var';


protected static $static_protected = 'protected static var';
private static $static_private = 'Private static var';
}
$class = new test;
print_r($class);
?>
The code prints
test Object ( [public] => Public var [protected:protected] => protected var [private:test:private] => Private var )
Functions like print_r(), var_dump() and var_export() prints public, protected and private variables, but not the static
variables.

wbcarts at juno dot com 19-May-2012 08:27


INSIDE CODE and OUTSIDE CODE

<?php
class Item
{
/**
* This is INSIDE CODE because it is written INSIDE the class.
*/
public $label;
public $price;
}
/**
* This is OUTSIDE CODE because it is written OUTSIDE the class.
*/
$item = new Item();
$item->label = 'Ink-Jet Tatoo Gun';
$item->price = 49.99;
?>
Ok, that's simple enough... I got it inside and out. The big problem with this is that the Item class is COMPLETELY IGNORANT
in the following ways:
* It REQUIRES OUTSIDE CODE to do all the work AND to know what and how to do it -- huge mistake.
* OUTSIDE CODE can cast Item properties to any other PHP types (booleans, integers, floats, strings, arrays, and objects etc.)
-- another huge mistake.
Note: we did it correctly above, but what if someone made an array for $price? FYI: PHP has no clue what we mean by an Item,
especially by the terms of our class definition above. To PHP, our Item is something with two properties (mutable in every way)
and that's it. As far as PHP is concerned, we can pack the entire set of Britannica Encyclopedias into the price slot. When
that happens, we no longer have what we expect an Item to be.
INSIDE CODE should keep the integrity of the object. For example, our class definition should keep $label a string and $price a
float -- which means only strings can come IN and OUT of the class for label, and only floats can come IN and OUT of the class
for price.
<?php
class Item
{
/**
* Here's the new INSIDE CODE and the Rules to follow:
*
* 1. STOP ACCESS to properties via $item->label and $item->price,
* by using the protected keyword.
* 2. FORCE the use of public functions.
* 3. ONLY strings are allowed IN & OUT of this class for $label
* via the getLabel and setLabel functions.
* 4. ONLY floats are allowed IN & OUT of this class for $price
* via the getPrice and setPrice functions.
*/
protected $label = 'Unknown Item'; // Rule 1 - protected.
protected $price = 0.0; // Rule 1 - protected.
public function getLabel() { // Rule 2 - public function.
return $this->label; // Rule 3 - string OUT for $label.
}
public function getPrice() { // Rule 2 - public function.

return $this->price; // Rule 4 - float OUT for $price.


}
public function setLabel($label) // Rule 2 - public function.
{
/**
* Make sure $label is a PHP string that can be used in a SORTING
* alogorithm, NOT a boolean, number, array, or object that can't
* properly sort -- AND to make sure that the getLabel() function
* ALWAYS returns a genuine PHP string.
*
* Using a RegExp would improve this function, however, the main
* point is the one made above.
*/
if(is_string($label))
{
$this->label = (string)$label; // Rule 3 - string IN for $label.
}
}
public function setPrice($price) // Rule 2 - public function.
{
/**
* Make sure $price is a PHP float so that it can be used in a
* NUMERICAL CALCULATION. Do not accept boolean, string, array or
* some other object that can't be included in a simple calculation.
* This will ensure that the getPrice() function ALWAYS returns an
* authentic, genuine, full-flavored PHP number and nothing but.
*
* Checking for positive values may improve this function,
* however, the main point is the one made above.
*/
if(is_numeric($price))
{
$this->price = (float)$price; // Rule 4 - float IN for $price.
}
}
}
?>
Now there is nothing OUTSIDE CODE can do to obscure the INSIDES of an Item. In other words, every instance of Item will always
look and behave like any other Item complete with a label and a price, AND you can group them together and they will interact
without disruption. Even though there is room for improvement, the basics are there, and PHP will not hassle you... which means
you can keep your hair!

briank at kappacs dot com 10-Nov-2011 12:20


To make (some) object members read-only outside of the class (revisited using PHP 5 magic __get):
<?php
class ReadOnlyMembers {
private $reallyPrivate;
private $justReadOnly;

function __construct () {
$this->reallyPrivate = 'secret';
$this->justReadOnly = 'read only';
}
function __get ($what) {
switch ($what) {
case 'justReadOnly':
return $this->$what;
default:
# Generate an error, throw an exception, or ...
return null;
}
}
function __isset ($what) {
$val = $this->__get($what);
return isset($val);
}
}
$rom = new ReadOnlyMembers();
var_dump($rom->justReadOnly); // string(9) "read only"
$rom->justReadOnly = 'new value'; // Fatal error
var_dump($rom->reallyPrivate); // Fatal error
?>

php at stage-slash-solutions dot com 10-Jul-2011 03:21


access a protected property:
<?php
//Some library I am not allowed to change:
abstract class a
{
protected $foo;
}
class aa extends a
{
function setFoo($afoo)
{
$this->foo = $afoo;
}
}
?>
if you get an instance of aa and need access to $foo:
<?php

class b extends a
{
function getFoo($ainstance)
{
return $ainstance->foo;
}
}
$aainstance=someexternalfunction();
$binstance=new b;
$aafoo=$binstance->getFoo($aainstance);
?>

Marce! 25-Sep-2009 03:04


Please note that protected methods are also available from sibling classes as long as the method is declared in the common
parent. This may also be an abstract method.

In the below example Bar knows about the existence of _test() in Foo because they inherited this method from the same parent.
It does not matter that it was abstract in the parent.
<?php
abstract class Base {
abstract protected function _test();
}

class Bar extends Base {

protected function _test() { }

public function TestFoo() {


$c = new Foo();
$c->_test();
}
}

class Foo extends Base {


protected function _test() {
echo 'Foo';
}
}

$bar = new Bar();


$bar->TestFoo(); // result: Foo
?>

imran at phptrack dot com 18-Aug-2009 02:06


Some Method Overriding rules :
1. In the overriding, the method names and arguments (args) must be same.
Example:
class p { public function getName(){} }
class c extends P{ public function getName(){} }
2. final methods cant be overridden.

3. private methods never participate in the in the overriding because these methods are not visible in the child classes.
Example:
class a {
private function my(){
print "parent:my";
}
public function getmy(){
$this->my();
}
}
class b extends a{
private function my(){
print "base:my";
}
}
$x = new b();
$x->getmy(); // parent:my
4. While overriding decreasing access specifier is not allowed
class a {
public function my(){
print "parent:my";
}
}
class b extends a{
private function my(){
print "base:my";
}
}
//Fatal error: Access level to b::my() must be public (as in class a)

a dot schaffhirt at sedna-soft dot de 29-Jun-2009 12:27


If you miss the "package" keyword in PHP in order to allow access between certain classes without their members being public,
you can utilize the fact, that in PHP the protected keyword allows access to both subclasses and superclasses.
So you can use this simple pattern:
<?php
abstract class Dispatcher {
protected function &accessProperty (self $pObj, $pName) {
return $pObj->$pName;
}
protected function invokeMethod ($pObj, $pName, $pArgs) {
return call_user_func_array(array($pObj, $pName), $pArgs);
}
}
?>
The classes that should be privileged to each other simply extend this dispatcher:
<?php
class Person extends Dispatcher {
private $name;
protected $phoneNumbers;

public function __construct ($pName) {


$this->name = $pName;
$this->phoneNumbers = array();
}
public function addNumber (PhoneNumber $pNumber, $pLabel) {
$this->phoneNumbers[$pLabel] = $pNumber;
// this does not work, because "owner" is protected:
// $pNumber->owner = $this;
// instead, we get a reference from the dispatcher:
$p =& $this->accessProperty($pNumber, "owner");
// ... and change that:
$p = $this;
}
public function call ($pLabel) {
// this does not work since "call" is protected:
// $this->phoneNumbers[$pLabel]->call();

// instead, we dispatch the call request:
$this->invokeMethod($this->phoneNumbers[$pLabel], "call", array());
}
}

class PhoneNumber extends Dispatcher {


private $countryCode;
private $areaCode;
private $number;
protected $owner;

public function __construct ($pCountryCode, $pAreaCode, $pNumber) {
$this->countryCode = $pCountryCode;
$this->areaCode = $pAreaCode;
$this->number = $pNumber;
}
protected function call () {
echo("calling " . $this->countryCode . "-" . $this->areaCode . "-" . $this->number . "\n");
}
}
$person = new Person("John Doe");
$number1 = new PhoneNumber(12, 345, 67890);
$number2 = new PhoneNumber(34, 5678, 90123);
$person->addNumber($number1, "home");
$person->addNumber($number2, "office");
$person->call("home");
?>
Without this pattern you would have to make $owner and call() public in PhoneNumber.
Best regards,

what at ever dot com 04-Dec-2008 05:15


If you have problems with overriding private methods in extended classes, read this:)
The manual says that "Private limits visibility only to the class that defines the item". That means extended children classes

do not see the private methods of parent class and vice versa also.
As a result, parents and children can have different implementations of the "same" private methods, depending on where you call
them (e.g. parent or child class instance). Why? Because private methods are visible only for the class that defines them and
the child class does not see the parent's private methods. If the child doesn't see the parent's private methods, the child
can't override them. Scopes are different. In other words -- each class has a private set of private variables that no-one
else has access to.
A sample demonstrating the percularities of private methods when extending classes:
<?php
abstract class base {
public function inherited() {
$this->overridden();
}
private function overridden() {
echo 'base';
}
}
class child extends base {
private function overridden() {
echo 'child';
}
}
$test = new child();
$test->inherited();
?>
Output will be "base".
If you want the inherited methods to use overridden functionality in extended classes but public sounds too loose, use
protected. That's what it is for:)
A sample that works as intended:
<?php
abstract class base {
public function inherited() {
$this->overridden();
}
protected function overridden() {
echo 'base';
}
}
class child extends base {
protected function overridden() {
echo 'child';
}
}
$test = new child();
$test->inherited();
?>
Output will be "child".

Jeffrey 09-Oct-2008 05:48

WHEN do I use public, protected or private keyword? Here's the default behavior.
<?php
class Example
{
/* use PUBLIC on variables and functions when:
* 1. outside-code SHOULD access this property or function.
* 2. extending classes SHOULD inherit this property or function.
*/
public $var1;
public function someFunction_1() { }
/* use PROTECTED on variables and functions when:
* 1. outside-code SHOULD NOT access this property or function.
* 2. extending classes SHOULD inherit this property or function.
*/
protected $var2;
protected function someFunction_2() { }
/* use PRIVATE on variables and functions when:
* 1. outside-code SHOULD NOT access this property or function.
* 2. extending classes SHOULD NOT inherit this property or function.
*/
private $var3;
private function someFunction_3() { }
}
# these are the only valid calls outside-code can make on Example objects:
$obj1 = new Example(); // instantiate
$var1 = $obj1->var1; // get public data
$obj1->var1 = 35; // set public data
$obj1->someFunction_1(); // call public function
?>
Now try extending the class...
<?php
class Example_2 extends Example
{
// this class inherits the following properties and functions.
public $var1;
public function someFunction_1() { }
protected $var2;
protected function someFunction_2() { }
}
# these are the only valid calls outside-code can make on Example_2 objects:
$obj2 = new Example_2(); // instantiate
$var2 = $obj2->var1; // get public data
$obj2->var1 = 45; // set public data
$obj2->someFunction_1(); // call public function
?>

wbcarts at juno dot com 10-Sep-2008 02:21


UNDERSTANDING PHP's OBJECT VISIBILITY
Sometimes it's good to see a list of many extended classes, one right after the other - just for the sole purpose of looking
at their inherited members. Maybe this will help:

<?php
class MyClass_1{
public $pubVal = 'Hello World!';
protected $proVal = 'Hello FROM MyClass_1';
private $priVal = 'Hello TO MyClass_1';
public function __toString(){
return "MyClass_1[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_2 extends MyClass_1{
public function __toString(){
return "MyClass_2[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_3 extends MyClass_2{
private $priVal = 'Hello TO MyClass_3';
public function __toString(){
return "MyClass_3[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_4 extends MyClass_3{
protected $proVal = 'Hello FROM MyClass_4';
public function __toString(){
return "MyClass_4[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_5 extends MyClass_4{
public function __toString(){
return "MyClass_5[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_6 extends MyClass_5{
private $priVal = 'Hello TO MyClass_6';
public function __toString(){
return "MyClass_6[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
echo (new MyClass_1()) . '<br>';
echo (new MyClass_2()) . '<br>';
echo (new MyClass_3()) . '<br>';
echo (new MyClass_4()) . '<br>';
echo (new MyClass_5()) . '<br>';
echo (new MyClass_6()) . '<br>';
?>
The list of extended objects:
MyClass_1[public=Hello World!, protected=Hello FROM MyClass_1, private=Hello TO MyClass_1]
MyClass_2[public=Hello World!, protected=Hello FROM MyClass_1, private=]
MyClass_3[public=Hello World!, protected=Hello FROM MyClass_1, private=Hello TO MyClass_3]

MyClass_4[public=Hello World!, protected=Hello FROM MyClass_4, private=]


MyClass_5[public=Hello World!, protected=Hello FROM MyClass_4, private=]
MyClass_6[public=Hello World!, protected=Hello FROM MyClass_4, private=Hello TO MyClass_6]
Notice in the class definitions, I made absolutly no attempt to change protected members to private, etc. - that gets too
confusing and is not necessary - though I did redeclare a few members with the same var name and visibility strength. One other
noteworthy: the output for MyClass_2, there seems to be a private property with value of empty string. Here, $priVal was not
inherited from MyClass_1 because it is private in MyClass_1, instead, because of PHP's relaxed syntax, it was actually created
right there in MyClass2::__toString() method... not only that, it is not a private member either. Watch out for this kind of
thing, as PHP can sometimes give confusing impressions.

omnibus at omnibus dot edu dot pl 13-Dec-2007 06:34


Please note that if a class has a protected variable, a subclass cannot have the same variable redefined private (must be
protected or weaker). It seemed to be logical for me as a subsubclass would not know if it could see it or not but even if you
declare a subclass to be final the restriction remains.

phpdoc at povaddict dot com dot ar 11-Oct-2007 12:52


Re: ference at super_delete_brose dot co dot uk
"If eval() is the answer, youre almost certainly asking the wrong question."
<?php
eval('$result = $this->'.$var.';'); //wrong
$result = $this->$var; //right way
$var = "foo";
$this->var = "this will assign to member called 'var'.";
$this->$var = "this will assign to member called 'foo'.";
?>

Joshua Watt 29-May-2007 12:09


I couldn't find this documented anywhere, but you can access protected and private member varaibles in different instance of
the same class, just as you would expect
i.e.
<?php
class A
{
protected $prot;
private $priv;

public function __construct($a, $b)


{
$this->prot = $a;
$this->priv = $b;
}

public function print_other(A $other)


{
echo $other->prot;
echo $other->priv;
}
}

class B extends A
{
}
$a = new A("a_protected", "a_private");
$other_a = new A("other_a_protected", "other_a_private");
$b = new B("b_protected", "ba_private");
$other_a->print_other($a); //echoes a_protected and a_private
$other_a->print_other($b); //echoes b_protected and ba_private
$b->print_other($a); //echoes a_protected and a_private
?>

ference at super_delete_brose dot co dot uk 22-May-2007 10:10


Sometimes you may wish to have all members of a class visible to other classes, but not editable - effectively read-only.
In this case defining them as public or protected is no good, but defining them as private is too strict and by convention
requires you to write accessor functions.
Here is the lazy way, using one get function for accessing any of the variables:
<?php
class Foo {
private $a;
private $b;
private $c;
private $d;
private $e;
private $f;
public function __construct() {
$this->a = 'Value of $a';
$this->b = 'Value of $b';
$this->c = 'Value of $c';
$this->d = 'Value of $d';
$this->e = 'Value of $e';
$this->f = 'Value of $f';
}
/* Accessor for all class variables. */
public function get($what) {
$result = FALSE;
$vars = array_keys(get_class_vars('Foo'));
foreach ($vars as $var) {
if ($what == $var) {
eval('$result = $this->'.$var.';');
return $result;
}
}
return $result;
}
}

class Bar {
private $a;
public function __construct() {
$foo = new Foo();
var_dump($foo->get('a')); // results in: string(11) "Value of $a"
}
}
$bar = new Bar();
?>

nanocaiordo at gmail dot com 08-Apr-2007 06:49


If you always thought how can you use a private method in php4 classes then try the following within your class.
<?php
function private_func($func)
{
$this->file = __FILE__;
if (PHPVERS >= 43) {
$tmp = debug_backtrace();
for ($i=0; $i<count($tmp); ++$i) {
if (isset($tmp[$i]['function'][$func])) {
if ($this->file != $tmp[$i]['file']) {
trigger_error('Call to a private method '.__CLASS__.'::'.$func.' in '.$tmp[$i]['file'], E_USER_ERROR);
}
}
}
}
}
?>
Then inside the private function add:
<?php
function foo() {
$this->private_func(__FUNCTION__);
# your staff goes here
}
?>

stephane at harobed dot org 23-Aug-2006 02:22


A class A static public function can access to class A private function :
<?php
class A {
private function foo()
{
print("bar");
}
static public function bar($a)
{
$a->foo();
}

}
$a = new A();
A::bar($a);
?>
It's working.

kakugo at kakugo dot com 13-Jul-2006 03:19


This refers to previous notes on protected members being manipulated externally:
It is obvious that if you were to allow methods the option of replacing protected variables with external ones it will be
possible, but there is no reason not to simply use a protected method to define these, or not to write the code to allow it.
Just because it is possible doesn't mean it's a problem, it simply does not allow you to be lax on the security of the class.

r dot wilczek at web-appz dot de 05-Jan-2006 05:11


Beware: Visibility works on a per-class-base and does not prevent instances of the same class accessing each others properties!
<?php
class Foo
{
private $bar;
public function debugBar(Foo $object)
{
// this does NOT violate visibility although $bar is private
echo $object->bar, "\n";
}
public function setBar($value)
{
// Neccessary method, for $bar is invisible outside the class
$this->bar = $value;
}

public function setForeignBar(Foo $object, $value)


{
// this does NOT violate visibility!
$object->bar = $value;
}
}
$a = new Foo();
$b = new Foo();
$a->setBar(1);
$b->setBar(2);
$a->debugBar($b); // 2
$b->debugBar($a); // 1
$a->setForeignBar($b, 3);
$b->setForeignBar($a, 4);
$a->debugBar($b); // 3
$b->debugBar($a); // 4
?>

gugglegum at gmail dot com 02-Sep-2005 03:14


Private visibility actually force members to be not inherited instead of limit its visibility. There is a small nuance that
allows you to redeclare private member in child classes.
<?php
class A
{
private $prop = 'I am property of A!';
}
class B extends A
{
public $prop = 'I am property of B!';
}
$b = new B();
echo $b->prop; // "I am property of B!"
?>

Miguel <miguel at lugopolis dot net> 21-Jul-2005 08:10


A note about private members, the doc says "Private limits visibility only to the class that defines the item" this says that
the following code works as espected:
<?php
class A {
private $_myPrivate="private";
public function showPrivate()
{
echo $this->_myPrivate."\n";
}
}
class B extends A {
public function show()
{
$this->showPrivate();
}
}
$obj=new B();
$obj->show(); // shows "private\n";
?>
this works cause A::showPrivate() is defined in the same class as $_myPrivate and has access to it.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Object Inheritance
Inheritance is a well-established programming principle, and PHP makes use of this principle in its object model.
This principle will affect the way many classes and objects relate to one another.
For example, when you extend a class, the subclass inherits all of the public and protected methods from the
parent class. Unless a class overrides those methods, they will retain their original functionality.
This is useful for defining and abstracting functionality, and permits the implementation of additional
functionality in similar objects without the need to reimplement all of the shared functionality.
Note:
Unless autoloading is used, then classes must be defined before they are used. If a class extends another,
then the parent class must be declared before the child class structure. This rule applies to classes that
inherit other classes and interfaces.
Example #1 Inheritance Example
<?php
classfoo
{
publicfunctionprintItem($string)
{
echo'Foo:'.$string.PHP_EOL;
}

publicfunctionprintPHP()
{
echo'PHPisgreat.'.PHP_EOL;
}
}
classbarextendsfoo
{
publicfunctionprintItem($string)
{
echo'Bar:'.$string.PHP_EOL;
}
}
$foo=newfoo();
$bar=newbar();
$foo->printItem('baz');//Output:'Foo:baz'
$foo->printPHP();//Output:'PHPisgreat'
$bar->printItem('baz');//Output:'Bar:baz'
$bar->printPHP();//Output:'PHPisgreat'
?>

User Contributed Notes

Object Inheritance

maximark at libero dot it 30-May-2012 09:55

MULTI INHERITANCE
<?php
class A
{
public function meth1()
{
echo "meth1";
}
public function meth2()
{
B::meth2();
}
}
class B
{
public function meth2()
{
echo "<br/>meth2 ".get_class($this);
}
}
$a = new A();
$a->meth2();
$b = new B();
$b->meth2();
?>

msg2maciej at aol dot com 28-Jan-2011 04:08


PHP supports single class inheritance. My bare idea on accessing protected methods with power of abstracts and sort of "multiclass inheritance SIMULATION":
<?php
error_reporting(E_ALL);
abstract class Base {
abstract protected function __construct ();
abstract protected function hello_left ();
abstract protected function hello_right ();
}
abstract class NotImplemented_Left extends Base {
protected function hello_right () {
echo 'well, wont see that'; }}
abstract class NotImplemented_Right extends Base {
protected function hello_left () {
echo 'well, wont see that'; }}
class Left extends NotImplemented_Left {
protected function __construct () { # limited visibility, no access from "outside"
echo __CLASS__.'::protected __construct'. "\n"; }
protected function hello_left () { # limited visibility, no access from "outside"
echo 'protected hello_left in ' . __CLASS__ . "\n"; }}
class Right extends NotImplemented_Right {

protected function __construct () { # limited visibility, no access from "outside"


echo __CLASS__.'::protected __construct'. "\n"; }
protected function hello_right () { # limited visibility, no access from "outside"
echo 'protected hello_right in ' . __CLASS__ . "\n"; }
protected function hello_left () {
echo "wont see that, and easy to get rid of it from here\n"; }}
class Center extends Base {
private $left;
private $right;
public function __construct () {
echo 'welcome in ' . __CLASS__ . "\n";
echo 'Center::'; $this->left = new Left;
echo 'Center::'; $this->right = new Right;
echo " oh and\n";
$this->hello_left();
$this->hello_right();
}
public function hello_left () { # calling class Left
echo __CLASS__.'::'; $this->left->hello_left(); }
public function hello_right () { # calling class Right
echo __CLASS__.'::'; $this->right->hello_right(); }
}
$c = new Center;
?>
Produces:
welcome in Center
Center::Left::protected __construct
Center::Right::protected __construct
oh and
Center::protected hello_left in Left
Center::protected hello_right in Right

OZ 14-Nov-2010 03:24
Model for Mixins pattern:
<?php
interface IMixinsCaller
{
public function __mixin_get_property($property);
public function __mixin_set_property($property, $value);
public function __mixin_call($method, $value);
}
abstract class MixinsCaller implements IMixinsCaller
{
protected $mixins = array();
public function __call($name, $arguments)
{
if (!empty($this->mixins))
{
foreach ($this->mixins as $mixin)

{
if (method_exists($mixin, $name))
{
return call_user_func_array(array($mixin, $name), $arguments);
}
}
}
trigger_error('Non-existent method was called in class '.__CLASS__.': '.$name, E_USER_WARNING);
}
public function __mixin_get_property($property)
{
if (property_exists($this, $property))
{
return $this->$property;
}
trigger_error('Non-existent property was get in class '.__CLASS__.': '.$property, E_USER_WARNING);
}
public function __mixin_set_property($property, $value)
{
if (property_exists($this, $property))
{
return $this->$property = $value;
}
trigger_error('Non-existent property was set in class '.__CLASS__.': '.$property, E_USER_WARNING);
}
public function __mixin_call($method, $value)
{
if (method_exists($this, $method))
{
return call_user_func_array(array($this, $method), $value);
}
trigger_error('Non-existent method was called in class '.__CLASS__.': '.$method, E_USER_WARNING);
}
public function AddMixin($mixin)
{
$this->mixins[] = $mixin;
}
}
abstract class Mixin
{
/** @var IMixinsCaller $parent_object */
private $parent_object;
public function __construct(IMixinsCaller $parent_object)
{
$this->parent_object = $parent_object;
}
public function __get($property)
{
return $this->parent_object->__mixin_get_property($property);
}
public function __set($property, $value)
{

return $this->parent_object->__mixin_set_property($property, $value);


}
public function __call($method, $value)
{
return $this->parent_object->__mixin_call($method, $value);
}
}
?>

janturon at email dot cz 22-Sep-2010 10:11


Here is an easy way how to implement multiple inheritance in PHP using magic methods. Let's have this class:
class Extender {
private $objs = array();
public function __construct() {
$drones = func_get_args();
foreach($drones as $drone) $this->objs[$drone] = new $drone();
foreach($this->objs as $obj) $obj->hive = $this;
}
public function __get($attr) {
foreach($this->objs as $obj)
if(isset($obj->$attr))
return $obj->$attr;
}
public function __set($attr,$val) {
if($attr=="hive") return;
foreach($this->objs as $obj)
if(isset($obj->$attr))
$obj->$attr = $val;
}
public function __call($meth,$args) {
foreach($this->objs as $obj)
if(method_exists($obj,$meth))
return call_user_func_array(array($obj,$meth),$args);
}
}
Now multiple inheritance can be written this way ($hive is reference to child classes)
class c1 {
public $p1 = "x";
function f1() { echo $this->p1; }
}
class c2 {
public $p2 = "x";
function f2() { echo $this->p2; }
}
class c_extends_c1_c2 {
static $hive;
function test() {
$this->hive->p1 = "hello,";
$this->hive->p2 = "world!";
return $this->hive->f1() . $this->hive->f2();
}
}

And here is how to use it:


$obj = new Extender("c1","c2","c_extends_c1_c2");
echo $obj->test(); //"hello,world!"

strata_ranger at hotmail dot com 19-Sep-2010 09:37


I was recently extending a PEAR class when I encountered a situation where I wanted to call a constructor two levels up the
class hierarchy, ignoring the immediate parent. In such a case, you need to explicitly reference the class name using the ::
operator.
Fortunately, just like using the 'parent' keyword PHP correctly recognizes that you are calling the function from a protected
context inside the object's class hierarchy.
E.g:
<?php
class foo
{
public function something()
{
echo __CLASS__; // foo
var_dump($this);
}
}
class foo_bar extends foo
{
public function something()
{
echo __CLASS__; // foo_bar
var_dump($this);
}
}
class foo_bar_baz extends foo_bar
{
public function something()
{
echo __CLASS__; // foo_bar_baz
var_dump($this);
}
public function call()
{
echo self::something(); // self
echo parent::something(); // parent
echo foo::something(); // grandparent
}
}
error_reporting(-1);
$obj = new foo_bar_baz();
$obj->call();
// Output similar to:
// foo_bar_baz

// object(foo_bar_baz)[1]
// foo_bar
// object(foo_bar_baz)[1]
// foo
// object(foo_bar_baz)[1]
?>

jackdracona at msn dot com 14-Apr-2010 08:53


Here is some clarification about PHP inheritance there is a lot of bad information on the net. PHP does support Multi-level
inheritance. (I tested it using version 5.2.9). It does not support multiple inheritance.

This means that you cannot have one class extend 2 other classes (see the extends keyword). However, you can have one class
extend another, which extends another, and so on.

Example:

<?php
class A {
// more code here
}

class B extends A {
// more code here
}

class C extends B {
// more code here
}

$someObj = new A(); // no problems


$someOtherObj = new B(); // no problems
$lastObj = new C(); // still no problems

?>

php at sleep is the enemy dot co dot uk 07-Apr-2010 02:36


Here's fun, an attempt to make some degree of multiple inheritance work in PHP using mixins. It's not particularly pretty,
doesn't support method visibility modifiers and, if put to any meaningful purpose, could well make your call stack balloon to
Ruby-on-Rails-esque proportions, but it does work.
<?php
abstract class Mix {

protected $_mixMap = array();

public function __construct(){



$this->_mixMap = $this->collectMixins($this);
}

public function __call($method, $args){



// doesn't pass scope
//return call_user_func_array(array($className, $method), $args);


// Error: Given object is not an instance of the class this method was declared in
//$method = new ReflectionMethod($className, $method);
//return $method->invokeArgs($this, $args);

$payload = $this->buildMixinPayload($this->_mixMap, $method, $args);
if(!$payload) throw new Exception('Method ' . $method . ' not found');

list($mixinMethod, list($method, $args)) = $payload;

return $this->$mixinMethod($method, $args);

}

protected function collectMixins($class){



static $found = array();
static $branch = array();

if(empty($branch)) $branch[] = get_class($this);
$mixins = array();

foreach(array_reverse(get_class_methods($class)) as $method){
if(preg_match('/^mixin(\w+)$/', $method, $matches)){

$className = $matches[1];

if(in_array($className, $branch))
throw new Exception('Circular reference detected ' . implode(' > ', $branch) . ' > ' . $className);

if(!in_array($className, $found)){

if(!class_exists($className)) throw new Exception('Class ' . $className . ' not found');

// populate props from mixin class
foreach(get_class_vars($className) as $key => $value){
if(!property_exists($this, $key)) $this->$key = $value;
}

$found[] = $branch[] = $className;
$mixins[$className] = $this->collectMixins($className);
}

$branch = array(get_class($this));
}
}

return $mixins;
}

protected function buildMixinPayload($mixins, $method, $args){



foreach($mixins as $className => $parents){

$mixinMethod = 'mixin' . $className;

if(method_exists($className, $method)) return array($mixinMethod, array($method, $args));

if(!empty($parents) && $return = $this->buildMixinPayload($parents, $method, $args)){
return array($mixinMethod, $return);

}
}

return false;
}

}
?>

php at sleep is the enemy dot co dot uk 31-Mar-2010 07:47


Here's some example usage of the mixin class.
<?php
class Lunch extends Mix {

public $edible = true;

/*
* Circular references are, of course, illegal and will be detected
*/
/*
public function mixinSteakAndKidneyPie($method, $args){
return SteakAndKidneyPie::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}
//*/

public function isEdible($affirm, $negate){


return $this->edible ? $affirm : $negate;
}
}
class Pie extends Mix {

/*
* class tokens are bound at compile time so need to be explicitly declared
* Need to make sure there are enough argument placeholders to cover all mixed in methods of Lunch
* Late static binding may improve this situation
*/
public function mixinLunch($method, $args){
return Lunch::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}

public function buildPie($sep = ','){


return 'Crust' . $sep . $this->getFilling() . $sep . 'More Crust';
}

public function getFilling(){


$this->edible = false;
return 'Baking beans';
}
}
class SteakAndKidney extends Mix {

public function mixinLunch($method, $args){


return Lunch::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}


/*
* everything to be mixed in must be public
* protected/private methods called from within mixed in methods will fail
*/
public $filling = 'Steak and Kidney';

public function getFilling(){


$this->edible = true;
return $this->filling;
}
}
class SteakAndKidneyPie extends Mix {

/*
* order of mixin declaration significant
* later declarations override earlier ones
*/
public function mixinSteakAndKidney($method, $args){
return SteakAndKidney::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}

public function mixinPie($method, $args){


return Pie::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}

/*
* Pick specific methods like so:
*/
//*
public function getFilling(){
return SteakAndKidney::getFilling();
}
//*/

}
$pie = new SteakAndKidneyPie();
echo $pie->buildPie(' | ');
echo '<br/>Pie ' . $pie->isEdible('is', 'is not') . ' Edible';
/*
OUTPUTS:
Crust | Steak and Kidney | More Crust
Pie is Edible
*/
?>

jarrod at squarecrow dot com 27-Oct-2009 06:01


You can force a class to be strictly an inheritable class by using the "abstract" keyword. When you define a class with
abstract, any attempt to instantiate a separate instance of it will result in a fatal error. This is useful for situations like
a base class where it would be inherited by multiple child classes yet you want to restrict the ability to instantiate it by
itself.
Example........

<?php
abstract class Cheese
{
//can ONLY be inherited by another class
}
class Cheddar extends Cheese
{
}
$dinner = new Cheese; //fatal error
$lunch = new Cheddar; //works!
?>

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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 properties 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
classMyClass{
constCONST_VALUE='Aconstantvalue';
}
$classname='MyClass';
echo$classname::CONST_VALUE;//AsofPHP5.3.0
echoMyClass::CONST_VALUE;
?>

Three special keywords self, parent and static are used to access properties or methods from inside the class
definition.
Example #2 :: from inside the class definition
<?php
classOtherClassextendsMyClass
{
publicstatic$my_static='staticvar';
publicstaticfunctiondoubleColon(){
echoparent::CONST_VALUE."\n";
echoself::$my_static."\n";
}
}
$classname='OtherClass';
echo$classname::doubleColon();//AsofPHP5.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.
Example #3 Calling a parent's method
<?php

classMyClass
{
protectedfunctionmyFunc(){
echo"MyClass::myFunc()\n";
}
}
classOtherClassextendsMyClass
{
//Overrideparent'sdefinition
publicfunctionmyFunc()
{
//Butstillcalltheparentfunction
parent::myFunc();
echo"OtherClass::myFunc()\n";
}
}
$class=newOtherClass();
$class->myFunc();
?>

See also some examples of static call trickery.

User Contributed Notes

Scope Resolution Operator (::)

phil at philfreo dot com 19-Aug-2010 10:00


I'm not sure if this was intentional or not, but it's worth noting...
As of PHP5.3 you can can say:
<?php
class Foo {
public function __construct($logClass = 'MyLog') {
$logClass::write();
}
}
?>
But you CANNOT say:
<?php
class Foo {
protected $log;
public function __construct($logClass = 'MyLog') {
$this->log = $logClass;
$this->log::write(); // breaks
}
}
?>
NOR can you say:
<?php
class Foo {
protected static $log;

public function __construct($logClass = 'MyLog') {


self::$log = $logClass;
self::$log::write(); // breaks
}
}
?>

remy dot damour at ----no-spam---laposte dot net 05-May-2010 01:50


As of php 5.3.0, you can use 'static' as scope value as in below example (add flexibility to inheritance mechanism compared to
'self' keyword...)
<?php
class A {
const C = 'constA';
public function m() {
echo static::C;
}
}
class B extends A {
const C = 'constB';
}
$b = new B();
$b->m();
// output: constB
?>

Theriault 05-Dec-2009 08:58


A class constant, class property (static), and class function (static) can all share the same name and be accessed using the
double-colon.
<?php
class A {
public static $B = '1'; # Static class variable.
const B = '2'; # Class constant.

public static function B() { # Static class function.


return '3';
}

}
echo A::$B . A::B . A::B(); # Outputs: 123
?>

wouter at interpotential dot com 09-Nov-2009 07:24


It's worth noting, that the mentioned variable can also be an object instance. This appears to be the easiest way to refer to
a static function as high in the inheritance hierarchy as possible, as seen from the instance. I've encountered some odd
behavior while using static::something() inside a non-static method.

See the following example code:


<?php
class FooClass {
public function testSelf() {
return self::t();
}
public function testThis() {
return $this::t();
}
public static function t() {
return 'FooClass';
}
function __toString() {
return 'FooClass';
}
}
class BarClass extends FooClass {
public static function t() {
return 'BarClass';
}
}
$obj = new BarClass();
print_r(Array(
$obj->testSelf(), $obj->testThis(),
));
?>
which outputs:
<pre>
Array
(
[0] => FooClass
[1] => BarClass
)
</pre>
As you can see, __toString has no effect on any of this. Just in case you were wondering if perhaps this was the way it's
done.

giovanni at gargani dot it 02-Jun-2009 06:38


Well, a "swiss knife" couple of code lines to call parent method. The only limit is you can't use it with "by reference"
parameters.
Main advantage you dont need to know the "actual" signature of your super class, you just need to know which arguments do you
need
<?php
class someclass extends some superclass {
// usable for constructors
function __construct($ineedthisone) {

$args=func_get_args();
/* $args will contain any argument passed to __construct.
* Your formal argument doesnt influence the way func_get_args() works
*/
call_user_func_array(array('parent',__FUNCTION__),$args);
}
// but this is not for __construct only
function anyMethod() {
$args=func_get_args();
call_user_func_array(array('parent',__FUNCTION__),$args);
}
// Note: php 5.3.0 will even let you do
function anyMethod() {
//Needs php >=5.3.x
call_user_func_array(array('parent',__FUNCTION__),func_get_args());
}
}
?>

erwinhaantjes at interurbia dot nl 11-Apr-2009 02:36


Here is a nice function i like to share with you because it so nice and handy feature. I wanted to get rid off the
parent::methodName(myVar1, myVar2, myVar3 etc.....) construction so i wrote a shortcut to this notation. The only thing you
have to do is calling $this->inherited() (or parent::inherited()) to call the same function with the same parameters in the
parent class. It is also possible to specify other parameters if you like. You can also use this inside
constructors/destructors.
To use this example, put it in the base class of all objects.You also need the simple function below to test if an array is
valid (from a self-build library) but you are free to change it to your own needs ;-):
<?php
function suIsValidArray( &$a, &$iCount = null )
{
$iCount = 0;
return ( is_array( $a ) and (( $iCount = @count( $a )) > 0 ));
}
?>
The inherited function/construction is familiar language construction in Object Pascal/Delphi (wonderful language). If you have
any comments, please enter a note.
Here it is:
<?php
public function inherited()
{
// Use DEBUG backtrace to trace caller function
$bt = debug_backtrace();
$bt = $bt[ 1 ]; // List is in reversed order, 0 reffers to this function so get previous one

if( !suIsValidArray( $bt ))
{ return; }

$sClassName = $bt["class"];
$sParentClassName = get_parent_class( $sClassName );
if( empty( $sClassName ) or empty( $sParentClassName ) or $sParentClassName == $sClassName )
{ return; }

$sFuncName = $bt["function"];
// constructor or destructor called (old fashion way)?
if( ( $bIsConstruct = ( $sFuncName == $sClassName )) or ( $sFuncName == "_".$sClassName ) )
{
// get parent constructor/destructor
$sFuncName = (( !$bIsConstruct ) ? "_" : "" ).$sParentClassName;
if( $sFuncName == (( !$bIsConstruct ) ? "_" : "" ).$sClassName )
{ return; }
}

if( method_exists( $sParentClassName, $sFuncName ))
{
// If there are parameters specified, use these
$args = func_get_args();
if( !suIsValidArray( $args ))
{ $args = &$bt["args"]; } // otherwise use previous function parameters if any

$iCount = 0;
$sArgs = "";
if( suIsValidArray( $args, $iCount ))
{
for( $i = 0; $i < $iCount; $i++ )
{ $sArgs.="&$"."args[$i]".( $i < ($iCount-1) ? "," : "" ); }
}

// Simple, evaluate it, this is possible because it is done inside the class itself, and
// the parent class is already created because is a part of the class structure, no worry, no scope issues
eval( "$"."result = $sParentClassName::".$sFuncName."($sArgs);" );
return @$result;
}
}
?>

csaba dot dobai at php-sparcle dot com 03-Feb-2009 09:54


For the 'late static binding' topic I published a code below, that demonstrates a trick for how to setting variable value in
the late class, and print that in the parent (or the parent's parent, etc.) class.
<?php
class cA
{
/**
* Test property for using direct default value
*/
protected static $item = 'Foo';

/**
* Test property for using indirect default value
*/
protected static $other = 'cA';

public static function method()


{
print self::$item."\r\n"; // It prints 'Foo' on everyway... :(
print self::$other."\r\n"; // We just think that, this one prints 'cA' only, but... :)
}

public static function setOther($val)

{
self::$other = $val; // Set a value in this scope.
}
}
class cB extends cA
{
/**
* Test property with redefined default value
*/
protected static $item = 'Bar';

public static function setOther($val)


{
self::$other = $val;
}
}
class cC extends cA
{
/**
* Test property with redefined default value
*/
protected static $item = 'Tango';

public static function method()


{
print self::$item."\r\n"; // It prints 'Foo' on everyway... :(
print self::$other."\r\n"; // We just think that, this one prints 'cA' only, but... :)
}

/**
* Now we drop redeclaring the setOther() method, use cA with 'self::' just for fun.
*/
}
class cD extends cA
{
/**
* Test property with redefined default value
*/
protected static $item = 'Foxtrot';

/**
* Now we drop redeclaring all methods to complete this issue.
*/
}
cB::setOther('cB'); // It's cB::method()!
cB::method(); // It's cA::method()!
cC::setOther('cC'); // It's cA::method()!
cC::method(); // It's cC::method()!
cD::setOther('cD'); // It's cA::method()!
cD::method(); // It's cA::method()!
/**
* Results: ->
* Foo
* cB
* Tango

* cC
* Foo
* cD
*
* What the hell?! :)
*/
?>

luka8088 at gmail dot com 24-Jan-2009 03:15


Little static trick to go around php strict standards ...
Function caller founds an object from which it was called, so that static method can alter it, replacement for $this in static
function but without strict warnings :)
<?php
error_reporting(E_ALL + E_STRICT);
function caller () {
$backtrace = debug_backtrace();
$object = isset($backtrace[0]['object']) ? $backtrace[0]['object'] : null;
$k = 1;

while (isset($backtrace[$k]) && (!isset($backtrace[$k]['object']) || $object === $backtrace[$k]['object']))
$k++;
return isset($backtrace[$k]['object']) ? $backtrace[$k]['object'] : null;
}
class a {
public $data = 'Empty';

function set_data () {
b::set();
}
}
class b {
static function set () {
// $this->data = 'Data from B !';
// using this in static function throws a warning ...
caller()->data = 'Data from B !';
}
}
$a = new a();
$a->set_data();
echo $a->data;
?>
Outputs: Data from B !
No warnings or errors !

barss dot dev at gmail dot com 01-Jul-2008 03:47


Nice trick with scope resolution
<?php
class A
{
public function TestFunc()
{
return $this->test;
}
}
class B
{
public $test;
public function __construct()
{
$this->test = "Nice trick";
}
public function GetTest()
{
return A::TestFunc();
}
}
$b = new B;
echo $b->GetTest();
?>
will output
Nice trick

richard at richard-sumilang dot com 24-Mar-2008 06:27


Actually, for people not using PHP 5.3 yet you should try avoiding the use of a eval() at all costs! THere are too many
security risks and dirty code that come from using eval. If you want to call a static method from a class then you can use
call_user_func() instead which is much safer.
Example:
clas Foo{
public static method Bar(){
echo "Hello world!";
}
}
And to execute that with call_user_func you would do the following:
call_user_func(array('Foo', 'bar') [, $params] );
Thanks,
- Richard S.

thomas dot sahlin at gmail dot com 27-Dec-2007 04:15


If you need to reference a class using a variable (prior to PHP 5.3.0) you may use something like this:
<?php
$className = 'MyClass';
eval('$foo = ' . $className . '::myFunction();');
var_dump($foo);
?>

Anonymous 16-Oct-2007 03:41


There's no surprize here. These resolution rules are identical in C++ and Java, where static fields (and methods) are not
separately instanciated within the inheritance tree for the new derived classes.
This is per design. If you want per-class static fields,you have to overload each static field (or method) to assign them a
new value that will hide the inherited static field (or method). The "$self::" scope in a static method does not refer to the
object or class from which the method is called, as it is statically compiled and resolved within the class declaring the
method.
In other words "$self::" is just needed to specify the field declared in the defining class, instead of a homonym variable (or
function) in the local scope which may hide it. This is exactly similar to the "this." scope specifier (used with the "."
operator here) used in C++ (or Java).
The same can be said about the semantic of "$super::" used within a static method (similar to "super." scope specifier used in
C++ or Java).
Neither PHP, nor C++, have a way to work on instanciated class objects as if they were objects of the first grade (that's why
C++ and Java are making distinctions between classes and interfaces).
On the opposite Javascript/ECMAScript defines classes like standard objects with a "prototype" field for the fields (or
methods) to inherit instead of duplicating them with the new operator. When working in PHP, forget Javascript, think like in
C++ and Java.

mongoose643 at gmail dot com 13-Feb-2007 12:11


This is a solution for those that still need to write code compatible with php 4 but would like to use the flexibility of
static variables. PHP 4 does not support static variables within the class scope but it does support them within the scope of
class methods. The following is a bit of a workaround to store data in static mode in php 4.
Note: This code also works in PHP 5.
(Tested on version 4.3.1+)
The tricky part is when using when arrays you have to do a bit of fancy coding to get or set individual elements in the array.
The example code below should show you the basics of it though.
<?php
class StaticSample
{
//Copyright Michael White (www.crestidg.com) 2007
//You may use and modify this code but please keep this short copyright notice in tact.
//If you modify the code you may comment the changes you make and append your own copyright
//notice to mine. This code is not to be redistributed individually for sale but please use it as part
//of your projects and applications - free or non-free.

//Static workaround for php4 - even works with arrays - the trick is accessing the arrays.
//I used the format s_varname for my methods that employ this workaround. That keeps it
//similar to working with actual variables as much as possible.
//The s_ prefix immediately identifies it as a static variable workaround method while
//I'm looking thorugh my code.
function &s_foo($value=null, $remove=null)
{
static $s_var; //Declare the static variable. The name here doesn't matter - only the name of the method matters.

if($remove)
{
if(is_array($value))
{
if(is_array($s_var))
{
foreach($value as $key => $data)
{
unset($s_var[$key]);
}
}
}
else
{
//You can't just use unset() here because the static state of the variable will bring back the value next time
you call the method.
$s_var = null;
unset($s_var);
}
//Make sure that you don't set the value over again.
$value = null;
}
if($value)
{
if(is_array($value))
{
if(is_array($s_var))
{
//$s_var = array_merge($s_var, $value); //Doesn't overwrite values. This adds them - a property of
the array_merge() function.
foreach($value as $key => $data)
{
$s_var[$key] = $data; //Overwrites values.
}
}
else
{
$s_var = $value;
}
}
else
{
$s_var = $value;
}
}

return $s_var;
}
}

echo "Working with non-array values.<br>";


echo "Before Setting: ".StaticSample::s_foo();
echo "<br>";
echo "While Setting: ".StaticSample::s_foo("VALUE HERE");
echo "<br>";
echo "After Setting: ".StaticSample::s_foo();
echo "<br>";
echo "While Removing: ".StaticSample::s_foo(null, 1);
echo "<br>";
echo "After Removing: ".StaticSample::s_foo();
echo "<hr>";
echo "Working with array values<br>";
$array = array(0=>"cat", 1=>"dog", 2=>"monkey");
echo "Set an array value: ";
print_r(StaticSample::s_foo($array));
echo "<br>";
//Here you need to get all the values in the array then sort through or choose the one(s) you want.
$all_elements = StaticSample::s_foo();
$middle_element = $all_elements[1];
echo "The middle element: ".$middle_element;
echo "<br>";
$changed_array = array(1=>"big dog", 3=>"bat", "bird"=>"flamingo");
echo "Changing the value: ";
print_r(StaticSample::s_foo($changed_array));
echo "<br>";
//All you have to do here is create an array with the keys you want to erase in it.
//If you want to erase all keys then don't pass any array to the method.
$element_to_erase = array(3=>null);
echo "Erasing the fourth element: ";
$elements_left = StaticSample::s_foo($element_to_erase, 1);
print_r($elements_left);
echo "<br>";
echo "Enjoy!";
?>

developit at mail dot ru 27-Jan-2006 03:57


You use 'self' to access this class, 'parent' - to access parent class, and what will you do to access a parent of the parent?
Or to access the very root class of deep class hierarchy? The answer is to use classnames. That'll work just like 'parent'.
Here's an example to explain what I mean. Following code
<?php
class A
{
protected $x = 'A';
public function f()
{
return '['.$this->x.']';
}
}
class B extends A
{
protected $x = 'B';

public function f()


{
return '{'.$this->x.'}';
}
}
class C extends B
{
protected $x = 'C';
public function f()
{
return '('.$this->x.')'.parent::f().B::f().A::f();
}
}
$a = new A();
$b = new B();
$c = new C();
print $a->f().'<br/>';
print $b->f().'<br/>';
print $c->f().'<br/>';
?>
will output
[A] -- {B} -- (C){C}{C}[C]

Kristof Coomans 25-Nov-2005 03:08


In response to ian at [first name]henderson dot org:
(related bogus bug report: http://bugs.php.net/bug.php?id=26930)
The functionality you've expected maybe will be possible in PHP6, probably by using the static keyword in conjunction with the
scope resolution parameter. You can read more about this in the minutes of the PHP developers meeting at 11 and 12 november in
Paris: http://www.php.net/~derick/meeting-notes.html point 5.4: Late static binding using "this" without "$" (or perhaps with a
different name)

HuugjeWeg 29-Apr-2005 05:58


In response to ian at [first name]henderson dot org:
You are not allowed to redefine static methods, see
http://www.php.net/manual/en/language.oop5.static.php
And in response to thenewparadigm at hotmail dot com: the behaviour you describe seems appropriate for *classes* with static
variables, see "Using static variables" on http://nl2.php.net/static

thenewparadigm at hotmail dot com 05-Mar-2005 09:43


There is also a quirk with using the scope resolution operator on static class variables. Below is an example using a highly
modified version of Ian's code:
<?php
class ExampleSuperclass
{

static $className;
static function showClassName() {
echo self::$className . "\n";
}
}
class ExampleSubclassOne extends ExampleSuperclass
{
static function setClassName()
{
self::$className = "subclassOne";
}
}
class ExampleSubclassTwo extends ExampleSuperClass
{
static function setClassName()
{
self::$className = "subclassTwo";
}
}
// setting variables for each class
ExampleSubclassOne::setClassName();
ExampleSubclassTwo::setClassName();
ExampleSubclassOne::showClassName(); // output is "subclassTwo"!
// more output:
echo ExampleSubclassOne::$className . "\n"; // output is "subclassTwo"!
echo ExampleSubclassTwo::$className . "\n"; // output is "subclassTwo"
echo ExampleSuperclass::$className . "\n"; // output is "subclassTwo"!
?>
appearantly, any static variables defined in a superclass are directly referenced in subclasses,
and all changes are visible throughout the class heirarchy. care must be taken when using static
class variables.

ian at [first name]henderson dot org 31-Jan-2005 10:43


Please note that methods called by the scope resolution operator which are defined by a superclass of the first operand are
called in the scope of the SUPERCLASS. For example,
<?php
class ExampleSuperclass
{
static function classType()
{
return "superclass";
}
static function doSomething()
{
echo "doing something with " . self::classType();
}

}
class ExampleClass extends ExampleSuperclass
{
static function classType()
{
return "subclass";
}
}
ExampleClass::doSomething();
// output is "doing something with superclass"!
?>
This can be surprising (it surprised me!) when coming from other object-oriented languages, which would output "doing something
with subclass" in this case.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Static Keyword
Declaring class properties or methods as static makes them accessible without needing an instantiation of the
class. A property 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 property 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.

Like any other PHP static variable, static properties may only be initialized using a literal or constant;
expressions are not allowed. So while you may initialize a static property to an integer or array (for instance),
you may not initialize it to another variable, to a function return value, or to an object.
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 property example
<?php
classFoo
{
publicstatic$my_static='foo';
publicfunctionstaticValue(){
returnself::$my_static;
}
}
classBarextendsFoo
{
publicfunctionfooStatic(){
returnparent::$my_static;
}
}

printFoo::$my_static."\n";
$foo=newFoo();
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";//AsofPHP5.3.0
printBar::$my_static."\n";
$bar=newBar();
print$bar->fooStatic()."\n";
?>

Example #2 Static method example

<?php
classFoo{
publicstaticfunctionaStaticMethod(){
//...
}
}
Foo::aStaticMethod();
$classname='Foo';
$classname::aStaticMethod();//AsofPHP5.3.0
?>

User Contributed Notes

Static Keyword

kaspars [at] gign.lv 03-Oct-2011 02:02


in order to use __destruct() in a class without instance (see the sample code in the comment below), you must assign return
value of new B(); to a static private variable class-wide or else __destruct() will be called at the end of init() function
because the return value of new B() will be treated as a local variable
e.g.:
<?php
class B {
static private $fakeClass = null;
static public init($autoSave) {
self::$fakeClass = new B();
}
/* rest of the code */
}

programmer-comfreek at hotmail dot com 08-Aug-2011 07:40


If you haven't an instance for your class (e.g. all functions are static), but you also want a __destruct() functionality,
consider the following example:
We have a class which loads and saves data so we also want to have an autosave mechanism which is called at the end of the PHP
script.
So usually you declare a __destruct function but our class is designed to provide static functions / variables instead:
<?php
class A
{
static private $autoSave;
static public function init($autoSave)
{
/* emulating __construct() */
self::$autoSave = $autoSave;
}
static public function save() { /*...*/ } /* load(), get(), etc. */

}
?>
In order to define a __destruct function (which is definitely called) we create a new instance in the init() function and
define a destruct() function (which is called from the 'real' one):
<?php
class B
{
static private $autoSave;
static public function init($autoSave)
{
/* emulating __construct() */
self::$autoSave = $autoSave;
new B();
}
static public function destruct()
{
if (self::$autoSave)
self::save();
}
public function __destruct()
{
B::destruct();
}
}
?>

payal001 at gmail dot com 09-Jul-2011 03:17


Here statically accessed property prefer property of the class for which it is called. Where as self keyword enforces use of
current class only. Refer the below example:
<?php
class a{
static protected $test="class a";
public function static_test(){
echo static::$test; // Results class b
echo self::$test; // Results class a
}
}
class b extends a{
static protected $test="class b";
}
$obj = new b();
$obj->static_test();
?>

gratcypalma at gmail dot om 18-Apr-2011 11:50


<?php
class foo {
private static $getInitial;
public static function getInitial() {
if (self::$getInitial == null)
self::$getInitial = new foo();
return self::$getInitial;
}
}
foo::getInitial();
/*
this is the example to use new class with static method..
i hope it help
*/
?>

jeroen at simonetti dot nl 04-Apr-2011 02:27


accessing a non-existing static property will result in an E_ERROR message.
You can check wether a property exists with the 'defined' function.
Example:
<?php
class a {
static $test;
function set($name) {
if (defined(self::$$name)) echo "$name is defined";
else echo "$name is not defined";
}
}
a::set('test');
a::set('test2');
?>
will output:
test is defined
test2 is not defined

tolean_dj at yahoo dot com 11-Dec-2010 05:09


Starting with php 5.3 you can get use of new features of static keyword. Here's an example of abstract singleton class:
<?php
abstract class Singleton {

protected static $_instance = NULL;


/**
* Prevent direct object creation
*/
final private function __construct() { }
/**
* Prevent object cloning
*/
final private function __clone() { }
/**
* Returns new or existing Singleton instance
* @return Singleton
*/
final public static function getInstance(){
if(null !== static::$_instance){
return static::$_instance;
}
static::$_instance = new static();
return static::$_instance;
}

}
?>

Mirco 23-Aug-2010 10:16


The simplest static constructor.
Because php does not have a static constructor and you may want to initialize static class vars, there is one easy way, just
call your own function directly after the class definition.
for example.
<?php
function Demonstration()
{
return 'This is the result of demonstration()';
}
class MyStaticClass
{
//public static $MyStaticVar = Demonstration(); //!!! FAILS: syntax error
public static $MyStaticVar = null;
public static function MyStaticInit()
{
//this is the static constructor
//because in a function, everything is allowed, including initializing using other functions

self::$MyStaticVar = Demonstration();
}
} MyStaticClass::MyStaticInit(); //Call the static constructor
echo MyStaticClass::$MyStaticVar;
//This is the result of demonstration()
?>

Anonymous 28-Jun-2010 06:49


I can't find anything in the PHP manual about this, but the new-ish E_STRICT error reporting will complain if an inherited
class overrides a static method with a different call signature (usually a parameter list). Ironically, it seems to only be a
problem of 'coding style' because the code works correctly and has done for quite a few versions.
The exact error is "Strict Standards: Declaration of [child-class]::[method]() should be compatible with that of [parentclass]::[method]()".
So if you must code with E_STRICT enabled, you need to rename the method name.
Google shows that this is biting *a lot* of people. (Bugs have been filed, but there has been no response yet.)

myselfasunder at gmail dot com 13-Apr-2010 09:42


If you inadvertently call a non-static method in one class from another class, using $this in the former will actually refer
to the wrong class.
<?php
class CalledClass
{
function go()
{
print(get_class($this) . "\n");
return true;
}
}
class CallerClass
{
function go()
{
CalledClass::Go();

return true;
}
}
$obj = new CallerClass();
$obj->go();
// Output is "CallerClass" instead of "CalledClass" like it should be.
?>
Dustin Oprea

webmaster at removethis dot weird-webdesign dot de 25-Feb-2010 01:38


On PHP 5.2.x or previous you might run into problems initializing static variables in subclasses due to the lack of late static
binding:
<?php
class A {
protected static $a;


public static function init($value) { self::$a = $value; }
public static function getA() { return self::$a; }
}
class B extends A {
protected static $a; // redefine $a for own use

// inherit the init() method


public static function getA() { return self::$a; }
}
B::init('lala');
echo 'A::$a = '.A::getA().'; B::$a = '.B::getA();
?>
This will output:
A::$a = lala; B::$a =
If the init() method looks the same for (almost) all subclasses there should be no need to implement init() in every subclass
and by that producing redundant code.
Solution 1:
Turn everything into non-static. BUT: This would produce redundant data on every object of the class.
Solution 2:
Turn static $a on class A into an array, use classnames of subclasses as indeces. By doing so you also don't have to redefine
$a for the subclasses and the superclass' $a can be private.
Short example on a DataRecord class without error checking:
<?php
abstract class DataRecord {
private static $db; // MySQLi-Connection, same for all subclasses
private static $table = array(); // Array of tables for subclasses

public static function init($classname, $table, $db = false) {


if (!($db === false)) self::$db = $db;
self::$table[$classname] = $table;
}

public static function getDB() { return self::$db; }


public static function getTable($classname) { return self::$table[$classname]; }
}
class UserDataRecord extends DataRecord {
public static function fetchFromDB() {
$result = parent::getDB()->query('select * from '.parent::getTable('UserDataRecord').';');

// and so on ...
return $result; // An array of UserDataRecord objects
}
}
$db = new MySQLi(...);
UserDataRecord::init('UserDataRecord', 'users', $db);
$users = UserDataRecord::fetchFromDB();
?>
I hope this helps some people who need to operate on PHP 5.2.x servers for some reason. Late static binding, of course, makes

this workaround obsolete.

valentin at balt dot name 26-Jan-2010 07:46


How to implement a one storage place based on static properties.
<?php
class a {

public function get () {


echo $this->connect();
}
}
class b extends a {
private static $a;
public function connect() {
return self::$a = 'b';
}
}
class c extends a {
private static $a;
public function connect() {
return self::$a = 'c';
}
}
$b = new b ();
$c = new c ();
$b->get();
$c->get();
?>

Jay Cain 18-Dec-2009 02:45


Regarding the initialization of complex static variables in a class, you can emulate a static constructor by creating a static
function named something like init() and calling it immediately after the class definition.
<?php
class Example {
private static $a = "Hello";
private static $b;
public static function init() {
self::$b = self::$a . " World!";
}
}
Example::init();
?>

maximark at libero dot it 08-Dec-2009 09:34


<?php
// USING the same method in an instance and in a static context
// If you want to have the same definition of a method that you
// want to use both as static and as instance method, a classname control of $this
// variable is needed. This tip can be used wether the caller context is not the same class type

class A
{
private $myProp = 'A';

public function myMethodA()


{
if(isset($this) && get_class($this) == __CLASS__)
return $this->myProp;
return 'C';
}
}
class B
{
public $myProp = 'B';

public function myMethodB()


{
$a = new A;
return $a->myMethodA().' ++++ '.A::myMethodA();
}
}
$b = new B();
echo $b->myMethodB(); // output: A ++++ C
// NOTE:
// if you don't verify "&& get_class($this) == __CLASS__"
// it will output A ++++ B, it seems that if a method is not marked as "static"
// its scope would be the scope in which the function was called
?>

Stratadrake 13-Nov-2009 12:24


When a method is declared as static, not only is the magic variable $this unavailable (returns NULL), but it is impossible to
tell if the function was actually called from a static context. A backtrace implies that for a static method, calling $object>method() is internally translated to className::method() at run time.
<?php
class Foo
{
static function bar()
{
var_dump(reset(debug_backtrace()));
}
}
$foo = new Foo();
$foo->baz();
Foo::baz();
// Output in either case resembles this:
// array(3)
// {
// 'file' => .....
// 'line => .....
// 'function' => string(3) 'baz'
// 'class' => string(3) 'Foo'
// 'type' => string(2) '::'
// }
?>

sep16 at psu dot edu 10-Jul-2009 12:32


I find having class variables useful for inherited classes, especially when inheriting abstract classes, yet self:: doesn't
refer to the class calling the method, rather the actual class in which it was defined. Although it is less memory efficient,
this can be circumvented with instance properties, but sometimes even this won't work, i.e., when using resources like classwide database or prepared statement handles.
The pre-5.3.0 way that I used to get around this limitation was to write a class that stores a central value and sets instance
properties as references to this value. In this way objects can have access to the same value while still being able to use
inherited methods that reference this property.
Usage example:
<?php // (SharedPropertyClass is defined below)
class Foo extends SharedPropertyClass {
public $foo = "bar";
public function showFoo() {
echo $this->foo, "\n";
}
}
class FooToo extends Foo {
public function __construct() {
$this->makeShared('foo');
}
}
$ojjo = new FooToo;
$ojjo->showFoo(); // "bar"
$xjjx = new FooToo;
$xjjx->showFoo(); // "bar"
$ojjo->foo = "new";
$ojjo->showFoo(); // "new"
$xjjx->showFoo(); // "new"
?>
Notice how the showFoo() method, while defined in the parent class, correctly uses the child class's "foo" property (unlike
self:: would), and how the "foo" property is shared by all instances of FooToo objects (like a static property). This is
essentially how the new static:: keyword will work, and how most people probably expected the self:: keyword to work.
<?php
// --------------------------------------------------------------abstract class SharedPropertyClass {
// --------------------------------------------------------------/*
Shared properties should be declared as such in the
constructor function of the inheriting class.
The first instance will have the shared property set to
the value in the class definition, if any, otherwise null.
All subsequent instances will also have their shared
property set as a reference to that variable.
*/
private static $shared = array();
public function makeShared($property) {
$class = get_class($this);
if (!property_exists($this,$property))
trigger_error("Access to undeclared property "

. "'$property' in class $class.",E_USER_ERROR);


if (!array_key_exists($class,self::$shared))
self::$shared[$class] = array();
if (!array_key_exists($property,self::$shared[$class]))
self::$shared[$class][$property]
= isset($this->$property)
? $this->$property
: null;
$this->$property =& self::$shared[$class][$property];
}
public function isShared($property) {
$class = get_class($this);
if (!property_exists($this,$property))
trigger_error("Access to undeclared property "
. "'$property' in class $class.",E_USER_ERROR);
return array_key_exists($class,self::$shared)
&& array_key_exists($property, self::$shared[$class]);
}
}
?>

davidn at xnet dot co dot nz 17-Mar-2009 04:56


Static variables are shared between sub classes
<?php
class MyParent {

protected static $variable;


}
class Child1 extends MyParent {

function set() {

self::$variable = 2;
}
}
class Child2 extends MyParent {

function show() {

echo(self::$variable);
}
}
$c1 = new Child1();
$c1->set();
$c2 = new Child2();
$c2->show(); // prints 2
?>

yesmarklapointe at hotmail dot com 21-Jan-2009 11:19


<?php
// experiments with static
// tested on PHP 5.2.6 on 1-21-09

class User{
const GIVEN = 1; // class constants can't be labeled static nor assigned visibility
public $a=2;
public static $b=3;

public function me(){


echo "print me";
}
public static function you() {
echo "print you";
}
}
class myUser extends User {
}
// Are properties and methods instantiated to an object of a class, & are they accessible?
//$object1= new User(); // uncomment this line with each of the following lines individually
//echo $object1->GIVEN . "</br>"; // yields nothing
//echo $object1->GIVE . "</br>"; // deliberately misnamed, still yields nothing
//echo $object1->User::GIVEN . "</br>"; // yields nothing
//echo $object1->a . "</br>"; // yields 2
//echo $object1->b . "</br>"; // yields nothing
//echo $object1->me() . "</br>"; // yields print me
//echo $object1->you() . "</br>"; // yields print you
// Are properties and methods instantiated to an object of a child class, & are accessible?
//$object2= new myUser(); // uncomment this line with each of the following lines individually
//echo $object2->GIVEN . "</br>"; // yields nothing
//echo $object2->a . "</br>"; // yields 2
//echo $object2->b . "</br>"; // yields nothing
//echo $object2->me() . "</br>"; // yields print me
//echo $object2->you() . "</br>"; // yields print you
// Are the properties and methods accessible directly in the class?
//echo User::GIVEN . "</br>"; // yields 1
//echo User::$a . "</br>"; // yields fatal error since it is not static
//echo User::$b . "</br>"; // yields 3
//echo User::me() . "</br>"; // yields print me
//echo User::you() . "</br>"; // yields print you
// Are the properties and methods copied to the child class and are they accessible?
//echo myUser::GIVEN . "</br>"; // yields 1
//echo myUser::$a . "</br>"; // yields fatal error since it is not static
//echo myUser::$b . "</br>"; // yields 3
//echo myUser::me() . "</br>"; // yields print me
//echo myUser::you() . "</br>"; // yields print you
?>

zerocool at gameinsde dot ru 20-Oct-2008 01:06


Hi, here's my simple Singleton example, i think it can be useful for someone. You can use this pattern to connect to the
database for example.
<?php
class MySingleton
{

private static $instance = null;


private function __construct()
{
$this-> name = 'Freddy';
}
public static function getInstance()
{
if(self::$instance == null)
{
print "Object created!<br>";
self::$instance = new self;
}
return self::$instance;
}
public function sayHello()
{
print "Hello my name is {$this-> name}!<br>";
}
public function setName($name)
{
$this-> name = $name;
}
}
//
$objA = MySingleton::getInstance(); // Object created!
$objA-> sayHello(); // Hello my name is Freddy!
$objA-> setName("Alex");
$objA-> sayHello(); // Hello my name is Alex!
$objB = MySingleton::getInstance();
$objB-> sayHello(); // Hello my name is Alex!
$objB-> setName("Bob");
$objA-> sayHello(); // Hello my name is Bob!
?>

wbcarts at juno dot com 18-Oct-2008 10:24


[NB: This is a copy of the note by juno dot com on 11-Sep-2008 04:53, but with syntax highlighting.]

A CLASS WITH MEAT ON IT'S BONES...


I have yet to see an example that I can really get my chops into. So I am offering an example that I hope will satisfy most of
us.
<?php
class RubberBall
{
/*
* ALLOW these properties to be inherited TO extending classes - that's
* why they're not private.
*
* DO NOT ALLOW outside code to access with 'RubberBall::$property_name' * that's why they're not public.
*
* Outside code should use:
* - RubberBall::getCount()
* - RubberBall::setStart()
* These are the only routines outside code can use - very limited indeed.
*
* Inside code has unlimited access by using self::$property_name.
*
* All RubberBall instances will share a "single copy" of these properties - that's
* why they're static.
*/
protected static $count = 0;
protected static $start = 1;
protected static $colors = array('red','yellow','blue','orange', 'green', 'white');
protected static $sizes = array(4, 6, 8, 10, 12, 16);
public $name;
public $color;
public $size;
public function __construct(){
$this->name = 'RB_' . self::$start++;
$this->color = (int) rand(0, 5);
$this->size = self::$sizes[(int) rand(0, 5)];
self::$count++;
}
public static function getCount(){
return self::$count;
}
public static function setStart($val){
self::$start = $val;
}
/*
* Define the sorting rules for RubberBalls - which is to sort by self::$colors.
* PHP's usort() method will call this function many many times.
*/
public static function compare($a, $b){
if($a->color < $b->color) return -1;
else if($a->color == $b->color) return 0;
else return 1;
}

public function __toString(){


return "RubberBall[
name=$this->name,
color=" . self::$colors[$this->color] . ",
size=" . $this->size . "\"]";
}
}
# RubberBall counts the number of objects created, but allows us to
# set the starting count like so:
RubberBall::setStart(100);
# create a PHP Array and initialize it with (12) RubberBall objects
$balls = array();
for($i = 0; $i < 12; $i++) $balls[] = new RubberBall();
# sort the RubberBall objects. PHP's usort() calls RubberBall::compare() to do this.
usort($balls, array("RubberBall", "compare"));
# print the sorted results - uses the static RubberBall::getCount().
echo 'RubberBall count: ' . RubberBall::getCount() . '<br><br>';
foreach($balls as $ball) echo $ball . '<br>';
?>
I'm running out of room so I have not displayed the output, but it is tested and it works great.

vvikramraj at yahoo dot com 23-Sep-2008 03:24


when attempting to implement a singleton class, one might also want to either
a) disable __clone by making it private
b) bash the user who attempts to clone by defining __clone to throw an exception

wbcarts at juno dot com 10-Sep-2008 08:53


A CLASS WITH MEAT ON IT'S BONES...
I have yet to see an example that I can really get my chops into. So I am offering an example that I hope will satisfy most of
us.
class RubberBall
{
/*
* ALLOW these properties to be inherited TO extending classes - that's
* why they're not private.
*
* DO NOT ALLOW outside code to access with 'RubberBall::$property_name' * that's why they're not public.
*
* Outside code should use:
* - RubberBall::getCount()
* - RubberBall::setStart()
* These are the only routines outside code can use - very limited indeed.
*
* Inside code has unlimited access by using self::$property_name.
*
* All RubberBall instances will share a "single copy" of these properties - that's
* why they're static.

*/
protected static $count = 0;
protected static $start = 1;
protected static $colors = array('red','yellow','blue','orange', 'green', 'white');
protected static $sizes = array(4, 6, 8, 10, 12, 16);
public $name;
public $color;
public $size;
public function __construct(){
$this->name = 'RB_' . self::$start++;
$this->color = (int) rand(0, 5);
$this->size = self::$sizes[(int) rand(0, 5)];
self::$count++;
}
public static function getCount(){
return self::$count;
}
public static function setStart($val){
self::$start = $val;
}
/*
* Define the sorting rules for RubberBalls - which is to sort by self::$colors.
* PHP's usort() method will call this function many many times.
*/
public static function compare($a, $b){
if($a->color < $b->color) return -1;
else if($a->color == $b->color) return 0;
else return 1;
}
public function __toString(){
return "RubberBall[
name=$this->name,
color=" . self::$colors[$this->color] . ",
size=" . $this->size . "\"]";
}
}
# RubberBall counts the number of objects created, but allows us to
# set the starting count like so:
RubberBall::setStart(100);
# create a PHP Array and initialize it with (12) RubberBall objects
$balls = array();
for($i = 0; $i < 12; $i++) $balls[] = new RubberBall();
# sort the RubberBall objects. PHP's usort() calls RubberBall::compare() to do this.
usort($balls, array("RubberBall", "compare"));
# print the sorted results - uses the static RubberBall::getCount().
echo 'RubberBall count: ' . RubberBall::getCount() . '<br><br>';
foreach($balls as $ball) echo $ball . '<br>';
I'm running out of room so I have not displayed the output, but it is tested and it works great.

Mathijs Vos 23-Aug-2008 03:53


<?php
class foo
{
public static $myStaticClass;

public function __construct()


{
self::myStaticClass = new bar();
}
}
class bar
{
public function __construct(){}
}
?>
Please note, this won't work.
Use self::$myStaticClass = new bar(); instead of self::myStaticClass = new bar(); (note the $ sign).
Took me an hour to figure this out.

nacion_01 at hotmail dot com 22-Aug-2008 09:38


Thanks to all of you, this is my little contribution, i hope it give you ideas:
The next script uses a class Logs to store and show the logs. You can show the last logs of your scripts. You can:
- push ("a new log")
- show () // the last logs until the las call to show()
- showAll() // to show all the logs and
- message("a forced message") // which sends a message to the log output with out storing the message (you may imagine other
solutions)
<?php
class Logs{
// this makes this thing to be hidden from outside calls [private]
private static $logs=array("start");
private static $index=0;
// this is available for outside calls [public]
public static function getLogsCount(){
// the constant "self" refers to the class, instead $this wich
// refers to an instance of a class (this class is not instanced,
// its running itself, so lets use "self" and "::" to access the
// "static" functions and properties.
$count=count(self::$logs);
return $count;
}
public static function show(){
//echo ("# Logs::show ".self::getLogsCount());
$count=self::getLogsCount();
// start the show since the last log shown ($index)
for ($i=self::$index; $i<$count;$i++){
$log=self::$logs[$i];
self::message($log);
}
// update the las log shown index
self::$index=$i;

}
public static function showAll(){
//echo ("# Logs::show ".self::getLogsCount());
// show the logs from cero to last
// im starting with php so I use for (...) because its my
// way in AS3.0 but you better keep checking that
$count=self::getLogsCount();
for ($i=0; $i<$count;$i++){
$log=self::$logs[$i];
self::message($log);
}
}
// Yup! a new log!
public static function push($msg){
//self::message("# Logs::push ");
array_push(self::$logs, $msg);
}
// Send a message to the html output.
// Now, a little words about this one, you may want to use an
// special button on your html or somewhere else to show or hide the
// logs, because you are in development and want to keep this thing
// little hidden of your clients. Probably may generate a java script
// variable so instead of [echo "<p>...</p>";] is ok to
// use [echo "<script>logs+=$msg</script>"]
// I dont know, figure it out.
public function message($msg){
echo "<p>- Logs &gt; $msg </p>";
}
}
// Ready to use.
// to call a function in an static class, refer to the function as
// TheClass::theFunction
// remember, php uses :: (sorry, I still learning why because I come from the AS3 world)
Logs::push("log1");
Logs::show();
Logs::push("log2");
Logs::show();
Logs::push("log3");
Logs::showAll();
?>

michaelnospamdotnospamdaly at kayakwiki 13-Jul-2008 06:59


Further to the comment by "erikzoltan NOSPAM at msn NOSPAM dot com" on 05-Apr-2005 03:40,
It isn't just constructors that can't be used for static variable initialization, it's functions in general:
class XYZ
{
static $foo = chr(1); // will fail
}
You have to do external initialization:

XYZ::$foo = chr(1);
class XYZ
{
static $foo;
}

Siarhei 04-Mar-2008 05:25


There is a problem to make static property shared only for objects of self class not defining it in every child class.
Example:
class a
{
public static $s;

public function get()


{
return self::$s;
}
}
class b extends a { }
class c extends b { }
a::$s = 'a';
$c = new c();
echo $c->get(); // a
There is solution i found:
class a
{
public final function v($vs = null)
{
static $s = null;

if(!is_null($vs))
$s = $vs;
return $s;
}
}
class b extends a { }
class c extends b { }
$a = new a();
$a->v('a');
$aa = new a();
$aa->v('last a');
$c = new c();
$c->v('c');

echo $a->v().' - '.$c->v(); // last a - c

inkredibl 28-Jan-2008 12:27


Note that you should read "Variables/Variable scope" if you are looking for static keyword use for declaring static variables
inside functions (or methods). I myself had this gap in my PHP knowledge until recently and had to google to find this out. I
think this page should have a "See also" link to static function variables.
http://www.php.net/manual/en/language.variables.scope.php

ssj dot narutovash at gmail dot com 01-Jan-2008 08:48


It's come to my attention that you cannot use a static member in an HEREDOC string. The following code
class A
{
public static $BLAH = "user";
function __construct()
{
echo <<<EOD
<h1>Hello {self::$BLAH}</h1>
EOD;
}
}
$blah = new A();
produces this in the source code:
<h1>Hello {self::}</h1>
Solution:
before using a static member, store it in a local variable, like so:
class B
{
public static $BLAH = "user";
function __construct()
{
$blah = self::$BLAH;
echo <<<EOD
<h1>Hello {$blah}</h1>
EOD;
}
}
and the output's source code will be:
<h1>Hello user</h1>

gabe at mudbugmedia dot com 16-Oct-2007 06:55


Currently, inheritance with static methods can be a difficult matter, mainly because the 'self' keyword refers the exact class
in which the reference is present, much like __CLASS__. Thus, in a case like the following:
<?php

class A {
static function foo () {
echo "A::foo()";
}

static function callFoo () {


self::foo();
}
}
class B extends A {
static function foo () {
echo "B::foo()";
}
}
B::callFoo();
?>
Will output 'A::foo()' instead of 'B::foo()'. As of 5.2 and below, there is no clean way to get around this. get_class(),
self, __CLASS__, and even the stack (examined by debug_backtrace()) will all report the appropriate class as being 'A', which
is resolved before being called. There is no sane way, short of determining the filename and line of code from
debug_backtrace, re-opening the file, and parsing that out yourself (this kludge is left as an exercise to only the most
demented developer). This setup makes it extremely difficult to develop an ORM like ActiveRecord in PHP.
You'll see some rather ugly solutions below, including passing the class name to callFoo(). Another possible route is to skip
static calls all together and make a function that returns an instance of the object, thus allowing you to gain access to the
'$this' variable (which *will* know the class name that was originally being called):
<?php
class A {
static function foo () {
echo "A::foo()";
}

static function callFoo () {


$this->foo();
}
}
class B extends A {
static function foo () {
echo "B::foo()";
}
}
function getB () { return new B(); }
getB()->callFoo();
?>
Luckily, a work around has been committed to PHP's HEAD, and should be available in the 5.3 series. The concept is called
"late static binding" (LSB), and can be read about at http://www.colder.ch/news/08-24-2007/28/late-static-bindings-expl.html .
Basically, you'd have the exact same setup in as in the first example, but instead of calling "self::foo()", you instead would
call "static::foo()".

Clment Genzmer 09-Aug-2007 01:54


The best solution I found for the non-inherited static problem : pass the name of the class.
<?php
class A {

public static $my_vars = "I'm in A";

static function find($class) {


$vars = get_class_vars($class) ;
echo $vars['my_vars'] ;
}
}
class B extends A {
public static $my_vars = "I'm in B";
}
B::find("B");
// Result : "I'm in B"
?>

james at earthemergency dot org 12-Oct-2006 04:36


One way to get around the fact that static variables are shared throughout the inheritance tree to map a instance variable to a
global variable named after the class.
<?php
$GLOBALS['static'] = array();
class root {
public $self;
public static $all_instances;

function __construct() {
$this->self = &$GLOBALS['static'][get_class($this)];
$this->self['instances'] += 1;
self::$all_instances += 1;
}
}
class child_a extends root {
}
class child_b extends root {
}
$a1 = new child_a();
$a2 = new child_a();
$a3 = new child_a();
$b1 = new child_b();
$b2 = new child_b();
echo "child_a instances: " . $a3->self['instances'] . " | all_instances: " . child_a::$all_instances . "\n";
echo "child_b instances: " . $b2->self['instances'] . " | all_instances: " . child_b::$all_instances . "\n";
echo "\$GLOBALS['static'] = ";
var_dump($GLOBALS['static']);

?>
// Output:
child_a instances: 3 | all_instances: 5
child_b instances: 2 | all_instances: 5
$GLOBALS['static'] = array(2) {
["child_a"]=>
&array(1) {
["instances"]=>
int(3)
}
["child_b"]=>
&array(1) {
["instances"]=>
int(2)
}
}

jan(dot)-re-mov.ethis-mazanek/AT-abeo.cz 19-Sep-2006 11:42


This reacts to comment from
michael at digitalgnosis dot removethis dot com from 16-Dec-2004 08:09
> Note that Base::Foo() may no longer be declared 'static' since static methods cannot be overridden (this means it will
trigger errors if error level includes E_STRICT.)
In my test on Windows PHP Version 5.1.4 it seems that it *is possible* to override static method.
This code works at my machine without producing E_STRICT error:
<?php
class Base
{
static function Foo ( $class = __CLASS__ )
{
call_user_func(array($class,'Bar'));
}
}
class Derived extends Base
{
static function Foo ( $class = __CLASS__ )
{
parent::Foo($class);
}
static function Bar ()
{
echo "Derived::Bar()";
}
}
Derived::Foo(); // This time it works.
?>

Jakob Schwendner 04-Nov-2005 01:17


Here is my solution to the static search method problem for data objects. I found the debug_trace version posted earlier quite
clever, but a little too risky.

<?php
class Foo {
static function find($class) {
$obj = new $class();
return $obj;
}
}
class Bar extends Foo {
static function find() {
return parent::find(__CLASS__);
}
function print_hello() {
echo("hello");
}
}
Bar::find()->print_hello();
?>

aidan at php dot net 04-May-2005 07:14


To check if a function was called statically or not, you'll need to do:
<?php
function foo () {
$isStatic = !(isset($this) && get_class($this) == __CLASS__);
}
?>
More at (http://blog.phpdoc.info/archives/4-Schizophrenic-Methods.html).
(I'll add this to the manual soon).

06-Apr-2005 03:14
You misunderstand the meaning of inheritance : there is no duplication of members when you inherit from a base class. Members
are shared through inheritance, and can be accessed by derived classes according to visibility (public, protected, private).
The difference between static and non static members is only that a non static member is tied to an instance of a class
although a static member is tied to the class, and not to a particular instance.
That is, a static member is shared by all instances of a class although a non static member exists for each instance of
class.
Thus, in your example, the static property has the correct value, according to principles of object oriented conception.
class Base
{
public $a;
public static $b;
}
class Derived extends Base
{
public function __construct()
{
$this->a = 0;

parent::$b = 0;
}
public function f()
{
$this->a++;
parent::$b++;
}
}
$i1 = new Derived;
$i2 = new Derived;
$i1->f();
echo $i1->a, ' ', Derived::$b, "\n";
$i2->f();
echo $i2->a, ' ', Derived::$b, "\n";
outputs
1 1
1 2

erikzoltan NOSPAM at msn NOSPAM dot com 05-Apr-2005 05:50


I was doing this in a more complex example (than previous note) and found that I had to place the initialization statement
AFTER the class in a file where I was using the __autoload function.

erikzoltan NOSPAM at msn NOSPAM dot com 05-Apr-2005 03:40


I had trouble getting a static member to be an instance of a class. Here's a code example that DOESN'T work.
<?php
// This doesn't work.
class XYZ
{
// The following line will throw a syntax error.
public static $ABC = new ABC();
}
class ABC
{
}
$myXyz = new XYZ();
var_dump($myXyz);
var_dump(XYZ::$ABC);
?>
I get the following entry in my error log.
[05-Apr-2005 18:27:41] PHP Parse error: syntax error, unexpected T_NEW in staticTest.php on line 7
Since PHP doesn't appear to allow static constructor methods, I was only able to resolve this problem by moving the
initialization outside of the class. To make my code more self-documenting I put it above the class. The revised example
below appears to work.

<?php
// This will work.
// Moved the static variable's initialization logic outside the class.
XYZ::$ABC = new ABC();
class XYZ
{
// I'm just declaring the static variable here, but I'm not initializing it.
public static $ABC;
}
class ABC
{
}
$myXyz = new XYZ();
var_dump($myXyz);
var_dump(XYZ::$ABC);
?>

michalf at ncac dot torun dot pl 31-Mar-2005 02:42


Inheritance with the static elements is a nightmare in php. Consider the following code:
<?php
class BaseClass{
public static $property;
}
class DerivedClassOne extends BaseClass{
}
class DerivedClassTwo extends BaseClass{
}
DerivedClassOne::$property = "foo";
DerivedClassTwo::$property = "bar";
echo DerivedClassOne::$property; //one would naively expect "foo"...
?>
What would you expect as an output? "foo"? wrong. It is "bar"!!! Static variables are not inherited, they point to the
BaseClass::$property.
At this point I think it is a big pity inheritance does not work in case of static variables/methods. Keep this in mind and
save your time when debugging.
best regards - michal

c_daught_d at earthlink dot net 14-Jan-2005 01:57


A twist on christian at koch dot net's Singleton example is setting/getting non-static member variables using self::$instance>varname within static method calls.
Within the modified Singleton class below, the member variable $value is set within the getInstance static method instead of

the constructor.
Whether this is "pure" OPP, I don't know. But it does work, is worth mentioning, and could be usefull.
class Singleton
{
private static $instance=null;
private $value=null;
private function __construct() {
}
public static function getInstance() {
if ( self::$instance == null ) {
echo "<br>new<br>";
self::$instance = new Singleton("values");
self::$instance->value = "values";
}
else {
echo "<br>old<br>";
}
return self::$instance;
}
}

ference at super_delete_brose dot co dot uk 14-Jan-2005 07:11


Both static and const fields can be accessed with the :: operator. However, while a constant can't be changed, this is not true
for static variables.
If you want to access an array using the :: operator you have to declare the array static, since you can't have a constant
array. Beware:
<?php
class foo
{
static $stuff = array('key1' => 1, 'key2' => 2);
}
class bar
{
public function __construct()
{
var_dump(foo::$stuff);
}
}
class bad
{
public function __construct()
{
foo::$stuff = FALSE;
}
}
new bar(); // prints array(2) { ["key1"]=> int(1) ["key2"]=> int(2) }

new bad();
new bar(); // prints bool(false)
?>
A safe implementation requires a little more effort:
<?php
class foo
{
private static $stuff = array('key1' => 1, 'key2' => 2);
public final static function getstuff()
{
return self::$stuff;
}
}
class bar
{
public function __construct()
{
var_dump(foo::getstuff());
}
}
class bad
{
public function __construct()
{
foo::$stuff = FALSE;
}
}
new bar(); // prints array(2) { ["key1"]=> int(1) ["key2"]=> int(2) }
new bad(); // results in a fatal error
?>

michael at digitalgnosis dot removethis dot com 15-Dec-2004 11:41


Here's another way to do the same thing (see my post below) without having to muck up your Foo() function's parameters in the
Base and all Derived classes.
However, you cannot use static, and still must define Foo() in derived classes. This way also performs slower and may not
always work--but it DOES make for prettier code.
<?php
class Base
{
function Foo ()
{
$call = debug_backtrace();
call_user_func(array($call[1]['class'],'Bar'));
}
}
class Derived extends Base
{
function Foo () { parent::Foo(); }

function Bar ()
{
echo "Derived::Bar()";
}
}
Derived::Foo();
?>

michael at digitalgnosis dot removethis dot com 15-Dec-2004 11:09


If you are trying to write classes that do this:
<?php
class Base
{
static function Foo ()
{
self::Bar();
}
}
class Derived extends Base
{
function Bar ()
{
echo "Derived::Bar()";
}
}
Derived::Foo(); // we want this to print "Derived::Bar()"
?>
Then you'll find that PHP can't (unless somebody knows the Right Way?) since 'self::' refers to the class which owns the
/code/, not the actual class which is called at runtime. (__CLASS__ doesn't work either, because: A. it cannot appear before
::, and B. it behaves like 'self')
But if you must, then here's a (only slightly nasty) workaround:
<?php
class Base
{
function Foo ( $class = __CLASS__ )
{
call_user_func(array($class,'Bar'));
}
}
class Derived extends Base
{
function Foo ( $class = __CLASS__ )
{
parent::Foo($class);
}

function Bar ()
{
echo "Derived::Bar()";
}
}
Derived::Foo(); // This time it works.
?>
Note that Base::Foo() may no longer be declared 'static' since static methods cannot be overridden (this means it will trigger
errors if error level includes E_STRICT.)
If Foo() takes parameters then list them before $class=__CLASS__ and in most cases, you can just forget about that parameter
throughout your code.
The major caveat is, of course, that you must override Foo() in every subclass and must always include the $class parameter
when calling parent::Foo().

christian at koch dot net 16-Nov-2004 09:10


STATIC is cool. Here is an example how to get an existing instance as a Singleton:
<?php
class Singleton {
private static $instance=null;
private $value=null;
private function __construct($value) {
$this->value = $value;
}
public static function getInstance() {
if ( self::$instance == null ) {
echo "<br>new<br>";
self::$instance = new Singleton("values");
} else {
echo "<br>old<br>";
}
return self::$instance;
}
}
$x = Singleton::getInstance();
var_dump($x); // returns the new object
$y = Singleton::getInstance();
var_dump($y); // returns the existing object
?>
ckj

dmintz at davidmintz dot org 09-Nov-2004 03:20


[Editor's Note: This is done for back compatability. Depending on your error level, An E_STRICT error will be thrown.]

PHP 5.0.1 doesn't seem to mind if you call a static method in a non-static context, though it might not be the best of style
to do so.
On the other hand, PHP complains if you try to try to call a non-static method in a static context (if your error reporting is
cranked up to E_STRICT).
class Test {

static function static_method() {


echo "Here's your static method: Foo!<br />\n";
}
function static_method_caller() {
echo "static_method_caller says: ";$this->static_method();
}
function non_static() {
echo "I am not a static method<br />\n";
}
}
$t = new Test();
$t->static_method();
$t->static_method_caller();
Test::non_static();

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Class Abstraction
PHP 5 introduces abstract classes and methods. Classes defined as abstract may not be instantiated, and 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. Furthermore the signatures of the methods must match, i.e. the type
hints and the number of required arguments must be the same. This also applies to constructors as of PHP 5.4.
Before 5.4 constructor signatures could differ.
Example #1 Abstract class example
<?php
abstractclassAbstractClass
{
//ForceExtendingclasstodefinethismethod
abstractprotectedfunctiongetValue();
abstractprotectedfunctionprefixValue($prefix);
//Commonmethod
publicfunctionprintOut(){
print$this->getValue()."\n";
}
}
classConcreteClass1extendsAbstractClass
{
protectedfunctiongetValue(){
return"ConcreteClass1";
}
publicfunctionprefixValue($prefix){
return"{$prefix}ConcreteClass1";
}
}
classConcreteClass2extendsAbstractClass
{
publicfunctiongetValue(){
return"ConcreteClass2";
}
publicfunctionprefixValue($prefix){
return"{$prefix}ConcreteClass2";
}
}
$class1=newConcreteClass1;
$class1->printOut();
echo$class1->prefixValue('FOO_')."\n";
$class2=newConcreteClass2;
$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.

User Contributed Notes

Class Abstraction

oliver at ananit dot de 27-Nov-2011 08:07


Abstract classes may have an final constructor, and sometime it makes sense to implement a class with a final constructor.
<?php
abstract class AbstractModel
{
//our models must use the default constuctor
public final function __construct(){}
public function inject($array){
foreach(array_keys(get_class_vars(get_called_class())) as $property){
$this->$property = $array[$property];
}
}
}
class ProductModel extends AbstractModel
{
public $name;
public $price;
protected $id;

public function getId(){return $this->id;}


}
class Factory{
private $dataSource;
public function __consruct($dataSource){
$this->dataSource = $dataSource;
}

public function get($class, $table, $filter, $orderby, $limit){


$result = array();
foreach($datasource->fetchAssoc($table, $filter, $orderby, $limit) as $rawData){
$obj = new $class();//this can only work if ALL models have a default constructor
$obj->inject($rawData);
$result[] = $obj;
}
return $result;
}
}
?>
Note: This is a very simple example, and I am aware that there are other (better) ways to do this.

Oliver Anan

darkmantis at cybershade dot org 13-Oct-2011 09:25


This may be irrelevant to you, but I just had an idea about abstract classes and the final keyword. If you declare a class
as abstract and the constructor of that class as final, then the extending class will not work:
<?php
abstract class newClass{
final public function __construct(){
echo 'You failed xD';
}
}
class MyClass extends newClass{
public function __construct(){
echo 'Will this work?';
}

public static function myFunc(){


echo 'FooBar';
}
}
$init = new MyClass();
$init::myFunc();
?>
And that will return :
Fatal error: Cannot override final method newClass::__construct() in C:\wamp\Projects\BMPortal\public_html\newPHPClass.php on
line 16

joelhy 31-May-2011 07:27


The documentation says: "It is not allowed to create an instance of a class that has been defined as abstract.". It only means
you cannot initialize an object from an abstract class. Invoking static method of abstract class is still feasible. For
example:
<?php
abstract class Foo
{
static function bar()
{
echo "test\n";
}
}
Foo::bar();
?>

Adrian N 02-May-2011 04:10


By their nature, although sometimes they may look quite similar, abstract classes and class interfaces serve very distinct
purposes.
The interface of a class is meant as a tool for the "user" of that class. An interface is a public presentation for the class,
and it should advertise, to anyone considering to use it, what methods and constants are available and accessible from the
outside. So, as it name suggests, it always sits between the user and the class implementing it.

On the other hand, an abstract class is a tool aimed at helping the "implementor" of the classes that extend it. It is an
infrastructure that can impose restrictions and guidelines about what the concrete classes should look like. From a class
design perspective, abstract classes are more architecturally important than interfaces. In this case, the implementor sits
between the abstract class and the concrete one, building the latter on top of the former.

a dot tsiaparas at watergate dot gr 26-Mar-2011 03:57


Abstraction and interfaces are two very different tools. The are as close as hammers and drills. Abstract classes may have
implemented methods, whereas interfaces have no implementation in themselves.
Abstract classes that declare all their methods as abstract are not interfaces with different names. One can implement multiple
interfaces, but not extend multiple classes (or abstract classes).
The use of abstraction vs interfaces is problem specific and the choice is made during the design of software, not its
implementation. In the same project you may as well offer an interface and a base (probably abstract) class as a reference that
implements the interface. Why would you do that?
Let us assume that we want to build a system that calls different services, which in turn have actions. Normally, we could
offer a method called execute that accepts the name of the action as a parameter and executes the action.
We want to make sure that classes can actually define their own ways of executing actions. So we create an interface IService
that has the execute method. Well, in most of your cases, you will be copying and pasting the exact same code for execute.
We can create a reference implemention for a class named Service and implement the execute method. So, no more copying and
pasting for your other classes! But what if you want to extend MySLLi?? You can implement the interface (copy-paste probably),
and there you are, again with a service. Abstraction can be included in the class for initialisation code, which cannot be
predefined for every class that you will write.
Hope this is not too mind-boggling and helps someone. Cheers,
Alexios Tsiaparas

designbyjeeba at gmail dot com 26-Dec-2010 06:29


Please be aware of the visibility of the parent fields. If the fields are private, then you are not going to see those fields
in their childrens. Its basic OOP, but can be problematic sometimes.

bishop 28-Jul-2010 10:36


Incidentally, abstract classes do not need to be base classes:
<?php
class Foo {
public function sneeze() { echo 'achoooo'; }
}
abstract class Bar extends Foo {
public abstract function hiccup();
}
class Baz extends Bar {
public function hiccup() { echo 'hiccup!'; }
}
$baz = new Baz();
$baz->sneeze();
$baz->hiccup();
?>

mbajoras at gmail dot com 31-Dec-2009 11:59


Here's an example that helped me with understanding abstract classes. It's just a very simple way of explaining it (in my
opinion). Lets say we have the following code:
<?php
class Fruit {
private $color;

public function eat() {


//chew
}

public function setColor($c) {


$this->color = $c;
}
}
class Apple extends Fruit {
public function eat() {
//chew until core
}
}
class Orange extends Fruit {
public function eat() {
//peel
//chew
}
}
?>
Now I give you an apple and you eat it.
<?php
$apple = new Apple();
$apple->eat();
?>
What does it taste like? It tastes like an apple. Now I give you a fruit.
<?php
$fruit = new Fruit();
$fruit->eat();
?>
What does that taste like??? Well, it doesn't make much sense, so you shouldn't be able to do that. This is accomplished by
making the Fruit class abstract as well as the eat method inside of it.
<?php
abstract class Fruit {
private $color;

abstract public function eat();

public function setColor($c) {


$this->color = $c;
}
}

?>
Now just think about a Database class where MySQL and PostgreSQL extend it. Also, a note. An abstract class is just like an
interface, but you can define methods in an abstract class whereas in an interface they are all abstract.

nathan dot vorbei dot tech at gmail dot com 16-Nov-2009 10:55
"additionally, these methods must be defined with the same (or a less restricted) visibility."
The words were not restricted in abstract class but also normal classes,
the method in child Class which overwrites the parent Class can also change the the visibility of the method to same or less
restricted.
for example:
<?php
class ClassOne {
protected static $staticone = 'nathan';
protected function changestaticone() {
return self::$staticone = 'john';
}
}
class ClassTwo extends ClassOne {
public function changestaticone() {
return self::$staticone = 'Alexey';
}
}
$classtwo = new ClassTwo();
echo $classtwo->changestaticone();

pete at surfaceeffect dot com 13-Oct-2009 02:49


One fairly important difference between php's abstract functions and, say, Java, is that php does not specify the return type
in any way - or indeed whether there has to be one.
<?php public abstract function square($number); ?>
could be implemented by...
<?php
public function square($number) {
return $number*$number;
}
?>
or
<?php
public function square($number) {
print ($number*$number);
}
?>
So you need to take care that incompatibilities don't arise due to not returning the right kind of value and this is not
enforced in any way.

Cheese Doodle 22-Sep-2009 04:13


There isn't really that much of a great hurdle in understanding these things, there really isn't.

If you're defining a new class that is abstract, it means that you can make some non-abstract functions that you can use to
define the general underlying behavior of that class along side abstract ones.
In interfaces, you can't do that since functions defined therewithin cannot have a body.
Abstract functions you use for classes that must define more specific behavior when "extending" your class.
So for a crude example - define by your non-abstract functions how that particular object (which may be part of a larger class
hierarchy) would store and process it's data in SQL, XML, etc.
Then define abstract functions which allow someone implementing that class to specifically manipulate the data that is to be
stored. Then require a format which this data must be returned in, and then in your non-abstract functions call those functions
on destruction, in normal runtime, and so on.
Again, non-abstract functions, or even another class could implement the finer points of ensuring that data is in the correct
format, and so on, ad infinitum.
It isn't too much of a reach to say that if you used a normal class instead of an abstract class, then there isn't much
intrinsic requirement between the two classes.
Assuming that you wanted the functions to use each-others functions and you'd need to use them specifically by name, you'd have
to write some code which checked to see -- lamely using function_exists() and other lamery -- if that class has the function
you require for interoperability, when you could avoid all possible confusion and headaches by simply using the right tool for
the job.
And reading a decent OOP book.

Kiam 01-Aug-2009 12:04


The person - student - employee is the classic example where the interfaces are more appropriate.
It is true that students, and employees are persons, but a person can be both a student, and an employee.
<?php
class Person {
// Properties for Person objects.
}
interface IStudent {
// ...
}
interface IEmployee {
// ...
}
class Student implements IStudent extends Person {
// ...
}
class StudentEmployee implements IStudent, IEmployee extends Person {
// ...
}
?>

eeescalona 02-Jun-2008 09:04


here is a real world example of abstract using:

a (abstract) person class


a student and an employee final class, which extends person class.
simple theory is that both student and employee is an extension of the person class. the difference lies on which table the
data is written on, and what other pre processing (ie mandatory field checking, type checking, etc.) needed before writing each
of the classes.
codes:
<?php
abstract class person {

abstract protected function write_info();

public $LastName;
public $FirstName;
public $BirthDate;

public function get_Age($today=NULL){


//age computation function
}
}
final class employee extends person{
public $EmployeeNumber;
public $DateHired;
public function write_info(){
echo "Writing ". $this->LastName . "'s info to emloyee dbase table";
//ADD unique mandatory checking unique to EMPLOYEE ONLY
//actual sql codes here
}
}
final class student extends person{
public $StudentNumber;
public $CourseName;

public function write_info(){


echo "Writing ". $this->LastName . "'s info to student dbase table";
//ADD unique mandatory checking unique to STUDENT ONLY
//actual sql codes here
}
}
///---------$personA = new employee;
$personB = new student;
$personA->FirstName="Joe";
$personA->LastName="Sbody";
$personB->FirstName="Ben";
$personB->LastName="Dover";
$personA->write_info();
?>

OUTPUT:Writing Sbody's info to emloyee dbase table

keithjfrank at gmail dot com 13-May-2008 01:19


While building my database class, I came across something I didn't see any documentation on...
abstract class db
{
abstract protected function prepareSelect();
}
class dbPlugin extends db
{
/**
* Prepare Select
* Populates $this->currentQuery with MySQL formatted SELECT query.
*
* @param string Fields to retrieve
* @param string Table from which fields will be selected
* @param string Optional WHERE restriction
**/
protected function prepareSelect( $fields, $table, $where = NULL )
{
$this->currentQuery .= "SELECT {$fields} FROM {$this->dbSettings['sqlPrefix']}{$table}";

if ( $where !== NULL )
{
$this->currentQuery .= " WHERE {$where}";
}
}
}
While executing the script I was greeted with: Fatal error: Declaration of dbPlugin::prepareSelect() must be compatible with
that of db::prepareSelect() in [...]\includes\plugins\dbMySQL.php on line 209
The fix? Adding the same expected variables to the parent abstract method.
abstract class db
{
abstract protected function prepareSelect( $fields, $table, $where );
}
I am unsure as to whether this is common knowledge or not, but I figured I would share to ease someone else's frustration
while figuring out what was going awry. :)

ironiridis at gmail dot com 27-Mar-2008 01:56


Just one more time, in the simplest terms possible:
An Interface is like a protocol. It doesn't designate the behavior of the object; it designates how your code tells that object
to act. An interface would be like the English Language: defining an interface defines how your code communicates with any
object implementing that interface.
An interface is always an agreement or a promise. When a class says "I implement interface Y", it is saying "I promise to have
the same public methods that any object with interface Y has".
On the other hand, an Abstract Class is like a partially built class. It is much like a document with blanks to fill in. It

might be using English, but that isn't as important as the fact that some of the document is already written.
An abstract class is the foundation for another object. When a class says "I extend abstract class Y", it is saying "I use
some methods or properties already defined in this other class named Y".
So, consider the following PHP:
<?php
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>
You would have your class implement a particular interface if you were distributing a class to be used by other people. The
interface is an agreement to have a specific set of public methods for your class.
You would have your class extend an abstract class if you (or someone else) wrote a class that already had some methods written
that you want to use in your new class.
These concepts, while easy to confuse, are specifically different and distinct. For all intents and purposes, if you're the
only user of any of your classes, you don't need to implement interfaces.

sneakyimp at hotmail dot com 09-Oct-2007 05:05


Ok...the docs are a bit vague when it comes to an abstract class extending another abstract class. An abstract class that
extends another abstract class doesn't need to define the abstract methods from the parent class. In other words, this causes
an error:
<?php
abstract class class1 {
abstract public function someFunc();
}
abstract class class2 extends class1 {
abstract public function someFunc();
}
?>
Error: Fatal error: Can't inherit abstract function class1::someFunc() (previously declared abstract in class2) in
/home/sneakyimp/public/chump.php on line 7
However this does not:
<?php
abstract class class1 {
abstract public function someFunc();
}
abstract class class2 extends class1 {
}
?>
An abstract class that extends an abstract class can pass the buck to its child classes when it comes to implementing the
abstract methods of its parent abstract class.

eamon at gizzle dot co dot uk Eamon Straughn 20-Jul-2007 04:20


Sometimes I wonder. PHP needs to be pushed to its limits and below everyone fails to understand what an interface is and what
abstraction is. So let me make it extremely clear as I have many languages under my belt.
Interfaces are in general WYSIWYG implementations of logic which in PHP are not accessible like in other languages like Java \

ASP.NET where you don't have to access the class itself...however in future I hope PHP does give us this functionality.
Interfaces in PHP only define public functions without any basic or core functionality therefore making it lesser a friend to
PROs from OOP && OOD backgrounds.
Instead Abstraction in PHP is perfered as this allows your objects a core with the ability to define different levels of access
to methods | variables | constants. Although publicly allowing access to variables (to me) | (to official \ senior programmers)
defeats the whole idea of OO. Abstraction allows the keywords of final which is very important to me as I can have many child
objects of objects and of child objects.
Thus knowing the difference helps with your choosen style but if your really looking to make an application with Abstraction I
would always suggest using an Abstract Class instead of Interfaces as Interfaces are limited and provides no functionality and
is a waste of bytes on your hard drive.
The below is an example of Abstraction used in an automated system.
<?php
Abstract Class events
{
protected $priority;
protected $message;
protected $environment;
protected $syslog;
protected $config;
protected $global;
protected $classes;
protected $super;

public function __construct(array &$config)
{
$this->config = $config;
}

abstract protected function writeToDatabase(Environment &$environment);


abstract protected function writeToSystem(Environment &$environment);
abstract protected function writeToEmail(Environment &$environment);
abstract protected function writeToMobile(Environment &$environment);
abstract public function execute(&$class, $method, $args);

protected function environment(Exception &$object) {


$this->super =& new Environment($object, $this->config);
$this->global = $this->super->env();
$this->global = $this->global['environment'];
return $this->super;
}

public function __destruct()


{
unset($this);
}
}
?>

pierre at pamdata dot com 25-Jun-2007 06:25


I love examples.
This example will let you see that an Interface and an Astract Class are two different entities.
Just go and read the Object Interface section at :
http://www.php.net/manual/en/language.oop5.interfaces.php

and look at this example


<?php
/*
* A Very simple example to understand why we should use ABSRACT CLASSES.
* This abstract class contains 2 methods : 1 abstract and 1 common methods.
*
*/
abstract class Shape
{
# Let's assume a shape will always have a base and a height
protected $base;
protected $height;

#This function can be the same for both classes 'Triangle' and 'Rectangle'
public function getValue($base,$height)
{
$this->base = $base;
$this->height = $height;
}

# This might be different for each class of shape, because each Surface is calculated by a different formula ( St = b*h/2
and Sr = b*h)
abstract public function surface();
}
class Triangle extends Shape
{
# s = b*h/2
public function surface(){
return round((($this->base)*($this->height)/2),2);
}
}
class Rectangle extends Shape
{
# s = b*h
public function surface(){
return round((($this->base)*($this->height)),2);
}
}
$r = new Rectangle();
$r->getValue(15,3);
echo $r->surface() ."\n"; # echo 45
$t = new Triangle();
$t->getValue(15,3);
echo $t->surface() ."\n"; # echo 22.5
?>

joebert 24-Jun-2007 04:09


I don't agree with jfkallens' last comparison between Abstract Classes & Object Interfaces completely.
In an Abstract Class, you can define how some methods work, where as in an Object Interface you can not.

An Object Interface is essentually nothing but a list of function names that a class must define if the class implements that
interface.
An Abstract Class is essentually a prototype which hints towards what extending classes should be doing.
An Abstract Class can also be thought of as a Base Class that provides some basic functionality, & also defines a built-in
Object Interface that all extending classes will implement.
So, an Object Interface is really a built-in part of an Abstract Class.

david at mr-t dot nl 25-Jul-2006 08:27


It took me a while to figure this out and i couldn't find it easily in the documentation anywhere.
If you want to override a method from a base class and want to call the base class in the method, then you have to use the
parent::function() syntax, even though the method isn't static. There is no $base variable in php that i know of.
Expamle:
<?php
public abstract class BasePerson() {
/*
* alot of code..
*/
public function getName() {
return $this->name;
}
}
public class Person() extends BasePerson {
/*
* alot of code..
*/
// override of base getName()..
public function getName() {
// you would expect $base->getName() instead of parrent::getName()...
return htmlspecialchars(parent::getName());
}
}
?>
Hope this helps!

rasto_klc (at) yahoo (dot) obvious 28-Dec-2005 01:27


Variable-length argument lists in abstract methods will generate fatal error if derived. Here is an simple example:
<?php
// common wrap for all validators is forcing uniform interface
abstract class ValidatorWrap {
// just example why variable-length arguments are needed
public function __construct()
{
if (func_num_args() > 0) {
$arg_list = func_get_args();
call_user_func_array(array(&$this, 'setupValidator'), $arg_list);
} else {
$this->setupValidator();
}

// continue with construction


}
// amount of arguments is specific to validator implementation
abstract public function setupValidator();
// known interface
abstract public function validate($value);
}
class Validator1 extends ValidatorWrap {
protected $pattern = '';
// this will generate PHP Fatal error because $pattern is not expected
public function setupValidator($pattern)
{
$this->pattern = $pattern;
}
// this will do OK
public function validate($value)
{
return preg_match($this->pattern, $value);
}
}
// make numeric validator
$validator = new Validator1('/^\d+$/');
echo (int) $validator->validate($_REQUEST['digits']);
?>
I need it to work so I just redefine troublemaking function as follows:
<?php
public function setupValidator() { }
?>
This will give me functionality I need and generates only PHP Strict Standards warning.

turgut85 at hotmail dot com 02-Dec-2005 09:38


<?php
// Design Pattern ABSTRACT FACTORY implementation //
abstract class AbstractFactory {
public abstract function CreateProductA(); // return data type is AbstractProductA
public abstract function CreateProductB(); // return data type is AbstractProductB
}
// Abstract factory #1 //
class ConcreteFactory1 extends AbstractFactory {
public function CreateProductA() { // return data type is AbstractProductA
return new ProductA1();
}
public function CreateProductB() { // return data type is AbstractProductB

return new ProductB1();


}
}
// Abstract factory #2 //
class ConcreteFactory2 extends AbstractFactory {
public function CreateProductA() { // return data type is AbstractProductA //
return new ProductA2();
}
public function CreateProductB() { // return data type is AbstractProductB //
return new ProductB2();
}
}
// "AbstractProductA" //
abstract class AbstractProductA {
}
// "AbstractProductB" //
abstract class AbstractProductB {
public abstract function Interact($a); // return type is void // // input type is AbstractProductA
}
// "ProductA1" //
class ProductA1 extends AbstractProductA {
}
// "ProductB1" //
class ProductB1 extends AbstractProductB {
public function Interact($a) {
echo __CLASS__." interacts with ".__METHOD__."\n";
var_dump($a);
}
}
// "ProductA2"
class ProductA2 extends AbstractProductA {
}
// "ProductB2"
class ProductB2 extends AbstractProductB {
public function Interact($a) {
echo __CLASS__." interacts with ".__METHOD__."\n";
var_dump($a);
}
}
class Client {
private $AbstractProductA; // type AbstractProductA;
private $AbstractProductB; // type AbstractProductB;
// Constructor
public function __construct($factory) {
$this->AbstractProductB = $factory->CreateProductB();
$this->AbstractProductA = $factory->CreateProductA();
}

public function Run() {


$this->AbstractProductB->Interact($this->AbstractProductA);
}
}
// Abstract factory #1
$factory1 = new ConcreteFactory1();
$c1 = new Client($factory1);
$c1->Run();
// Abstract factory #2
$factory2 = new ConcreteFactory2();
$c2 = new Client($factory2);
$c2->Run();
// TURGUT Z. YESILYURT, MS
// Software Developer
// NewJersey, USA
?>
Output::
ProductB1 interacts with ProductB1::Interact
object(ProductA1)#4 (0) {
}
ProductB2 interacts with ProductB2::Interact
object(ProductA2)#8 (0) {
}

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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.

Note:
Interfaces can be extended like classes using the extends operator.

Note:
The class implementing the interface must use the exact same method signatures as are defined in the
interface. Not doing so will result in a fatal error.

Constants
It's possible for interfaces to have constants. Interface constants works exactly like class constants except they
cannot be overridden by a class/interface that inherits them.

Examples
Example #1 Interface example
<?php
//Declaretheinterface'iTemplate'
interfaceiTemplate
{
publicfunctionsetVariable($name,$var);
publicfunctiongetHtml($template);
}
//Implementtheinterface
//Thiswillwork
classTemplateimplementsiTemplate
{
private$vars=array();

publicfunctionsetVariable($name,$var)

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

publicfunctiongetHtml($template)
{
foreach($this->varsas$name=>$value){
$template=str_replace('{'.$name.'}',$value,$template);
}

return$template;
}
}
//Thiswillnotwork
//Fatalerror:ClassBadTemplatecontains1abstractmethods
//andmustthereforebedeclaredabstract(iTemplate::getHtml)
classBadTemplateimplementsiTemplate
{
private$vars=array();

publicfunctionsetVariable($name,$var)
{
$this->vars[$name]=$var;
}
}
?>

Example #2 Extendable Interfaces


<?php
interfacea
{
publicfunctionfoo();
}
interfacebextendsa
{
publicfunctionbaz(Baz$baz);
}
//Thiswillwork
classcimplementsb
{
publicfunctionfoo()
{
}
publicfunctionbaz(Baz$baz)
{
}
}
//Thiswillnotworkandresultinafatalerror
classdimplementsb
{
publicfunctionfoo()
{
}

publicfunctionbaz(Foo$foo)
{
}
}
?>

Example #3 Multiple interface inheritance


<?php
interfacea
{
publicfunctionfoo();
}
interfaceb
{
publicfunctionbar();
}
interfacecextendsa,b
{
publicfunctionbaz();
}
classdimplementsc
{
publicfunctionfoo()
{
}
publicfunctionbar()
{
}
publicfunctionbaz()
{
}
}
?>

Example #4 Interfaces with constants


<?php
interfacea
{
constb='Interfaceconstant';
}
//Prints:Interfaceconstant
echoa::b;

//Thiswillhowevernotworkbecauseit'snotallowedto
//overrideconstants.
classbimplementsa
{
constb='Classconstant';
}

?>

An interface, together with type-hinting, provides a good way to make sure that a particular object contains
particular methods. See instanceof operator and type hinting.

User Contributed Notes

Object Interfaces

md2perpe 04-Apr-2012 03:08


When implementing an interface that extends Traversable, not only you have to supply an implementation of Traversable (i.e.
either Iterator or IteratorAggregate) and tell which one you implement.
It also matters in which order the implemented interfaces are listed.
Changing "implements Iterator, MyTraversable" to "implements MyTraversable, Iterator" in the following snippet fails as of PHP
5.3.10:
<?php
interface MyTraversable extends Traversable {}
class MyClass implements Iterator, MyTraversable
{
// Implement Iterator
public function rewind() {}
public function valid() {}
public function current() {}
public function key() {}
public function next() {}
}
?>

guillaume at metayer dot ca 09-Mar-2012 03:11


I think good OOP design will actually require both what dlovell2001 and anon said. In the examples below, if Database is only
an abstract class, you will have limitations. What if one day you have a special Database object that is so different for some
specific needs, that it should NOT inherit from the Database abstract class? You would be stuck. In my opinion, the best thing
to do would be to have a Database abstract class that implements a DatabaseInterface interface.
When working on a Database object, you would first make sure it implements the DatabaseInterface object (dlovell2001, this is
something very important that's missing in your example). You can still use any object inheriting the Database class (because
this class implements the DatabaseInterface interface) but you are NOT limited to using an object inheriting from Database. Any
object implementing the DatabaseInterface will do. This way, you are not limited to a specific type.
Interfaces are a good way to have a 'contract' with the component using a certain object, without being limited to using a
specific type for that object. Also remember to use the 'instanceof' or similar when working on such object. One goal of
interfaces is to actually enforce the signature of an object before actually working with it.

dlovell2001 at yahoo dot com 03-Feb-2012 10:40


It seems like many contributors are missing the point of using an INTERFACE. An INTERFACE is not specifically provided for
abstraction. That's what a CLASS is used for. Most examples in this article of interfaces could be achieved just as easily
using just classes alone.
An INTERFACE is provided so you can describe a set of functions and then hide the final implementation of those functions in an
implementing class. This allows you to change the IMPLEMENTATION of those functions without changing how you use it.

For example: I have a database. I want to write a class that accesses the data in my database. I define an interface like
this:
interface Database {
function listOrders();
function addOrder();
function removeOrder();
...
}
Then let's say we start out using a MySQL database. So we write a class to access the MySQL database:
class MySqlDatabase implements Database {
function listOrders() {...
}
we write these methods as needed to get to the MySQL database tables. Then you can write your controller to use the interface
as such:
$database = new MySqlDatabase();
foreach ($database->listOrders() as $order) {
Then let's say we decide to migrate to an Oracle database. We could write another class to get to the Oracle database as such:
class OracleDatabase implements Database {
public function listOrders() {...
}
Then - to switch our application to use the Oracle database instead of the MySQL database we only have to change ONE LINE of
code:
$database = new OracleDatabase();
all other lines of code, such as:
foreach ($database->listOrders() as $order) {
will remain unchanged. The point is - the INTERFACE describes the methods that we need to access our database. It does NOT
describe in any way HOW we achieve that. That's what the IMPLEMENTing class does. We can IMPLEMENT this interface as many times
as we need in as many different ways as we need. We can then switch between implementations of the interface without impact to
our code because the interface defines how we will use it regardless of how it actually works.

julien arobase fastre point info 12-Dec-2011 11:12


If you use namespaces and autoloading, do not forget to mention the use statement for each class used in yours arguments,
before your class:
<?php
#file : fruit/squeezable.php
namespace fruit
use BarFoo;
interface squeezable {
public function squeeze (Foo $foo);
}
?>
<?php
#file: orange

namespace fruitcitrus;
class orange {
public function squeeze(Foo $foo);
}
#Will throw an exception Fatal error: Declaration of "fruit\citrus\orange::squeeze must be compatible with that of
fruit\squeezable() in fruit/squeezable.php
?>
<?php
#file: orange
namespace fruitcitrus;
use BarFoo; #DO NOT FORGET THIS!
class orange {
public function squeeze (Foo $foo);
}
#Will be correct
?>

FX Laviron 25-Oct-2011 09:12


The error "Can't inherit abstract function IB::f() (previously declared abstract in IA)" in the following code
<?php
interface IA { public function f(); }
interface IB { public function f(); }
class Test implements IA, IB {
public function f() {
echo "f";
}
}
$o = new Test();
$o->f();
?>
can be avoided (if appropriate) by adding a ancestor interface to IA and IB, and moving the common method to it:
<?php
interface IAncestor { public function f(); }
interface IA { }
interface IB extends IAncestor { }
class Test implements IA, IB {
public function f() {
echo "f";
}
}
$o = new Test();
$o->f();
?>

thanhn2001 at gmail dot com 03-Mar-2011 01:37


PHP prevents interface a contant to be overridden by a class/interface that DIRECTLY inherits it. However, further inheritance
allows it. That means that interface constants are not final as mentioned in a previous comment. Is this a bug or a feature?
<?php
interface a
{
const b = 'Interface constant';
}
// Prints: Interface constant
echo a::b;
class b implements a
{
}
// This works!!!
class c extends b
{
const b = 'Class constant';
}
echo c::b;
?>

jballard at natoga dot com 06-Jan-2011 01:33


If it isn't already obvious, you can create an object of a class above the class declaration if it does NOT implement an
interface. However, when a class DOES implement an interface, PHP will throw a "class not found" error unless the instantiation
declaration is _below_ the class definition.
<?php
$bar = new foo(); // Valid
class foo
{

}
?>
<?php
$bar = new foo(); // Invalid - throws fatal error
interface foo2
{
}
class bar implements foo2
{

}
$bar = new foo(); // Valid, since it is below the class declaration
?>

Also, @Jeffrey -- Lol? What? Is that a joke? PHP interfaces have nothing to do with connecting to "peripheral devices" or
"cameras", etc. Not even in the least sense. This is a very common miscommunication with the word "interface", as interfaces in
programming are not at all like interfaces in electronics or drivers, etc.

gratcypalma at gmail dot com 19-Nov-2010 11:07


here is my simply method muliple inheritence with __construct function..
<?php
class foo {
protected $mam = 'mamam';
function __construct() {
echo 'foo';
}
}
class bar extends foo {
function __construct() {
parent:: __construct();
echo 'bar';
}
}
class foobar extends bar {
function __construct() {
parent:: __construct();
echo 'foobar';
}
}
$foo = new foobar();
?>

Anonymous 13-Aug-2010 12:44


If you want to ensure implementation classes are correctly initialised (i.e. due to trickery one needs to do to work around
lack of multiple inheritance), simply add __construct() to your interface, so risk of init being forgotten is reduced.

drieick at hotmail dot com 23-Feb-2010 09:29


I was wondering if implementing interfaces will take into account inheritance. That is, can inherited methods be used to follow
an interface's structure?
<?php
interface Auxiliary_Platform {
public function Weapon();
public function Health();
public function Shields();
}
class T805 implements Auxiliary_Platform {
public function Weapon() {
var_dump(__CLASS__);
}
public function Health() {
var_dump(__CLASS__ . "::" . __FUNCTION__);
}
public function Shields() {
var_dump(__CLASS__ . "->" . __FUNCTION__);

}
}
class T806 extends T805 implements Auxiliary_Platform {
public function Weapon() {
var_dump(__CLASS__);
}
public function Shields() {
var_dump(__CLASS__ . "->" . __FUNCTION__);
}
}
$T805 = new T805();
$T805->Weapon();
$T805->Health();
$T805->Shields();
echo "<hr />";
$T806 = new T806();
$T806->Weapon();
$T806->Health();
$T806->Shields();
/* Output:
string(4) "T805"
string(12) "T805::Health"
string(13) "T805->Shields"
<hr />string(4) "T806"
string(12) "T805::Health"
string(13) "T806->Shields"
*/
?>
Class T805 implements the interface Auxiliary_Platform. T806 does the same thing, but the method Health() is inherited from
T805 (not the exact case, but you get the idea). PHP seems to be fine with this and everything still works fine. Do note that
the rules for class inheritance doesn't change in this scenario.
If the code were to be the same, but instead T805 (or T806) DOES NOT implement Auxiliary_Platform, then it'll still work. Since
T805 already follows the interface, everything that inherits T805 will also be valid. I would be careful about that.
Personally, I don't consider this a bug.
This seems to work in PHP5.2.9-2, PHP5.3 and PHP5.3.1 (my current versions).
We could also do the opposite:
<?php
class T805 {
public function Weapon() {
var_dump(__CLASS__);
}
}
class T806 extends T805 implements Auxiliary_Platform {
public function Health() {
var_dump(__CLASS__ . "::" . __FUNCTION__);
}
public function Shields() {

var_dump(__CLASS__ . "->" . __FUNCTION__);


}
}
$T805 = new T805();
$T805->Weapon();
echo "<hr />";
$T806 = new T806();
$T806->Weapon();
$T806->Health();
$T806->Shields();
/* Output:
string(4) "T805"
<hr />string(4) "T805"
string(12) "T806::Health"
string(13) "T806->Shields"
*/
?>
This works as well, but the output is different. I'd be careful with this.

uramihsayibok, gmail, com 10-Feb-2010 11:25


Interfaces can define static methods, but note that this won't make sense as you'll be using the class name and not
polymorphism.
...Unless you have PHP 5.3 which supports late static binding:
<?php
interface IDoSomething {
public static function doSomething();
}
class One implements IDoSomething {
public static function doSomething() {
echo "One is doing something\n";
}
}
class Two extends One {
public static function doSomething() {
echo "Two is doing something\n";
}
}
function example(IDoSomething $doer) {
$doer::doSomething(); // "unexpected ::" in PHP 5.2
}
example(new One()); // One is doing something
example(new Two()); // Two is doing something
?>

If you have PHP 5.2 you can still declare static methods in interfaces. While you won't be able to call them via LSB, the
"implements IDoSomething" can serve as a hint/reminder to other developers by saying "this class has a ::doSomething() method".
Besides, you'll be upgrading to 5.3 soon, right? Right?
(Heh. I just realized: "I do something". Unintentional, I swear!)

btjakachira at gmail dot com 11-Jan-2010 01:52


I'm going to give a very simple explanation between interface and any abstract. I'm not going to repeat basic stuff mentioned
above e.g you can not instantiate an interface or an abstract. Any class with an abstract method should be declared as
abstract.. etc.
Example.
I will show you where and when to use interfaces. Normally people will use interface when absctracting becomes a problem. Lets
say we start with the following objects
<?php
Person
Employee
Employer
Criminal
Rapist
President
Student
?>
You will easily see that Employee is a Person, Criminal is a person etc.. Therefore we can have Person as a PARENT class. For
person to be abstract, you decide within your application if a person object makes sense... if it doesn't make the person an
abstract so that you wont have alien objects.
Now, interfaces are used when, in a group of objects, you have two or more objects that share similar behaviour. E.g President
and Employer will makePolicy() while Criminal and Rapist will commitCrime(). Having said that, normally people would put these
methods in their respective classes (but defeating the OO designs). If you put makePolicy() in President and Employer class
there will be duplication of code. Other people can be tempted to put thet makePolicy() and commitCrime() in Person as abstract
methods so that the 6 objects will see the methods. Its not a good idea as Student or Employee will not normally makePolicy()
or commitCrime(). In fact, it means Employee object can makePolicy() of increasind salary :-) . Therefore in this case we use
INTERFACES
<?php
interface HighOffice {
public function makePolicy();
public function declareEmergency();
}
interface jailable {
public function commitCrime();
public function appeal();
}
abstract class Person {
public function getAge()
{
return "28years";
}
}
public class Employee extend Person {

//do stuff for employee


}
public class Criminal extend Person impliments jailable{
//do stuff for a criminal.

//these must be present.


public function commitCrime()
{
}
public function appeal()
{
}
public class President extend Person impliments HighOffice
{
//do other stuff for President
//then a President should make policies and declare emergency
public function makePolicy()
{
}
public function declareEmergency()
{
}
}
}

?>
NB: forgive me for errors syntax. I in the middle of doing Java.
You have noticed that relevant behavious have been added to the relevant objects..

rskret at ranphilit dot com 02-Jun-2009 02:47


This may help understand EX.2. Below are modifiers and additions to
the code. Refer to EX.2 to make a complete code block(this saves comment
space!).
I found the function definition baz(Baz $baz) baffling. Lucky was
able to sus it out fast. Seems method baz requires just one arg and
that must be an instance of the class Baz. Here is a way to know how to
deal with that sort of arg...
<?php
# modify iface b...adding $num to get better understanding
interface b extends a
{
public function baz(Baz $baz,$num);
}
# mod claas c
class c implements b
{
public function foo()
{
echo'foo from class c';
}

public function baz(Baz $baz,$num)


{
var_dump ($baz);# object(Baz)#2 (1) { ["bb"]=> string(3) "hot" }
echo '<br>';
echo $baz->bb." $num";echo '<br>';# hot 6
}
}
# add a class Baz...
class Baz
{
public $bb='hot';
function ebaz(){
echo'this is BAZ';
}
}
# set instance of Baz and get some output...
$bazI=new Baz;
baz::ebaz();echo '<br>';# this is BAZ
c::baz($bazI,6);
?>

cretz 21-Sep-2008 03:49


FYI, interfaces can define constructors, destructors, and magic methods. This can be very helpful especially in the case of
constructors when instantiating an implementing class via reflection in some sort of factory. Of course, it is not recommended
to do such a thing since it goes against the nature of a true interface.

lazybones_senior 15-Sep-2008 10:41


WHOA! KEEP IT SIMPLE...
With the code below, you already get a feel at how much ground this app might cover.
<?php
interface ElectricalDevice{
public function power_on();
public function power_off();
}
interface FrequencyTuner{
public function get_frequencey();
public function set_frequency($f);
}
class ElectricFan implements ElectricalDevice{
// define ElectricalDevice...
}
class MicrowaveOven implements ElectricalDevice{
// define ElectricalDevice...
}
class StereoReceiver implements ElectricalDevice, FrequencyTuner{
// define ElectricalDevice...
// define FrequencyTuner...
}

class CellPhone implements ElectricalDevice, FrequencyTuner{


// define ElectricalDevice...
// define FrequencyTuner...
}
?>
Even those who lack imagination can fill in the blanks from here.

secure_admin 14-Sep-2008 02:28


In response to harryjry and mehea concerning your Weather Model. The problem is that you don't need all the things you think
you need. In OOP, good class definitions get to the point rather quickly.
<?php
class Weather{
public $time, $temperature, $humidity;
public function __construct($tm, $t, $h){
$this->time = $tm;
$this->temperature = $t;
$this->humidity = $h;
}
public function __toString(){
return "Time: $this->time,
Temperature: $this->temperature&deg;,
Humidity: $this->humidity%";
}
}
$forecasts = array(
new Weather("1:00 pm", 65, 42),
new Weather("2:00 pm", 66, 40),
new Weather("3:00 pm", 68, 39)
// add more weather reports as desired...
);
echo "Forecast for Chicago, IL:<br>";
foreach($forecasts as $forecast) echo ' - ' . $forecast '<br>';
?>
Forecast for Chicago, IL:
- Time: 1:00 pm, Temperature: 65, Humidity: 42%
- Time: 2:00 pm, Temperature: 66, Humidity: 40%
- Time: 3:00 pm, Temperature: 68, Humidity: 39%
Note: MySQL can store data like this already, but if you included constants, more variables, and other functions in the Weather
class, then maybe, just maybe it could be of use.

mehea 30-Jul-2008 11:55


While a subclass may implement an interface by extending an abstract class that implements the interface, I question whether it
is good design to to do so. Here's what I would suggest while taking the liberty of modifying the above weather/wet model:
<?php
interface water
{
public function makeItWet();
}


/**
* abstract class implements water but defines makeItWet
* in the most general way to allow child class to
* provide specificity
**/
abstract class weather implements water
{
private $cloudy;
public function makeItWet(){}
abstract public function start();
abstract public function getCloudy();
abstract public function setCloudy();
}
class rain extends weather {
private $cloudy;
public function start() {
return "Here's some weather. ";
}

public function makeItWet() {


return 'it is raining cats and dogs today.';
}
public function getCloudy() {
return $this->cloudy;
}
public function setCloudy($bln=false) {
$this->cloudy = $bln;
}
}
$a = new rain();
echo $a->start();
$a->setCloudy(true);
if ($a->getCloudy()) {
echo 'It is a cloudy day and ';
}
echo $a->makeItWet();
?>

logik at centrum dot cz 17-Jul-2008 02:17


Makes them useles a bit. I give an example:
I have a class that enumerate (so implements iterator) a interface that has method key() that returns key for the enumerated
object.
I cannot implement iterator, that enumerates the objects by itself (so current() returns this), because of collision of method
key(). But it's not collision - the key in the iterator and the key in the enumerated object has the same meaning and allways
returns same values.
(Common example of this iterator is iterator, that reads from database - make a special object for each row is waste of time).
Yes - there are workarounds - e.g. rewrite the code so current don't return this - but it's in some cases waste of processor
time.
Or I can rename the method key in enumerated object - but why should I wrote the same method twice? It's either waste of time
(if the function key is simply duplicated) or waste of time (if the renamed key calls original key).
Well, the right, clear way there would be to redefine interface iterator -- move the method key to the ancestor of iterator,
and makes the ancestor ancestor of enumerated interface too. But it's (with built-in interfaces) impossible too.

harryjry at yahoo dot com 10-Jun-2008 02:29


The structure I am working with has a lot of inheritance going on, but not all methods are specified in one place. I needed a
way to make sure an interface would be used, but that the method(s) defined in the interface are defined somewhere.
As such, I learned that the parent can define the interface's methods, and then the children can override that method at will
without having to worry about the interface.
To expand on nrg1981's example, the following is possible:
<?php
interface water
{
public function makeItWet();
}
class weather
{
public function makeItWet()
{
return 'it may or may not be wet';
}

public function start()


{
return 'Here is some weather';
}
}
class rain extends weather implements water
{
public function makeItWet()
{
return 'It is wet';
}
}
class thunder extends weather implements water
{
}
$a = new rain();
echo $a->start() . "\n";
echo $a->makeItWet() . "\n";
$a = new thunder();
echo $a->start() . "\n";
echo $a->makeItWet() . "\n";
?>

kaisershahid at gmail dot com 07-Apr-2008 05:41


php at wallbash dot com's comment of "It's important to note this because it is very unexpected behavior and renders many
common Interface completly useless" doesn't make sense.
the idea of the interface is to force objects that aren't related to be reused in a common way. without them, to force that

requirement, all objects that need those methods implemented would have to be descended from a base class that's known to have
those methods. that's clearly not a smart idea if these objects aren't actually related.
one example (that i'm currently working on) is a background service that pulls information down from different content
providers. i have a transport and i have an import. for both, what actually happens in the background is different from
provider to provider, but since i'm implementing a transport & import interface, i only need to write code once, because i know
exactly the what methods will be implemented to get the job done. then, i just have a config file that loads the class
dynamically. i don't need something like
if ( $provider == "some company" )
{
// use this set of code
}
elseif ( $provider == "another company" )
{
// use this other set of code
}
instead, i can do:
foreach ( $providers as $provider => $info )
{
$_transport = $info['transportObject'];
$transport = new $_transport();
$_import = $info['importObject'];
$import = new $_import();

$transport->setImporter( $import );
$transport->retrieve();
}
it is expected behavior that when a class implements two interfaces that share one or more method names, an error is thrown,
because interfaces don't relate to each other. if you want that sort of inferred behavior (i.e. A and B are different except
for these shared methods), stick to [abstract] classes.
it sucks that interface methods might collide for some common types of tasks (get(), set(), etc.), so knowing that, design your
interfaces with more unique method names.

michael dot martinek at gmail dot com 03-Jan-2008 08:18


In regards to what Hayley Watson is writing:
The "interface" is a method of enforcing that anyone who implements it must include all the functions declared in the
interface. This is an abstraction method, since you cannot just declare a base class and do something like "public abstract
function myTest();" and later on extend that class.
If you don't override the default value in a parameter list, it's assumed that the default value was received by time you have
any control to read or relay the value on again. There should be no problem in having all or none of your parameters in an
interface having a default value, as the value is "auto-filled" if not explicitly provided.
I just came across interfaces in PHP.. but I use them quite a bit in Java and Delphi. Currently building different DB wrappers,
but all must enforce common access using a base class.. and also enforce that all of specific routines are implemented.

Docey 11-Nov-2007 03:23


Another note about default values in interfaces is that an class must implement at least the arguments as in the interface.
that is: an implementation may have more arguments but not less if these additional arguments have an default value and thus
can be called as declared in the interface.

an litte example:
<?php
interface myInterface{
public function setStuff($id, $name);
}
class MyFirstClass implements myInterface{
public function setStuff($id, $name);
}
class MySecondClass implements myInterface{
public function setStuff($id, $name, $type);
}
class myThirdClass implements myInterface{
public function setStuff($id, $name, $type=0);
}
?>
Here mySecondClass will print an fatal error while myThirdClass is just fine because myThirdClass::setStuff($id, $name); is
valid and thus fullfills the interface requirements. an interface declares as set of requirement on how methods can be called
and any class implementing an interface thus agrees that is will provide these methods and that they can be called as in the
interface. adding additional arguments with default values is thus allowed because it does not violate the agreement that the
method can be called as in the interface.

nrg1981 {AT} hotmail {DOT} com 05-Oct-2007 06:48


In case you would want to, a child class can implement an interface:
<?php
interface water
{
public function makeItWet();
}
class weather
{
public function start()
{
return 'Here is some weather';
}
}
class rain extends weather implements water
{
public function makeItWet()
{
return 'It is wet';
}
}
$a = new rain();
echo $a->start();
echo $a->makeItWet();
?>

Hayley Watson 21-Sep-2007 03:42


If it's not already obvious, it's worth noticing that the parameters in the interface's method declaration do not have to have
the same names as those in any of its implementations.
More significantly, default argument values may be supplied for interface method parameters, and they have to be if you want to
use default argument values in the implemented classes:
<?php
interface isStuffable
{
public function getStuffed($ratio=0.5);
}
class Turkey implements isStuffable
{
public function getStuffed($stuffing=1)
{
// ....
}
}
?>
Note that not only do the parameters have different names ($ratio and $stuffing), but their default values are free to be
different as well. There doesn't seem to be any purpose to the interface's default argument value except as a dummy placeholder
to show that there is a default (a class implementing isStuffable will not be able to implement methods with the signatures
getStuffed(), getStuffed($a), or getStuffed($a,$b)).

Hayley Watson 20-Sep-2007 10:34


On an incidental note, it is not necessary for the implementation of an interface method to use the same variable names for its
parameters that were used in the interface declaration.
More significantly, your interface method declarations can include default argument values. If you do, you must specify their
implementations with default arguments, too. Just like the parameter names, the default argument values do not need to be the
same. In fact, there doesn't seem to be any functionality to the one in the interface declaration at all beyond the fact that
it is there.
<?php
interface isStuffed {
public function getStuff($something=17);
}
class oof implements isStuffed {
public function getStuff($a=42) {
return $a;
}
}
$oof = new oof;
echo $oof->getStuff();
?>
Implementations that try to declare the method as getStuff(), getStuff($a), or getStuff($a,$b) will all trigger a fatal error.

php at wallbash dot com 05-Sep-2007 07:39

Please note that the sentence "Note: A class cannot implement two interfaces that share function names, since it would cause
ambiguity." _really_ means that it is not possible to do something like:
<?php
interface IA {
public function a();
}
interface IB {
public function a();
}
class Test implements IA, IB {
public function a() {
echo "a";
}
}
$o = new Test();
$o->a();
?>
lead to:
PHP Fatal error: Can't inherit abstract function IB::a() (previously declared abstract in IA)
It's important to note this because it is very unexpected behavior and renders many common Interface completly useless.

zedd at fadingtwilight dot net 04-Jul-2007 09:42


Regarding my previous note (04-Jul-2007 9:01):
I noticed a minor but critical mistake in my explanation. After the link to the PHP manual page on class abstraction, I stated:
"So by definition, you may only overload non-abstract methods."
This is incorrect. This should read:
"So by definition, you may only override non-abstract methods."
Sorry for any confusion.

zedd at fadingtwilight dot net 04-Jul-2007 09:01


prometheus at php-sparcle:
Your code fails because you're effectively trying to do this:
<?php
abstract class IFoo
{
abstract public function Foo();
}

abstract class IBar extends IFoo


{
// Fails; abstract method IFoo::Foo() must be defined in child and must match parent's definition
abstract public function Foo($bar);
}

?>
By definition, all methods in an interface are abstract. So the above code segment is equivalent to your interface definitions
and results in the same error. Why? Let's have a look at the PHP manual. From the second paragraph on class abstraction:
"When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the
child;"
http://www.php.net/manual/en/language.oop5.abstract.php
So by definition, you may only overload non-abstract methods.
For example:
<?php
abstract class IFoo
{
public function Foo()
{
// do something...
}
}

abstract class IBar extends IFoo


{
public function Foo($bar)
{
// do something else...
}
}
?>
This can't be directly replicated with interfaces since you can't implement methods inside of an interface. They can only be
implemented in a class or an abstract class.
If you must use interfaces, the following accomplishes the same thing, but with two separate method names:
<?php
interface IFoo
{
public function Foo();
}

interface IBar extends IFoo


{
public function Bar($bar);
}

class FooBar implements IBar


{
public function Foo()
{
// do something...
}

public function Bar($bar)
{
// do something else...
}
}

?>
If both methods need the same name, then you'll have to use non-abstract methods. In this case, interfaces aren't the right
tool for the job. You'll want to use abstract classes (or just regular classes).

Maikel 12-Jan-2007 03:07


if you want to implement an interface and in addition to use inheritance, first it uses extends and then implements
example:
<?php
class MyChildClass extends MyParentClass implements MyInterface
{
// definition
}
?>

Chris AT w3style DOT co.uk 07-Dec-2006 05:25


Note that you can extend interfaces with other interfaces since under-the-hood they are just abstract classes:
<?php
interface Foo {
public function doFoo();
}
interface Bar extends Foo {
public function doBar();
}
class Zip implements Bar {
public function doFoo() {
echo "Foo";
}
public function doBar() {
echo "Bar";
}
}
$zip = new Zip();
$zip->doFoo();
$zip->doBar();
?>
This is quite useful when you're using interfaces for identity more than the rigidity it places upon an API. You can get the
same result by implementing multiple interfaces.
An example of where I've used this in the past is with EventListener objects ala Java's Swing UI. Some listeners are
effectively the same thing but happen at different times therefore we can keep the same API but change the naming for clarity.

marasek AT telton POINT de 06-Sep-2006 06:01


What is not mentioned in the manual is that you can use "self" to force object hinting on a method of the implementing class:
Consider the following interface:
<?php

interface Comparable
{function compare(self $compare);}
?>
Which is then implemented:
<?php
class String implements Comparable
{
private $string;
function __construct($string)
{$this->string = $string;}
function compare(self $compare)
{return $this->string == $compare->string;}
}
class Integer implements Comparable
{
private $integer;
function __construct($int)
{$this->integer = $int;}
function compare(self $compare)
{return $this->integer == $compare->integer;}
}
?>
Comparing Integer with String will result in a fatal error, as it is not an instance of the same class:
<?php
$first_int = new Integer(3);
$second_int = new Integer(3);
$first_string = new String("foo");
$second_string = new String("bar");
var_dump($first_int->compare($second_int)); // bool(true)
var_dump($first_string->compare($second_string)); // bool(false)
var_dump($first_string->compare($second_int)); // Fatal Error
?>

vbolshov at rbc dot ru 10-Aug-2006 02:34


Consider the following:
[vbolshov@localhost tmp]$ cat t.php
<?php
error_reporting(E_ALL | E_STRICT);
interface i {
function f($arg);
}
class c implements i {
function f($arg, $arg2 = null)
{
}
}
?>
[vbolshov@localhost tmp]$ php t.php

[vbolshov@localhost tmp]$
PHP doesn't generate a Fatal Error in this case, although the method declaration in the class differs from that in the
interface. This situation doesn't seem good to me: I'd prefer classes being strictly bound to their interfaces.

spiritus.canis at gmail dot com 25-Oct-2005 10:45


Regarding the example by cyrille.berliat:
This is not a problem and is consistent with other languages. You'd just want to use inheritance like so:
<?php
class AbstractClass {
public function __ToString ( ) { return 'Here I am'; }
}
class DescendantClass extends AbstractClass {}
interface MyInterface {
public function Hello ( AbstractClass $obj );
}
class MyClassOne implements MyInterface {
public function Hello ( AbstractClass $obj ) {
echo $obj;
}
} // Will work as Interface Satisfied
$myDC = new DescendantClass() ;
MyClassOne::Hello( $myDC ) ;
?>

cyrille.berliat[no spam]free.fr 17-Oct-2005 02:29


Interfaces and Type Hinting can be used but not with Inherintance in the same time :
<?
class AbstractClass
{
public function __ToString ( ) { return 'Here I\'m I'; }
}
class DescendantClass extends AbstractClass
{
}
interface MyI
{
public function Hello ( AbstractClass $obj );
}
class MyClassOne implements MyI
{

public function Hello ( AbstractClass $obj )


{
echo $obj;
}
} // Will work as Interface Satisfied
class MyClassTwo implements MyI
{
public function Hello ( DescendantClass $obj )
{
echo $obj;
}
} // Will output a fatal error because Interfaces don't support Inherintance in TypeHinting
//Fatal error: Declaration of MyClassTwo::hello() must be compatible with that of MyI::hello()
?>
Something a little bit bad in PHP 5.0.4 :)

darealremco at msn dot com 02-Oct-2005 12:53


To two notes below: There is one situation where classes and interfaces can be used interchangeably. In function definitions
you can define parameter types to be classes or interfaces. If this was not so then there would not be much use for interfaces
at all.

warhog at warhog dot net 11-Aug-2005 08:35


on the post below:
An interface is in fact the same like an abstract class containing abstract methods, that's why interfaces share the same
namespace as classes and why therefore "real" classes cannot have the same name as interfaces.

marcus at synchromedia dot co dot uk 28-Jul-2005 04:11


Classes and interface names share a common name space, so you can't have a class and an interface with the same name, even
though the two can never be used ambiguously (i.e. there are no circumstances in which a class and an interface can be used
interchangeably). e.g. this will not work:
interface foo {
public function bling();
}
class foo implements foo {
public function bling() {
}
}
You will get a 'Cannot redeclare class' error, even though it's only been declared as a class once.

tobias_demuth at web dot de 04-May-2005 02:21


The statement, that you have to implement _all_ methods of an interface has not to be taken that seriously, at least if you
declare an abstract class and want to force the inheriting subclasses to implement the interface.
Just leave out all methods that should be implemented by the subclasses. But never write something like this:
<?php

interface Foo {
function bar();
}
abstract class FooBar implements Foo {
abstract function bar(); // just for making clear, that this
// method has to be implemented
}
?>
This will end up with the following error-message:
Fatal error: Can't inherit abstract function Foo::bar() (previously declared abstract in FooBar) in path/to/file on line
anylinenumber

erik dot zoltan at msn dot com 25-Feb-2005 10:43


When should you use interfaces? What are they good for?
Here are two examples.
1. Interfaces are an excellent way to implement reusability.
You can create a general interface for a number of situations
(such as a save to/load from disk interface.) You can then
implement the interface in a variety of different ways (e.g. for
formats such as tab delimited ASCII, XML and a database.)
You can write code that asks the object to "save itself to
disk" without having to worry what that means for the object
in question. One object might save itself to the database,
another to an XML and you can change this behavior over
time without having to rewrite the calling code.
This allows you to write reusable calling code that can work
for any number of different objects -- you don't need to know
what kind of object it is, as long as it obeys the common
interface.
2. Interfaces can also promote gradual evolution. On a
recent project I had some very complicated work to do and I
didn't know how to implement it. I could think of a "basic"
implementation but I knew I would have to change it later.
So I created interfaces in each of these cases, and created
at least one "basic" implementation of the interface that
was "good enough for now" even though I knew it would have
to change later.
When I came back to make the changes, I was able to create
some new implementations of these interfaces that added the
extra features I needed. Some of my classes still used
the "basic" implementations, but others needed the
specialized ones. I was able to add the new features to the
objects themselves without rewriting the calling code in most
cases. It was easy to evolve my code in this way because
the changes were mostly isolated -- they didn't spread all

over the place like you might expect.

mat.wilmots (at) wanadoo (dot) fr 20-Jan-2005 06:22


interfaces support multiple inheritance
<?php
interface SQL_Result extends SeekableIterator, Countable
{
// new stuff
}
abstract class SQL_Result_Common
{
// just because that's what one would do in reality, generic implementation
}
class SQL_Result_mysql extends SQL_Result_Common implements SQL_Result
{
// actual implementation
}
?>
This code raises a fatal error because SQL_Result_mysql doesn't implement the abstract methods of SeekableIterator (6) +
Countable (1)

russ dot collier at gmail dot com 28-Nov-2004 10:24


You can also specify class constants in interfaces as well (similar to specifying 'public static final' fields in Java
interfaces):
<?php
interface FooBar
{
const SOME_CONSTANT = 'I am an interface constant';
public function doStuff();
}
?>
Then you can access the constant by referring to the interface name, or an implementing class, (again similar to Java) e.g.:
<?php
class Baz implements FooBar
{
//....
}
print Baz::SOME_CONSTANT;

print FooBar::SOME_CONSTANT;
?>
Both of the last print statements will output the same thing: the value of FooBar::SOME_CONSTANT

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Traits
As of PHP 5.4.0, PHP implements a method of code reuse called Traits.
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce
some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several
independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is
defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance
and Mixins.
A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is
not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal
composition of behavior; that is, the application of class members without requiring inheritance.
Example #1 Trait example
<?php
traitezcReflectionReturnInfo{
functiongetReturnType(){/*1*/}
functiongetReturnDescription(){/*2*/}
}
classezcReflectionMethodextendsReflectionMethod{
useezcReflectionReturnInfo;
/*...*/
}
classezcReflectionFunctionextendsReflectionFunction{
useezcReflectionReturnInfo;
/*...*/
}
?>

Precedence
An inherited member from a base class is overridden by a member inserted by a Trait. The precedence order is
that members from the current class override Trait methods, which in return override inherited methods.
Example #2 Precedence Order Example
An inherited method from a base class is overridden by the method inserted into MyHelloWorld from the
SayWorld Trait. The behavior is the same for methods defined in the MyHelloWorld class. The precedence
order is that methods from the current class override Trait methods, which in turn override methods from
the base class.
<?php
classBase{
publicfunctionsayHello(){
echo'Hello';
}
}
traitSayWorld{
publicfunctionsayHello(){
parent::sayHello();
echo'World!';
}

}
classMyHelloWorldextendsBase{
useSayWorld;
}
$o=newMyHelloWorld();
$o->sayHello();
?>

The above example will output:


Hello World!

Example #3 Alternate Precedence Order Example


<?php
traitHelloWorld{
publicfunctionsayHello(){
echo'HelloWorld!';
}
}
classTheWorldIsNotEnough{
useHelloWorld;
publicfunctionsayHello(){
echo'HelloUniverse!';
}
}
$o=newTheWorldIsNotEnough();
$o->sayHello();
?>

The above example will output:


Hello Universe!

Multiple Traits
Multiple Traits can be inserted into a class by listing them in the use statement, separated by commas.
Example #4 Multiple Traits Usage
<?php
traitHello{
publicfunctionsayHello(){
echo'Hello';
}
}
traitWorld{
publicfunctionsayWorld(){
echo'World';
}
}

classMyHelloWorld{
useHello,World;
publicfunctionsayExclamationMark(){
echo'!';
}
}
$o=newMyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>

The above example will output:


Hello World!

Conflict Resolution
If two Traits insert a method with the same name, a fatal error is produced, if the conflict is not explicitly
resolved.
To resolve naming conflicts between Traits used in the same class, the insteadof operator needs to be used to
chose exactly one of the conflicting methods.
Since this only allows one to exclude methods, the as operator can be used to allow the inclusion of one of the
conflicting methods under another name.
Example #5 Conflict Resolution
In this example, Talker uses the traits A and B. Since A and B have conflicting methods, it defines to use the
variant of smallTalk from trait B, and the variant of bigTalk from trait A.
The Aliased_Talker makes use of the as operator to be able to use B's bigTalk implementation under an
additional alias talk.
<?php
traitA{
publicfunctionsmallTalk(){
echo'a';
}
publicfunctionbigTalk(){
echo'A';
}
}
traitB{
publicfunctionsmallTalk(){
echo'b';
}
publicfunctionbigTalk(){
echo'B';
}
}
classTalker{
useA,B{
B::smallTalkinsteadofA;
A::bigTalkinsteadofB;

}
}
classAliased_Talker{
useA,B{
B::smallTalkinsteadofA;
A::bigTalkinsteadofB;
B::bigTalkastalk;
}
}
?>

Changing Method Visibility


Using the as syntax, one can also adjust the visibility of the method in the exhibiting class.
Example #6 Changing Method Visibility
<?php
traitHelloWorld{
publicfunctionsayHello(){
echo'HelloWorld!';
}
}
//ChangevisibilityofsayHello
classMyClass1{
useHelloWorld{sayHelloasprotected;}
}
//Aliasmethodwithchangedvisibility
//sayHellovisibilitynotchanged
classMyClass2{
useHelloWorld{sayHelloasprivatemyPrivateHello;}
}
?>

Traits Composed from Traits


Just as classes can make use of traits, so can other traits. By using one or more traits in a trait definition, it can
be composed partially or entirely of the members defined in those other traits.
Example #7 Traits Composed from Traits
<?php
traitHello{
publicfunctionsayHello(){
echo'Hello';
}
}
traitWorld{
publicfunctionsayWorld(){
echo'World!';
}
}
traitHelloWorld{

useHello,World;
}
classMyHelloWorld{
useHelloWorld;
}
$o=newMyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>

The above example will output:


Hello World!

Abstract Trait Members


Traits support the use of abstract methods in order to impose requirements upon the exhibiting class.
Example #8 Express Requirements by Abstract Methods
<?php
traitHello{
publicfunctionsayHelloWorld(){
echo'Hello'.$this->getWorld();
}
abstractpublicfunctiongetWorld();
}
classMyHelloWorld{
private$world;
useHello;
publicfunctiongetWorld(){
return$this->world;
}
publicfunctionsetWorld($val){
$this->world=$val;
}
}
?>

Static Trait Members


Static variables can be referred to in trait methods, but cannot be defined by the trait. Traits can, however,
define static methods for the exhibiting class.
Example #9 Static Variables
<?php
traitCounter{
publicfunctioninc(){
static$c=0;
$c=$c+1;
echo"$c\n";
}
}

classC1{
useCounter;
}
classC2{
useCounter;
}
$o=newC1();$o->inc();//echo1
$p=newC2();$p->inc();//echo1
?>

Example #10 Static Methods


<?php
traitStaticExample{
publicstaticfunctiondoSomething(){
return'Doingsomething';
}
}
classExample{
useStaticExample;
}
Example::doSomething();
?>

Properties
Traits can also define properties.
Example #11 Defining Properties
<?php
traitPropertiesTrait{
public$x=1;
}
classPropertiesExample{
usePropertiesTrait;
}
$example=newPropertiesExample;
$example->x;
?>

If a trait defines a property then a class can not define a property with the same name, otherwise an error is
issued. It is an E_STRICT if the class definition is compatible (same visibility and initial value) or fatal error
otherwise.
Example #12 Conflict Resolution
<?php
traitPropertiesTrait{
public$same=true;
public$different=false;

}
classPropertiesExample{
usePropertiesTrait;
public$same=true;//StrictStandards
public$different=true;//Fatalerror
}
?>

User Contributed Notes

Traits

ryanhanekamp at yahoo dot com 10-May-2012 12:14


Using AS on a __construct method (and maybe other magic methods) is really, really bad. The problem is that is doesn't throw
any errors, at least in 5.4.0. It just sporadically resets the connection. And when I say "sporadically," I mean that arbitrary
changes in the preceding code can cause the browser connection to reset or not reset *consistently*, so that subsequent page
refreshes will continue to hang, crash, or display perfectly in the same fashion as the first load of the page after a change
in the preceding code, but the slightest change in the code can change this state. (I believe it is related to precise memory
usage.)
I've spent a good part of the day chasing down this one, and weeping every time commenting or even moving a completely
arbitrary section of code would cause the connection to reset. It was just by luck that I decided to comment the
"__construct as primitiveObjectConstruct"
line and then the crashes went away entirely.
My parent trait constructor was very simple, so my fix this time was to copy the functionality into the child __construct. I'm
not sure how I'll approach a more complicated parent trait constructor.

ryan at derokorian dot com 15-Apr-2012 02:03


Simple singleton trait.
<?php
trait singleton {
/**
* private construct, generally defined by using class
*/
//private function __construct() {}

public static function getInstance() {


static $_instance = NULL;
$class = __CLASS__;
return $_instance ?: $_instance = new $class;
}

public function __clone() {


trigger_error('Cloning '.__CLASS__.' is not allowed.',E_USER_ERROR);
}

public function __wakeup() {


trigger_error('Unserializing '.__CLASS__.' is not allowed.',E_USER_ERROR);
}
}

/**
* Example Usage
*/
class foo {
use singleton;

private function __construct() {


$this->name = 'foo';
}
}
class bar {
use singleton;

private function __construct() {


$this->name = 'bar';
}
}
$foo = foo::getInstance();
echo $foo->name;
$bar = bar::getInstance();
echo $bar->name;

Anonymous 27-Mar-2012 09:30


Traits can not implement interfaces.
(should be obvious, but tested is tested)

Safak Ozpinar / safakozpinar at gmail 18-Mar-2012 03:03


Unlike inheritance; if a trait has static properties, each class using that trait has independent instances of those
properties.
Example using parent class:
<?php
class TestClass {
public static $_bar;
}
class Foo1 extends TestClass { }
class Foo2 extends TestClass { }
Foo1::$_bar = 'Hello';
Foo2::$_bar = 'World';
echo Foo1::$_bar . ' ' . Foo2::$_bar; // Prints: World World
?>
Example using trait:
<?php
trait TestTrait {
public static $_bar;
}
class Foo1 {
use TestTrait;
}
class Foo2 {

use TestTrait;
}
Foo1::$_bar = 'Hello';
Foo2::$_bar = 'World';
echo Foo1::$_bar . ' ' . Foo2::$_bar; // Prints: Hello World
?>

Jason dot Hofer dot deletify dot this dot part at gmail dot com 14-Mar-2012 04:39
A (somewhat) practical example of trait usage.
Without traits:
<?php
class Controller {
/* Controller-specific methods defined here. */
}
class AdminController extends Controller {
/* Controller-specific methods inherited from Controller. */
/* Admin-specific methods defined here. */
}
class CrudController extends Controller {
/* Controller-specific methods inherited from Controller. */
/* CRUD-specific methods defined here. */
}
class AdminCrudController extends CrudController {
/* Controller-specific methods inherited from Controller. */
/* CRUD-specific methods inherited from CrudController. */
/* (!!!) Admin-specific methods copied and pasted from AdminController. */
}
?>
With traits:
<?php
class Controller {
/* Controller-specific methods defined here. */
}
class AdminController extends Controller {
/* Controller-specific methods inherited from Controller. */
/* Admin-specific methods defined here. */
}
trait CrudControllerTrait {
/* CRUD-specific methods defined here. */
}
class AdminCrudController extends AdminController {
use CrudControllerTrait;
/* Controller-specific methods inherited from Controller. */
/* Admin-specific methods inherited from AdminController. */
/* CRUD-specific methods defined by CrudControllerTrait. */

}
?>

farhad dot peb at gmail dot com 09-Mar-2012 07:29


<?php
trait first_trait
{
function first_function()
{
echo "From First Trait";
}
}

trait second_trait
{
function first_function()
{
echo "From Second Trait";
}
}

class first_class
{
use first_trait, second_trait
{
// This class will now call the method
// first function from first_trait only
first_trait::first_function insteadof second_trait;

// first_function of second_traits can be


// accessed with second_function
second_trait::first_function as second_function;

}
}

$obj = new first_class();


// Output: From First Trait
$obj->first_function();

// Output: From Second Trait


$obj->second_function();
?>
the iranian php programmer
writer: farhad zand
farhad.peb@gmail.com
php_engineer_bk@yahoo.com

anthony bishopric 03-Mar-2012 12:11


The magic method __call works as expected using traits.
<?php

trait Call_Helper{

public function __call($name, $args){


return count($args);
}
}
class Foo{
use Call_Helper;
}
$foo = new Foo();
echo $foo->go(1,2,3,4); // echoes 4

Edward 01-Mar-2012 03:29


The difference between Traits and multiple inheritance is in the inheritance part. A trait is not inherited from, but rather
included or mixed-in, thus becoming part of "this class". Traits also provide a more controlled means of resolving conflicts
that inevitably arise when using multiple inheritance in the few languages that support them (C++). Most modern languages are
going the approach of a "traits" or "mixin" style system as opposed to multiple-inheritance, largely due to the ability to
control ambiguities if a method is declared in multiple "mixed-in" classes.
Also, one can not "inherit" static member functions in multiple-inheritance.

greywire at gmail dot com 16-Feb-2012 07:12


The best way to understand what traits are and how to use them is to look at them for what they essentially are: language
assisted copy and paste.
If you can copy and paste the code from one class to another (and we've all done this, even though we try not to because its
code duplication) then you have a candidate for a trait.

chris dot rutledge at gmail dot com 21-Dec-2011 12:42


It may be worth noting here that the magic constant __CLASS__ becomes even more magical - __CLASS__ will return the name of the
class in which the trait is being used.
for example
<?php
trait sayWhere {
public function whereAmI() {
echo __CLASS__;
}
}
class Hello {
use sayWHere;
}
class World {
use sayWHere;
}
$a = new Hello;
$a->whereAmI(); //Hello
$b = new World;

$b->whereAmI(); //World
?>
The magic constant __TRAIT__ will giev you the name of the trait

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Overloading
Overloading in PHP provides means to dynamically "create" properties 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 properties 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 properties" 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.3.0

Added __callStatic(). Added warning to enforce public visibility and non-static declaration.

5.1.0

Added __isset() and __unset().

Property overloading
public
public
public
public

void __set ( string $name , mixed


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

$value

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


__get() is utilized for reading data from inaccessible properties.
__isset() is triggered by calling isset() or empty() on inaccessible properties.
__unset() is invoked when unset() is used on inaccessible properties.
The $name argument is the name of the property being interacted with. The __set() method's $value argument
specifies the value the $name'ed property should be set to.
Property overloading only works in object context. These magic methods will not be triggered in static context.
Therefore these methods should not be declared static. As of PHP 5.3.0, a warning is issued if one of the magic
overloading methods is declared static.
Note:
The return value of __set() is ignored because of the way PHP processes the assignment operator. Similarly,
__get() is never called when chaining assignments together like this:

$a = $obj->b = 8;

Note:
It is not possible to use overloaded properties in other language constructs than isset(). This means if
empty() is called on an overloaded property, the overloaded method is not called.
To workaround that limitation, the overloaded property must be copied into a local variable in the scope and
then be handed to empty().
Example #1 Overloading properties via the __get(), __set(), __isset() and __unset() methods
<?php
classPropertyTest
{
/**Locationforoverloadeddata.*/
private$data=array();
/**Overloadingnotusedondeclaredproperties.*/
public$declared=1;
/**Overloadingonlyusedonthiswhenaccessedoutsidetheclass.*/
private$hidden=2;
publicfunction__set($name,$value)
{
echo"Setting'$name'to'$value'\n";
$this->data[$name]=$value;
}
publicfunction__get($name)
{
echo"Getting'$name'\n";
if(array_key_exists($name,$this->data)){
return$this->data[$name];
}
$trace=debug_backtrace();
trigger_error(
'Undefinedpropertyvia__get():'.$name.
'in'.$trace[0]['file'].
'online'.$trace[0]['line'],
E_USER_NOTICE);
returnnull;
}
/**AsofPHP5.1.0*/
publicfunction__isset($name)
{
echo"Is'$name'set?\n";
returnisset($this->data[$name]);
}
/**AsofPHP5.1.0*/
publicfunction__unset($name)
{
echo"Unsetting'$name'\n";
unset($this->data[$name]);

}
/**Notamagicmethod,justhereforexample.*/
publicfunctiongetHidden()
{
return$this->hidden;
}
}

echo"<pre>\n";
$obj=newPropertyTest;
$obj->a=1;
echo$obj->a."\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo"\n";
echo$obj->declared."\n\n";
echo"Let'sexperimentwiththeprivatepropertynamed'hidden':\n";
echo"Privatesarevisibleinsidetheclass,so__get()notused...\n";
echo$obj->getHidden()."\n";
echo"Privatesnotvisibleoutsideofclass,so__get()isused...\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
Let's experiment with the private property named 'hidden':
Privates are visible inside the class, so __get() not used...
2
Privates not visible outside of class, so __get() is used...
Getting 'hidden'

Notice:

Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29

Method overloading
public mixed __call ( string $name , array $arguments )
public static 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 methods via the __call() and __callStatic() methods
<?php
classMethodTest
{
publicfunction__call($name,$arguments)
{
//Note:valueof$nameiscasesensitive.
echo"Callingobjectmethod'$name'"
.implode(',',$arguments)."\n";
}
/**AsofPHP5.3.0*/
publicstaticfunction__callStatic($name,$arguments)
{
//Note:valueof$nameiscasesensitive.
echo"Callingstaticmethod'$name'"
.implode(',',$arguments)."\n";
}
}
$obj=newMethodTest;
$obj->runTest('inobjectcontext');
MethodTest::runTest('instaticcontext');//AsofPHP5.3.0
?>

The above example will output:


Calling object method 'runTest' in object context
Calling static method 'runTest' in static context

User Contributed Notes

Overloading

theaceofthespade at gmail dot com 23-Mar-2012 09:35


A word of warning! It may seem obvious, but remember, when deciding whether to use __get, __set, and __call as a way to
access the data in your class (as opposed to hard-coding getters and setters), keep in mind that this will prevent any sort of
autocomplete, highlighting, or documentation that your ide mite do.
Furthermore, it beyond personal preference when working with other people. Even without an ide, it can be much easier to go
through and look at hardcoded member and method definitions in code, than having to sift through code and piece together the
method/member names that are assembled in __get and __set.
If you still decide to use __get and __set for everything in your class, be sure to include detailed comments and documenting,
so that the people you are working with (or the people who inherit the code from you at a later date) don't have to waste time
interpreting your code just to be able to use it.

_ at apakoh dot dk 16-Feb-2012 04:11


I find the following use of __set and __get useful:

<?php
class Post {
private $title;
private $content;
private $author;
private $comments;
private $_getters = array('title', 'content', 'author', 'comments');
private $_setters = array('title', 'content', 'author');

public function __get($property) {


if (in_array($property, $this->_setters)) {
return $this->$property;
}
else if (method_exists($this, '_get_' . $property))
return call_user_func(array($this, '_get_' . $property));
else if (in_array($property, $this->_getters) OR method_exists($this, '_set_' . $property))
throw new Exception('Property "' . $property . '" is write-only.');
else
throw new Exception('Property "' . $property . '" is not accessible.');
}
public function __set($property, $value) {
if (in_array($property, $this->_getters)) {
$this->$property = $value;
}
else if (method_exists($this, '_set_' . $property))
call_user_func(array($this, '_set_' . $property), $value);
else if (in_array($property, $this->_setters) OR method_exists($this, '_get_' . $property))
throw new Exception('Property "' . $property . '" is read-only.');
else
throw new Exception('Property "' . $property . '" is not accessible.');
}
}
?>
This way the variables in the $_getters array can be read from the outside and the variables in the $_setters array can be
modified from the outside, like this:
<?php
$post = new Post();
$post->title = 'Hello, World';
echo $post->title;
// The following will throw an exception since $comments is read-only:
$post->comments = 23;
?>
And in case you need a less generic getter or setter at some point, you can remove the variable from the $_getters or
$_setters array and implement a method like:
<?php
private function _set_title($value) {
$this->title = str_replace('World', 'Universe', $value);
}
?>
And from the outside the property could still be used with:

<?php
$post->title = 'Hello, World!';
?>
I've tried a couple of different ways of doing this, but this seems to be the fastest (although still around 2 times slower
than using ugly old school getter- and setter-methods).
Functions like property_exists() are unnecessary and only makes thing even slower (my initial attempt at using __set and __get
was up to 9 times slower than traditional getter/setter methods).
Could probably still be improved/changed in different ways depending on context.

Voitcus at wp dot pl 02-Nov-2011 12:57


If a class is being extended by another class, its __get and __set methods (and others) can also be overloaded themselves:
<?php
class A {
public function __get($value){
switch($value){
case "a1": return 1; break;
case "a2": return 2; break;
default: // error handler goes here
return "number out of range"; // or NULL or anything else
}
} // end of method __get
} // end of class A
class B extends A {
public function __get($value){
switch($value){
case "a1": return 11; break; // we overload value of 1
case "b3": return 3; break; // we add these new properties
case "b4": return 4; break;
default: // check ancestor's properties
return parent::__get($value);
}
} // end of method __get
} //end of class B
$a=new A();
$b=new B();
echo $a->a1; // produces 1
echo $a->a2; // produces 2
echo $a->b3; // produces number out of range
echo $b->a1; // produces 11
echo $b->a2; // produces 2
echo $b->b3; // produces 3
echo $b->b4; // produces 4
echo $b->b5; // produces number out of range
?>
If class B's default switch option is reached, the class A's getter is called. So the extending class B overloads property
"a1", adds its own properties "b3" and "b4", and inherits property "a2". This solution can't, however, overload class A's error
handler (the line with "number out of range").
Should it be needed, consider the following error handler of the class B:
<?php

default: // error handler goes here


$p=parent::__get($value);
if(!is_numeric($p)){
return "no value"; // overload class A's error message
}
else{
return $p; // return class A's base properties
}
?>
So we have new "error handler"
<?php
echo $b->b5; // produces no value
?>

ari at asu dot edu 31-Oct-2011 01:57


It may be important to note that when __set($name, $value) is called, $name gets entered into the symbol table for that call
stack. This means that if a property is set within __set, it will only work if that property's name appears in the call stack
(ie if it matches $name). If not, __set will be called again on the new property recursively.
<?php
class test
{
function __set($name, $value)
{
echo "__set($name, $value);\n";
$this->prop3 = $value; // This will call __set(prop3, value)
$this->prop2 = $value; // This will call __set(prop2, value)
$this->prop1 = $value; // This will NOT call __set(prop1, value) because $name == prop1.
}
}
$test = new test;
$test->prop1 = 'value';
?>
It could be thought of like this: within the function __set($name, $value), $this->[property name] = [value] will recurse
unless property name == $name. Within the call stack of __set, __set will never recurse on the same name twice. Once you leave
__set (without actually creating the property), the call stack ends and all bets are off.
What this means:
You cannot do things like setting an (uppercase) property to lowercase within __set without expecting __set to be called twice.
If you were to add an underscore to the property name, you can expect an infinite recursion loop.
I hope someone finds this useful. It drove me nuts for a few hours.

matt at mcmcms dot com 13-Oct-2011 05:31


If you need to try and imitate the functionality of the __get() and __set() magic methods whilst outside of the object-scope
(i.e. using a static method) this small __callStatic() implementation may help you out.
<?php
class config
{
private static $_propertyArray = array();

public static function __callStatic( $method, $args )


{
$property = $args[0];

switch( $method )
{
case 'set':
// set property
self::$_propertyArray[ $property ] = $args[1];
break;

case 'get':
// get property
if( isset( self::$_propertyArray[ $property ] ) )
{
return self::$_propertyArray[ $property ];
}
else {
throw new Exception( "Property ({$property}) does not exist", 0 );
}
break;

default:
// do nothing..
break;
}
}
}
config::set( 'my_property', 'someValue' );
print "The value of 'my_property' is: " . config::get( 'my_property' );
// Will output: The value of 'my_property' is: someValue
?>

dans at dansheps dot com 01-Aug-2011 08:38


Since this was getting me for a little bit, I figure I better pipe in here...
For nested calls to private/protected variables(probably functions too) what it does is call a __get() on the first object,
and if you return the nested object, it then calls a __get() on the nested object because, well it is protected as well.
EG:
<?php
class A
{
protected $B
public function __construct()
{
$this->B = new B();
}
public function __get($variable)
{
echo "Class A::Variable " . $variable . "\n\r";
$retval = $this->{$variable};

return $retval;
}
}
class B
{
protected $val
public function __construct()
{
$this->val = 1;
}
public function __get($variable)
{
echo "Class B::Variable " . $variable . "\n\r";
$retval = $this->{$variable};
return $retval;
}
}
$A = new A();
echo "Final Value: " . $A->B->val;
?>
That will return something like...
Class A::Variable B
Class B::Variable val
Final Value: 1
It seperates the calls into $A->B and $B->val
Hope this helps someone

jk at jankriedner dot de 07-Jun-2011 03:15


You should take care when using properties retrieved via __get() in functions that expect arguments to be passed by reference
(e.g. mysqli_stmt_bind_param). The reference is NOT set to the property itself, but to the value returned by __get().
Thus, binding a property retrieved via __get() to a statement will let the statement be executed always with the value the
property had when calling bind_param, not with the current value it has when calling execute().
E.g.:
<?php
error_reporting(E_ALL);
class foo {
protected $bar;

public function __construct() {


$this->bar = "Hello World!";
}
public static function factory() {
return new self;
}
public function __get($property) {
if(!property_exists($this,$property)) {
throw new InvalidArgumentException("Property {$property} doesn't exist");
}
return $this->$property;

}
public function setBar($value) {
$this->bar = $value;
}
}
$foo = new foo();
echo $foo->bar; // Ouputs: Hello World!
$db = new mysqli("localhost","root","","tests");
$sql = "INSERT INTO foo SET bar=?";
$res = $db->prepare($sql);
$res->bind_param("s",$foo->bar); // Notice: Indirect modification of overloaded property foo::$bar has no effect in
/var/www/overload.php on line 24
$res->execute(); // Writes "Hello World!" to database
$foo->setBar("Goodbye");
echo $foo->bar; // Outputs: Goodbye
$res->execute(); // Writes "Hello World!" to database
?>

Daniel Smith 23-May-2011 04:15


Be careful of __call in case you have a protected/private method. Doing this:
<?php
class TestMagicCallMethod {
public function foo()
{
echo __METHOD__.PHP_EOL;
}
public function __call($method, $args)
{
echo __METHOD__.PHP_EOL;
if(method_exists($this, $method))
{
$this->$method();
}
}

protected function bar()


{
echo __METHOD__.PHP_EOL;
}
private function baz()
{
echo __METHOD__.PHP_EOL;
}
}
$test = new TestMagicCallMethod();
$test->foo();
/**
* Outputs:
* TestMagicCallMethod::foo
*/
$test->bar();
/**
* Outputs:

* TestMagicCallMethod::__call
* TestMagicCallMethod::bar
*/
$test->baz();
/**
* Outputs:
* TestMagicCallMethod::__call
* TestMagicCallMethod::baz
*/
?>
..is probably not what you should be doing. Always make sure that the methods you call in __call are allowed as you probably
dont want all the private/protected methods to be accessed by a typo or something.

jan dot machala at email dot cz 15-Apr-2011 03:47


Example of usage __call() to have implicit getters and setters
<?php
class Entity {
public function __call($methodName, $args) {
if (preg_match('~^(set|get)([A-Z])(.*)$~', $methodName, $matches)) {
$property = strtolower($matches[2]) . $matches[3];
if (!property_exists($this, $property)) {
throw new MemberAccessException('Property ' . $property . ' not exists');
}
switch($matches[1]) {
case 'set':
$this->checkArguments($args, 1, 1, $methodName);
return $this->set($property, $args[0]);
case 'get':
$this->checkArguments($args, 0, 0, $methodName);
return $this->get($property);
case 'default':
throw new MemberAccessException('Method ' . $methodName . ' not exists');
}
}
}
public function get($property) {
return $this->$property;
}
public function set($property, $value) {
$this->$property = $value;
return $this;
}
protected function checkArguments(array $args, $min, $max, $methodName) {
$argc = count($args);
if ($argc < $min || $argc > $max) {
throw new MemberAccessException('Method ' . $methodName . ' needs minimaly ' . $min . ' and maximaly ' . $max . '
arguments. ' . $argc . ' arguments given.');
}
}
}
class MemberAccessException extends Exception{}

class Foo extends Entity {


protected $a;
}
$foo = new Foo();
$foo->setA('some'); // outputs some
echo $foo->getA();
class Bar extends Entity {
protected $a;
/**
* Custom setter.
*/
public function setA($a) {
if (!preg_match('~^[0-9a-z]+$~i', $a)) {
throw new MemberAccessException('A can be only alphanumerical');
}
$this->a = $a;
return $this;
}
}
$bar = new Bar();
$bar->setA('abc123'); // ok
$bar->setA('[]/*@...'); // throws exception
?>

dvessel 29-Mar-2011 05:46


A controlled way to chain the results of a method call onto a new property. I thought it was impossible to do cleanly but I
finally found a decent way of handling it.
<?php
class main {
public function newMember($value) {
return new sub($this, $value);
}
}
class sub {
protected $parent;
protected $value;
public function __construct($parent, $value) {
$this->parent = $parent;
$this->value = $value;
}
public function __get($name) {
$this->parent->$name = $this->value;
return $this;
}
public function __call($name, $args) {
// Invoke parent class.
return call_user_func_array(array($this->parent, $name), $args);
}
}

$object = new main();


$object->newMember('value for foo')->foo->newMember('value for bar')->bar;
print var_dump($object->foo);
print var_dump($object->bar);
// prints out "value for foo" and "value for bar".
?>
Without the secondary 'sub' class, the chaining can be unpredictable since it doesn't carry over any state information. This
way you can encapsulate the results into the supporting class and let it do the work.

Anonymous 19-Dec-2010 03:12


Using anon functions, you can allow your class methods to be declared after your class is already set. Though you cannot use a
class property as a function in any way (including for properties that are objects with their own __invoke() method) without
triggering a fatal error, there is a workaround using an array property to store all these anon functions...
<?php
class Test {
// generic class allowing dynamic addition of methods
public $anon_list = array(); // list of all custom added methods
function __call($fnc, $args) {return call_user_func_array($this->anon_list[$fnc], $args);}

function __set($name, $val) {$this->anon_list[$name] = $val;}

}
// Example adding a new custom method
$test = new Test;
$test->do_something = function ($var1, $var2) {echo "custom called with $var1 and $var2\n";};
$test->do_something('asdf', 'test');
?>
Unfortunately, without access to $this within the anon functions, it's not really useful. You can "use ($test)" in your anon
function, but that just makes it more complicated.

php at lanar dot com dot au 12-Jun-2010 05:39


Note that __isset is not called on chained checks.
If isset( $x->a->b ) is executed where $x is a class with __isset() declared, __isset() is not called.
<?php
class demo
{
var $id ;
function __construct( $id = 'who knows' )
{
$this->id = $id ;
}
function __get( $prop )

{
echo "\n", __FILE__, ':', __LINE__, ' ', __METHOD__, '(', $prop, ') instance ', $this->id ;
return new demo( 'autocreated' ) ; // return a class anyway for the demo
}
function __isset( $prop )
{
echo "\n", __FILE__, ':', __LINE__, ' ', __METHOD__, '(', $prop, ') instance ', $this->id ;
return FALSE ;
}
}
$x = new demo( 'demo' ) ;
echo "\n", 'Calls __isset() on demo as expected when executing isset( $x->a )' ;
$ret = isset( $x->a ) ;
echo "\n", 'Calls __get() on demo without call to __isset() when executing isset( $x->a->b )' ;
$ret = isset( $x->a->b ) ;
?>
Outputs
Calls __isset() on demo as expected when executing isset( $x->a )
C:\htdocs\test.php:31 demo::__isset(a) instance demo
Calls __get() on demo without call to __isset() when executing isset( $x->a->b )
C:\htdocs\test.php:26 demo::__get(a) instance demo
C:\htdocs\test.php:31 demo::__isset(b) instance autocreated

navarr at gtaero dot net 15-May-2010 01:25


If you want to make it work more naturally for arrays $obj->variable[] etc you'll need to return __get by reference.
<?php
class Variables
{
public function __construct()
{
if(session_id() === "")
{
session_start();
}
}
public function __set($name,$value)
{
$_SESSION["Variables"][$name] = $value;
}
public function &__get($name)
{
return $_SESSION["Variables"][$name];
}
public function __isset($name)
{
return isset($_SESSION["Variables"][$name]);
}
}
?>

~A! 27-Apr-2010 09:03


Dynamic getting-setting using __call and __callStatic
<?php

class A {
private $fields;
public function __call($func, $args) {
if (empty($args)) {
return $this->fields[$args[0]];
} else {
$this->$fields[$func] = $args[0];
}
}
?>
Or statically:
<?php
class foo {
static $vals;
public static function __callStatic($func, $args) {
if (!empty($args)) {
self::$vals[$func] = $args[0];
} else {
return self::$vals[$func];
}
}
}
?>
Which would allow you to say:
<?php
Foo::username('john');
print Foo::username(); // prints 'john'
?>

zzzzbov 26-Apr-2010 12:30


I've written a brief, generic function for __get() and __set() that works well implementing accessor and mutator functions.
This allows the programmer to use implicit accessor and mutator methods when working with attribute data.
<?php
class MyClass
{
private $degrees
public function __get($name)
{
$fn_name = 'get_' . $name;
if (method_exists($this, $fn_name))
{
return $this->$fn_name();
}
else
{
return null;
}

}
public function __set($name, $value)
{
$fn_name = 'set_' . $name;
if (method_exists($this, $fn_name))
{
$this->$fn_name($value);
}
}
private function get_degrees()
{
return $this->degrees;
}

private function set_degrees($value)


{
$this->degrees = $value % 360;
if ($degrees < 0) $this->degrees += 360;
}
}
?>

f4bi0_ at hotmail dot com 01-Apr-2010 01:12


TRICKY CHALLENGE: is there a way to check if $object->variable exists without automatically triggering the functionality of
__get in case the variable doesn't exist?
TRADITIONAL WAY:
<?php
$object = new someClass(); // imagine someClass uses the Magic Method "__get"
if($object->variable){
// do something
} else {
// "__get" has inevitably been triggered :-(
}
?>
Ok, above we have the conventional way to check if a variable exists inside the object, the problem is that sometimes we DON'T
WANT TO TRIGGER __GET in case the statement returns false!
ALTERNATIVE WAY:
<?php
if(array_key_exists( 'variable', get_object_vars($object) ) ){
// do something
} else {
// "__get" has no idea what is going on, i think it is still asleep :-)

}
?>
you can even turn this into a function or something

strata_ranger at hotmail dot com 07-Oct-2009 09:56


Combining two things noted previously:
1 - Unsetting an object member removes it from the object completely, subsequent uses of that member will be handled by magic
methods.
2 - PHP will not recursively call one magic method from within itself (at least for the same $name).
This means that if an object member has been unset(), it IS possible to re-declare that object member (as public) by creating
it within your object's __set() method, like this:
<?php
class Foo
{
function __set($name, $value)
{
// Add a new (public) member to this object.
// This works because __set() will not recursively call itself.
$this->$name= $value;
}
}
$foo = new Foo();
// $foo has zero members at this point
var_dump($foo);
// __set() will be called here
$foo->bar = 'something'; // Calls __set()
// $foo now contains one member
var_dump($foo);
// Won't call __set() because 'bar' is now declared
$foo->bar = 'other thing';
?>
Also be mindful that if you want to break a reference involving an object member without triggering magic functionality, DO NOT
unset() the object member directly. Instead use =& to bind the object member to any convenient null variable.

Franz 05-Oct-2009 10:59


It says in the documentation that assignment chaining does not work with the __set() function like this:
<?php
$a = $foo->b = 3;
?>
If you still want to make it work, I suppose you can just turn the variables around:

<?php
$foo->b = $a = 3;
?>

kexianbin at diyism dot com 21-Aug-2009 11:29


By using __call, we can use php as using jQuery:
<?php
//SoWork PHP Framework
define('this', mt_rand());
$o='so_work';
class cls_so_work
{function __call($fun, $pars)
{foreach ($pars as &$v)
{if ($v===this)
{$v=$this->val;
break;
}
}
$tmp=eval('return defined("'.$fun.'")?constant("'.$fun.'"):"'.$fun.'";');
$this->val=call_user_func_array($tmp, $pars);
return $this;
}
function cls_so_work($obj)
{$this->val=isset($obj)?$obj:null;
}
}
function so_work($obj)
{if (isset($obj))
{return new cls_so_work($obj);
}
else
{if (!isset($GLOABALS['so_work']))
{$GLOABALS['so_work']=new cls_so_work();
}
else
{$GLOABALS['so_work']->val=null;
}
return $GLOABALS['so_work'];
}
}
define('echo', 'my_echo');
function my_echo($obj)
{echo $obj;
return $obj;
}
$o('abcd')->substr(this, 2, 2)->strlen(this)->echo(this);
$o()->substr('abcd', 1, 3)->strlen(this)->echo(this);
?>

eric dot druid+php dot net at gmail dot com 01-Jul-2009 04:22
I needed to know from where a member variable was set from to determine visibility.
<?php

class foo {
private $data;
public function __set($name, $value) {
$trace = debug_backtrace();
if(!isset($trace[1]) || $trace[1]['object'] != $trace[0]['object']) {
die("Trying to set protected member '$name' from public scope.");
}
$data[$name] = $value;
}
}
?>

Anonymous 05-Jun-2009 03:54


It is possible to accomplish method polymorphism via PHP's __call method:
<?php
class Example{
public function __call($name, $arguments){
switch($name){
case 'foo':
switch(count($arguments)){
case 2:
echo 'You called "foo" with two arguments.<br>' . PHP_EOL;
break;
case 3:
echo 'You called "foo" with three arguments.<br>' . PHP_EOL;
break;
default:
echo 'Error: Invalid number of arguments to "foo."<br>' . PHP_EOL;
break;
}
break;
default:
echo "Error: Call to undefined function \"$name.\"<br>" . PHP_EOL;
}
}
}
$test = new Example;
$test->foo('bar', 'baz');
$test->foo('bar', 'baz', 'fez', 'fap');
$test->bar();
?>

troggy dot brains at gmx dot de 19-May-2009 12:17


Just another note about using __get() & __set() on array properties with PHP v5.2.0.
Took me quite a while to find out why I couldn't write an array property that was created via __set(). Now a few notes earlier
someone described a working solution using the ArrayObject-class. This does work, but has a big downside, you cannot expect
other programmers to know that they will be getting an instance of ArrayObject instead of a native array, and trying to do an
implode() on an ArrayObject will just not work. So, here is my solution to the problem:
<?php
class A {
private $properties = array();
public function __set($key, $value) {
if (is_array($value)) {

$this->$key = $value;
} else {
$this->properties[$key] = $value;
}
}
public function __get($key) {
if (array_key_exists($key, $this->properties)) {
return $this->properties[$key];
}
return null;
}
}
?>
The idea behind this is, that you can register new properties at any time from within a class without getting a warning or
some of that kind. Now, if you try to set a property from outside the class, the __set() method will be called and decides
whether to place the new property in the properties array or declare it as a new "native" property. When trying to get that
property, the __get() method will only be called if the property is not "native", which won't be the case for an array.
HTH

daevid at daevid dot com 14-May-2009 09:16


Here's a handy little routine to suggest properties you're trying to set that don't exist. For example:
Attempted to __get() non-existant property/variable 'operator_id' in class 'User'.
checking for operator and suggesting the following:
* id_operator
* operator_name
* operator_code
enjoy.
<?php
/**
* Suggests alternative properties should a __get() or __set() fail
*
* @param string $property
* @return string
* @author Daevid Vincent [daevid@daevid.com]
* @date 05/12/09
* @see __get(), __set(), __call()
*/
public function suggest_alternative($property)
{
$parts = explode('_',$property);
foreach($parts as $i => $p) if ($p == '_' || $p == 'id') unset($parts[$i]);
echo 'checking for <b>'.implode(', ',$parts)."</b> and suggesting the following:<br/>\n";
echo "<ul>";
foreach($this as $key => $value)
foreach($parts as $p)
if (stripos($key, $p) !== false) print '<li>'.$key."</li>\n";
echo "</ul>";

}
just put it in your __get() or __set() like so:
public function __get($property)
{
echo "<p><font color='#ff0000'>Attempted to __get() non-existant property/variable '".$property."' in class
'".$this->get_class_name()."'.</font><p>\n";
$this->suggest_alternative($property);
exit;
}
?>

niehztog 14-Feb-2009 10:59


If you got a parent class agregating(not inheriting) a number of child classes in an array, you can use the following to allow
calling methods of the parent object on agregated child objects:
<?php
class child {
public $holder = null;
public function __call($name, $arguments) {
if($this->holder instanceof parentClass && method_exists($this->holder, $name)) {
return call_user_func_array(array($this->holder, $name), $arguments);
}
else {
trigger_error();
}
}
}
class parentClass {
private $children = array();
function __construct() {
$this->children[0] = new child();
$this->children[0]->holder = $this;
}
function getChild($number) {
if(!isset($this->children[$number])) {
return false;
}
return $this->children[$number];
}
function test() {
return 'it works';
}
}
$parent = new parentClass();
$firstChild = $parent->getChild(0);
echo $firstChild->test(); //should output 'it works'
?>

jorge dot hebrard at gmail dot com 23-Dec-2008 04:55

This is a great way to give different permissions to parent classes.


<?php
class A{
private $b;
function foo(){
$this->b = new B;
echo $this->b->protvar;
}
}
class B extends A{
protected $protvar="protected var";
public function __get($nm) {
echo "Default $nm value";
}
}
$a = new A;
$b = new B;
$a->foo(); // prints "protected var"
echo $b->protvar; // prints "Default protvar value"
?>
This way, you can help parent classes to have more power with protected members.

Ant P. 21-Dec-2008 08:40


Be extra careful when using __call(): if you typo a function call somewhere it won't trigger an undefined function error, but
get passed to __call() instead, possibly causing all sorts of bizarre side effects.
In versions before 5.3 without __callStatic, static calls to nonexistent functions also fall through to __call!
This caused me hours of confusion, hopefully this comment will save someone else from the same.

erick2711 at gmail dot com 14-Nov-2008 07:33


<?php
/***********************************************
*And here follows a child class which implements a menu based in the 'nodoMenu' class (previous note).
*
*[]s
*
*erick2711 at gmail dot com
************************************************/
class menu extends nodoMenu{
private $cssc = array();

public function __toString(){ //Just to show, replace with something better.


$stringMenu = "<pre>\n";$stringMenu .= $this->strPrint();$stringMenu .= "</pre>\n";
return $stringMenu;
}
public function __construct($cssn = null){
parent::__construct();
if (isset($cssn) && is_array($cssn)){$this->cssc = $cssn;}
$this->buildMenu();
}

public function buildMenu(){


$this->add('server',
'Server',
'server.php');

$this->server->add('personalD',
'Personal Data',
'server/personal.php');
$this->server->add('personalI',
'Personal Interviews',
'server/personalI.php');
$this->server->personalI->add('detailsByIer',
'Detalis by Interviewer',
'server/personalI.php?tab=detailsByIer');
//(...)
return $this;
}
}
//Testing
$meuMenu = new menu;
echo $meuMenu;
/***********************************************
*Will output (to the browser):
*
*<pre>
*1 Server<br>
*1.1 Personal Data<br>
*1.2 Personal Interviews<br>
*1.2.1 Details by Interviewer<br>
*</pre>
*
*Which shows:
*
*1 Server
* 1.1 Personal Data
* 1.2 Personal Interviews
* 1.2.1 Details by Interviewer
************************************************/
?>

erick2711 at gmail dot com 14-Nov-2008 07:09


<?php
/*
Here folows a little improvement of the 'strafvollzugsbeamter at gmx dot de' code, allowing each node to hold both
'parameters' and 'child nodes', and differentiate $s->A->B->C ('FOO') from $s->A (same 'FOO', but shouldn't exist) and from
$s-A->B (idem).
This allows the class, using the interesting suggested syntax ($root->dad->child->attribute, in which 'dad's and 'child's
names are dynamically generated), to do something actually useful, like implementing a n-tree data structure (a menu, for
instance).
It was tested under PHP 5.2.6 / Windows.
I know that must there be something better which already do this (probably in the DOM Model classes, or something like),
but it was fun to develop this one, for the sake of studying the "magic" methods.
Its a compressed version of the code (no comments, too short variable names, almost no identation). I had to compress it in
order to add the note. If anyone cares about the full version, just email me.
[]s

erick2711 at gmail dot com


*/
class nodoMenu{
protected $p = array();
protected $c = array();

public function __construct($t = '', $uri = '', $css = null, $n = 0, $i=0){


$this->p['t'] = $t;$this->p['uri'] = $uri;$this->p['css'] = $css;$this->p['n'] = $n;$this->p['i'] = $i;$this>p['q'] = 0;return $this;
}
public function add($cn, $ct = '', $cl = '', $css = null){
$nc = new nodoMenu($ct, $cl, $css, $this->p['n'] + 1, $this->p['q']);$this->c[$cn] = $nc;$this->p['q'] += 1;return
$this->c[$cn];
}
private function isParameter($pn){
return array_key_exists($pn, $this->p);
}

public function __isset($pn){


if ($this->isParameter($pn)){return(!is_null($this->p[$pn]));}
else{return(array_key_exists($pn, $this->c));}
}
public function remove($cn){
if (array_key_exists($cn, $this->c)){$this->p['q'] -= 1;unset($this->c[$cn]);}
}
public function __unset($pn){
if ($this->isParameter($pn)){$this->p[$pn] = null;}
else{$this->remove($pn);}
}
public function __set($pn, $v){
$r = null;
if ($this->isParameter($pn)){$this->p[$pn] = $v;$r = $v;}
else{if (array_key_exists($pn, $this->c)){$this->c[$pn] = $v;$r = $this->c[$pn];}
else{$r = $this->add($pn);}}
return $r;
}
public function __get($pn){
$v = null;
if ($this->isParameter($pn)){$v = $this->p[$pn];}
else{if (array_key_exists($pn, $this->c)){$v = $this->c[$pn];}
else{$v = $this->add($pn);}}
return $v;
}

public function hasChilds(){


return(isset($this->c[0]));
}

public function child($i){


return $this->c[$i];
}

public function strPrint($bm = ''){ //Just to show, replace with something better.
$m = '';$r = '';$n = $this->p['n'];
if ($n > 0){switch($n){case 0:case 1: $qs = 0; break;case 2: $qs = 2; break;case 3: $qs = 6; break;case 4: $qs = 12;
break;case 5: $qs = 20; break;case 6: $qs = 30; break;case 7: $qs = 42; break;case 8: $qs = 56; break;}
$tab = str_repeat('&nbsp;', $qs);$r .= $tab;
if ($bm <> ''){$m = $bm.'.';}
$im = $this->p['i'] + 1;$m .= $im;$r .= $m.' ';$r .= $this->p['t']."<br>\n";

}
foreach ($this->c as $child){$r .= $child->strPrint($m);}
return $r;
}

public function __toString(){


return $this->strPrint();
}
}
?>

Ant P. 30-Aug-2008 07:01


There's nothing wrong with calling these functions as normal functions:
If you end up in a situation where you need to know the return value of your __set function, just write <?php $a = $obj>__set($var, $val); ?> instead of <?php $a = $obj->$var = $val; ?>.

strafvollzugsbeamter at gmx dot de 16-Jul-2008 12:57


The following works on my installation (5.2.6 / Windows):
<?php
class G
{
private $_p = array();

public function __isset($k)


{
return isset($this->_p[$k]);
}

public function __get($k)
{
$v = NULL;
if (array_key_exists($k, $this->_p))
{
$v = $this->_p[$k];
}
else
{
$v = $this->{$k} = $this;
}

return $v;
}

public function __set($k, $v)


{
$this->_p[$k] = $v;

return $this;
}
}
$s = new G();
$s->A->B->C = 'FOO';
$s->X->Y->Z = array ('BAR');

if (isset($s->A->B->C))
{
print($s->A->B->C);
}
else
{
print('A->B->C is NOT set');
}
if (isset($s->X->Y->Z))
{
print_r($s->X->Y->Z);
}
else
{
print('X->Y->Z is NOT set');
}
// prints: FOOArray ( [0] => BAR )
?>
... have fun and ...

Anonymous 30-Apr-2008 01:02


This is a generic implementation to use getter, setter, issetter and unsetter for your own classes.
<?php
abstract class properties
{
public function __get( $property )
{
if( ! is_callable( array($this,'get_'.(string)$property) ) )
throw new BadPropertyException($this, (string)$property);
return call_user_func( array($this,'get_'.(string)$property) );
}
public function __set( $property, $value )
{
if( ! is_callable( array($this,'set_'.(string)$property) ) )
throw new BadPropertyException($this, (string)$property);
call_user_func( array($this,'set_'.(string)$property), $value );
}

public function __isset( $property )


{
if( ! is_callable( array($this,'isset_'.(string)$property) ) )
throw new BadPropertyException($this, (string)$property);
return call_user_func( array($this,'isset_'.(string)$property) );
}
public function __unset( $property )
{
if( ! is_callable( array($this,'unset_'.(string)$property) ) )
throw new BadPropertyException($this, (string)$property);

call_user_func( array($this,'unset_'.(string)$property) );
}
}
?>

nospam michael AT netkey DOT at nospam 01-Apr-2008 10:10


you CAN write into ARRAYS by using __set and __get magic functions.
as has been mentioned before $obj->var['key'] = 'test'; does call the __get method of $obj, and there is no way to find out,
if the method has been called for setting purposes.
the solution is quite simple: use __get to return the array by reference. then you can write into it:
<?php
class setter{
private $_arr = array();
public function __set($name, $value){
$this->_arr[$name] = $value;
}
public function &__get($name){
if (isset($this->_arr[$name])){
return $this->_arr[$name];
} else return null;
}
}
?>

Matt Creenan 29-Feb-2008 08:34


PHP4 supports using __call but with a twist that I did not see mentioned anywhere on this page.
In 4, you must make the __call method signature with 3 parameters, the 3rd of which is the return value and must be declared
by-reference. Instead of using "return $value;" you would assign the 3rd argument to $value.
Example (both implementations below have the same result when run in the respective PHP versions:
<?php
// Will only work in PHP4
class Foo
{
function __call($method_name, $parameters, &$return_value)
{
$return_value = "Method $method_name was called with " . count($parameters) . " parameters";
}
}
// Will only work in PHP5
class Foo
{
function __call($method_name, $parameters)
{
return "Method $method_name was called with " . count($parameters) . " parameters";

}
}
?>

dave at mozaiq dot org 10-Feb-2008 03:58


Several users have mentioned ways to allow setting of array properties via magic methods. In particular, PHP calls the __get()
method instead of the __set() method when you try to do: $obj->prop['offset'] = $val.
The suggestions that I've read below all work, except that they do not allow you make properties read-only. After a bit of
struggling, I have found a solution. Essentially, if the property is supposed to be a read-only array, create an new
ArrayObject() out of it, then clone it and return the clone.
<?php
public function __get($var) {
if(isset($this->read_only_props[$var])) {
$ret = null;
if (is_array($this->read_only_props[$var]))
return clone new ArrayObject($this->read_only_props[$var]);
else if (is_object($this->read_only_props[$var]))
return clone $this->read_only_props[$var];
else
return $this->read_only_props[$var];
}
else if (!isset($this->writeable_props[$var]))
$this->writeable_props[$var] = NULL;
return $this->writeable_props[$var];
}
public function __set($var, $val) {
if (isset($this->read_only_props[$var]))
throw new Exception('tried to set a read only property on the event object');
return $this->writeable_props[$var] = $val;
}
?>
Note that __get() does not explicitly return by reference as many examples have suggested. Also, I have not found a way to
detect when __get() is being called for setting purposes, thus my code can not throw an exception when necessary in these
cases.

timshaw at mail dot NOSPAMusa dot com 28-Jan-2008 09:47


The __get overload method will be called on a declared public member of an object if that member has been unset.
<?php
class c {
public $p ;
public function __get($name) { return "__get of $name" ; }
}
$c = new c ;
echo $c->p, "\n" ; // declared public member value is empty
$c->p = 5 ;
echo $c->p, "\n" ; // declared public member value is 5
unset($c->p) ;
echo $c->p, "\n" ; // after unset, value is "__get of p"

?>

jj dhoT maturana aht gmail dhot com 25-Jan-2008 04:16


There isn't some way to overload a method when it's called as a reflection method:
<?php
class TestClass {
function __call($method, $args) {
echo "Method {$method} called with args: " . print_r($args, TRUE);
}
}
$class = new ReflectionClass("TestClass");
$method = $class->getMethod("myMehtod");
//Fatal error: Uncaught exception 'ReflectionException' with message 'Method myMethod' does not exist'
?>
Juan.

v dot umang at gmail dot com 11-Jan-2008 09:20


If you want to be able to overload a variable from within a class and this is your code:
<?php
class myClass
{
private $data;
public function __set($var, $val)
{
$this->data[$var] = $val;
}
public function __get($var)
{
$this->data[$var] = $val;
}
}
?>
There is a problem if you want to call these variables from within the class, as you you want to access data['data'] then you
can't say $this->data as it will return the array $data. Therefore a simple solution is to name the array $_data. So in your
__get and __set you will say $this->_data ... rather than $this->data. I.E:
<?php
class myClass
{
private $_data;
public function __set($var, $val)
{
$this->_data[$var] = $val;
}
public function __get($var)
{
$this->_data[$var] = $val;
}
}
?>

Umang

soldair at NOSPAM gmail.com 10-Jan-2008 09:21


the documentation states a falsehood:
"All overloading methods must be defined as public."
<?php
class test{
#################
#public use methods#
#################
public static function echoData(){
$obj = self::getInstance();
echo $obj->find('data');
return true;
}
######################
#only use a single instance#
######################
private static $instance;
private static function getInstance(){
if(!isset(self::$instance)){
self::$instance = new test;
}
return self::$instance;
}
#################
#private instantiation#
#################
private $data = array('data'=>'i am data');
private function __construct(){}
private function __call($nm,$args){
if(isset($this->data[$args[0]])){
return $this->data[$args[0]];
}
return null;
}
}
test::echoData();
?>
--------------OUTPUT--------------i am data
----------------------------------this test was run using PHP Version 5.2.4

Anonymous 09-Jan-2008 07:45


it should be noted that __call will trigger only for method calls on an instantiated object, and cannot be used to 'overload'
static methods. for example:
<?php
class TestClass {
function __call($method, $args) {

echo "Method {$method} called with args: " . print_r($args, TRUE);


}
}
// this will succeed
$obj = new TestClass();
$obj->method_doesnt_exist();
// this will not
TestClass::method_doesnt_exist();
?>
It would be useful if the PHP devs would include this in a future release, but in the meantime, just be aware of that pitfall.

egingell at sisna dot com 20-Dec-2007 07:54


The PHP devs aren't going to implement true overloading because: PHP is not strictly typed by any stretch of the imagination
(0, "0", null, false, and "" are the same, for example) and unlike Java and C++, you can pass as many values as you want to a
function. The extras are ignored unless you fetch them using func_get_arg(int) or func_get_args(), which is often how I
"overload" a function/method, and fewer than the declared number of arguments will generate an E_WARNING, which can be
suppressed by putting '@' before the function call, but the function will still run as if you had passed null where a value
was expected.
<?php
class someClass {
function whatever() {
$args = func_get_args();

// public boolean whatever(boolean arg1) in Java


if (is_bool($args[0])) {
// whatever(true);
return $args[0];

// public int whatever(int arg1, boolean arg2) in Java


} elseif(is_int($args[0]) && is_bool($args[1])) {
// whatever(1, false)
return $args[0];

} else {
// public void whatever() in Java
echo 'Usage: whatever([int], boolean)';
}
}
}
?>
// The Java version:
public class someClass {
public boolean whatever(boolean arg1) {
return arg1;
}

public int whatever(int arg1, boolean arg2) {


return arg1;
}

public void whatever() {


System.out.println("Usage: whatever([int], boolean)");

}
}

matthijs at yourmediafactory dot com 16-Dec-2007 11:09


While PHP does not support true overloading natively, I have to disagree with those that state this can't be achieved trough
__call.
Yes, it's not pretty but it is definately possible to overload a member based on the type of its argument. An example:
<?php
class A {

public function __call ($member, $arguments) {


if(is_object($arguments[0]))
$member = $member . 'Object';
if(is_array($arguments[0]))
$member = $member . 'Array';
$this -> $member($arguments);
}

private function testArray () {


echo "Array.";
}

private function testObject () {


echo "Object.";
}
}
class B {
}
$class = new A;
$class -> test(array()); // echo's 'Array.'
$class -> test(new B); // echo's 'Object.'
?>
Of course, the use of this is questionable (I have never needed it myself, but then again, I only have a very minimalistic C++
& JAVA background). However, using this general principle and optionally building forth on other suggestions a 'form' of
overloading is definately possible, provided you have some strict naming conventions in your functions.
It would of course become a LOT easier once PHP'd let you declare the same member several times but with different arguments,
since if you combine that with the reflection class 'real' overloading comes into the grasp of a good OO programmer. Lets keep
our fingers crossed!

anthony dot parsons at manx dot net 09-Nov-2007 02:57


You can't use __set to set arrays, but if you really want to, you can emulate it yourself:
<?php
class test {
public $x = array();
public $y = array();
function __set($var, $value)
{
if ( preg_match('/(.*)\[(.*)\]/', $var, $names) ) {
$this->y[$names[1]][$names[2]] = $value;
}
else {

$this->x[$var] = $value;
}
}
}
$z = new test;
$z->variable = 'abc';
$z->{'somearray[key]'} = 'def';
var_dump($z->x);
var_dump($z->y);
?>

php_is_painful at world dot real 19-Oct-2007 07:49


This is a misuse of the term overloading. This article should call this technique "interpreter hooks".

bgoldschmidt at rapidsoft dot de 28-Sep-2007 01:23


"These methods will only be triggered when your object or inherited object doesn't contain the member or method you're trying
to access."
is not quite correct:
they get called when the member you trying to access in not visible:
<?php
class test {
public $a;
private $b;
function __set($name, $value) {
echo("__set called to set $name to $value\n");
$this->$name = $value;
}
}
$t = new test;
$t->a = 'a';
$t->b = 'b';
?>
Outputs:
__set called to set b to b
Be aware that set ist not called for public properties

lokrain at gmail dot com 26-Sep-2007 02:05


Let us look at the following example:
<?php
class objDriver {
private $value;
public function __construct()
{
$value = 1;

}
public function doSomething($parameterList)
{
//We make actions with the value
}
}
class WantStaticCall {
private static $objectList;
private function __construct()
public static function init()
{
self::$objectList = array();
}
public static function register($alias)
{
self::$objectList[$alias] = new objDriver();
}
public static function __call($method, $arguments)
{
$alias = $arguments[0];
array_shift($arguments);
call_user_method($method, self::$objectList[$alias], $arguments);
}
}
// The deal here is to use following code:
WantStaticCall::register('logger');
WantStaticCall::doSomething('logger', $argumentList);
// and we will make objDriver to call his doSomething function with arguments
// $argumentList. This is not common pattern but very usefull in some cases.
// The problem here is that __call() cannot be static, Is there a way to work it around
?>

Typer85 at gmail dot com 18-Sep-2007 08:28


Just to clarify something the manual states about method overloading.
"All overloading methods must be defined as public."
As of PHP 5.2.2, this should be considered more of a coding convention rather than a requirement. In PHP 5.2.2, declaring a
__get or __set function with a visibility other than public, will be silently ignored by the parser and will not trigger a
parse error!
What is more, PHP will completely ignore the visibility modifier either of these functions are declared with and will always
treat them as if they were public.
I am not sure if this is a bug or not so to be on the safe side,
stick with always declaring them public.

egingell at sisna dot com 15-Sep-2007 05:12

Small vocabulary note: This is *not* "overloading", this is "overriding".


Overloading: Declaring a function multiple times with a different set of parameters like this:
<?php
function foo($a) {
return $a;
}
function foo($a, $b) {
return $a + $b;
}
echo foo(5); // Prints "5"
echo foo(5, 2); // Prints "7"
?>
Overriding: Replacing the parent class's method(s) with a new method by redeclaring it like this:
<?php
class foo {
function new($args) {
// Do something.
}
}
class bar extends foo {
function new($args) {
// Do something different.
}
}
?>

ac221 at sussex dot ac dot uk 01-Sep-2007 10:07


Just Noting the interesting behavior of __set __get , when modifying objects contained in overloaded properties.
<?php
class foo {
public $propObj;
public function __construct(){
$propObj = new stdClass();
}
public function __get($prop){
echo("I'm Being Got ! \n");
return $this->propObj->$prop;
}
public function __set($prop,$val){
echo("I'm Being Set ! \n");
$this->propObj->$prop = $val;
}
}
$test = new foo();
$test->barProp = new stdClass(); // I should invoke set
$test->barProp->barSubProp = 'As Should I';
$test->barProp->barSubProp = 'As Should I';
$test->barProp = new stdClass(); // As should i

?>
Outputs:
I'm Being Set !
I'm Being Got !
I'm Being Got !
I'm Being Set !
Whats happening, is PHP is acquiring a reference to the object, triggering __get; Then applying the changes to the object via
the reference.
Which is the correct behaviour; objects being special creatures, with an aversion to being cloned...
Unfortunately this will never invoke the __set handler, even though it is modifying a property within 'foo', which is slightly
annoying if you wanted to keep track of changes to an objects overloaded properties.
I guess Journaled Objects will have to wait till PHP 6 :)

stephen dot cuppett at webmastersinc dot net 16-Aug-2007 07:10


Please note, this example will not work on later PHP versions. You must return from __get() by reference using &__get()

php at sleep is the enemy dot co dot uk 23-Jul-2007 07:23


Just to reinforce and elaborate on what DevilDude at darkmaker dot com said way down there on 22-Sep-2004 07:57.
The recursion detection feature can prove especially perilous when using __set. When PHP comes across a statement that would
usually call __set but would lead to recursion, rather than firing off a warning or simply not executing the statement it will
act as though there is no __set method defined at all. The default behaviour in this instance is to dynamically add the
specified property to the object thus breaking the desired functionality of all further calls to __set or __get for that
property.
Example:
<?php
class TestClass{
public $values = array();

public function __get($name){


return $this->values[$name];
}

public function __set($name, $value){


$this->values[$name] = $value;
$this->validate($name);
}
public function validate($name){
/*
__get will be called on the following line
but as soon as we attempt to call __set
again PHP will refuse and simply add a
property called $name to $this
*/
$this->$name = trim($this->$name);

}
}
$tc = new TestClass();
$tc->foo = 'bar';
$tc->values['foo'] = 'boing';
echo '$tc->foo == ' . $tc->foo . '<br>';
echo '$tc ' . (property_exists($tc, 'foo') ? 'now has' : 'still does not have') . ' a property called "foo"<br>';
/*
OUPUTS:
$tc->foo == bar
$tc now has a property called "foo"
*/
?>

Adeel Khan 10-Jul-2007 01:18


Observe:
<?php
class Foo {
function __call($m, $a) {
die($m);
}
}
$foo = new Foo;
print $foo->{'wow!'}();
// outputs 'wow!'
?>
This method allows you to call functions with invalid characters.

alexandre at nospam dot gaigalas dot net 07-Jul-2007 10:59


PHP 5.2.1
Its possible to call magic methods with invalid names using variable method/property names:
<?php
class foo
{
function __get($n)
{
print_r($n);
}
function __call($m, $a)
{
print_r($m);
}
}

$test = new foo;


$varname = 'invalid,variable+name';
$test->$varname;
$test->$varname();
?>
I just don't know if it is a bug or a feature :)

BenBE at omorphia dot de 05-May-2007 10:48


While playing a bit with the __call magic method I found you can not emulate implementing methods of an interface as you might
think:
<?php
class Iteratable implements Iterator {
public function __call($funcname) {
if(in_array($funcname, array('current', 'next', /*...*/)) {
//Redirect the call or perform the actual action
}
}
}
?>
Using this code you'll get a "class Iteratable contains abstract methods ..." fatal error message. You'll ALWAYS have to
implement those routines by hand.

mafu at spammenot-mdev dot dk 24-Feb-2007 02:24


As a reply to james at thunder-removeme-monkey dot net, I found that there is a much simpler way to restore the behavior of
__get() to 5.1.x state; just force __get() to return by reference, like this:
<?php
class View {
/* Somewhere to store our overloaded properties */
private $v = array();
/* Store a new property */
function __set($varName, $varValue) {
$this->v[$varName] = $varValue;
}
/* Retrieve a property */
function & __get($varName) {
if(!isset($this->v[$varName])) {
$this->v[$varName] = NULL;
}
return $this->v[$varName];
}
}
?>
The only problem is that the code generates a notice if null is returned in __get(), because null cannot be returned by
reference. If somebody finds a solution, feel free to email me. :)
Cheers

james at thunder-removeme-monkey dot net 31-Jan-2007 01:07


Following up on the comment by "jstubbs at work-at dot co dot jp" and after reading "http://weierophinney.net/matthew/archives/
131-Overloading-arrays-in-PHP-5.2.0.html", the following methods handle property overloading pretty neatly and return variables
in read/write mode.
<?php
class View {
/* Somewhere to store our overloaded properties */
private $v = array();
/* Store a new property */
function __set($varName, $varValue) {
$this->v[$varName] = $varValue;
}
/* Retrieve a property */
function __get($varName) {
if(!isset($this->v[$varName])) {
$this->v[$varName] = NULL;
}
return is_array($this->v[$varName]) ? new ArrayObject($this->v[$varName]) : $this->v[$varName];
}
}
?>
This is an amalgm of previous solutions with the key difference being the use of ArrayObject in the return value. This is more
flexible than having to extend the whole class from ArrayObject.
Using the above class, we can do ...
<?php
$obj = new SomeOtherObject();
$view = new View();
$view->list = array();
$view->list[] = "hello";
$view->list[] = "goat";
$view->list[] = $group;
$view->list[] = array("a", "b", "c");
$view->list[3][] = "D";
$view->list[2]->aprop = "howdy";
/*
$view->list now contains:
[0] => "hello"
[1] => "goat"
[2] => SomeOtherObject { aprop => "howdy" }
[3] => array("a", "b", "c", "D")
and
$obj === $view->list[2] // equates to TRUE
*/
?>

mhherrera31 at hotmail dot com 25-Nov-2006 10:11


example for read only properties in class object. Lets you manage read only properties with var names like $ro_var.

The property must be PRIVATE, otherwise the overload method __get doesn't be called.
<?php
class Session {
private $ro_usrName;
function __construct (){
$this->ro_usrName = "Marcos";
}
function __set($set, $val){
if(property_exists($this,"ro_".$set))
echo "The property '$set' is read only";
else
if(property_exists($this,$set))
$this->{$set}=$val;
else
echo "Property '$set' doesn't exist";
}
function __get{$get}{
if(property_exists($this,"ro_".$get))
return $this->{"ro_".$get};
else
if(property_exists($this,$get))
return $this->{$get};
else
echo "Property '$get' doesn't exist";
}
}
?>

MagicalTux at ooKoo dot org 06-Sep-2006 02:35


Since many here probably wanted to do real overloading without having to think too much, here's a generic __call() function
for those cases.
Little example :
<?php
class OverloadedClass {
public function __call($f, $p) {
if (method_exists($this, $f.sizeof($p))) return call_user_func_array(array($this, $f.sizeof($p)), $p);
// function does not exists~
throw new Exception('Tried to call unknown method '.get_class($this).'::'.$f);
}
function Param2($a, $b) {
echo "Param2($a,$b)\n";
}
function Param3($a, $b, $c) {
echo "Param3($a,$b,$c)\n";
}
}
$o = new OverloadedClass();
$o->Param(4,5);
$o->Param(4,5,6);
$o->ParamX(4,5,6,7);

?>
Will output :
Param2(4,5)
Param3(4,5,6)
Fatal error: Uncaught exception 'Exception' with message 'Tried to call unknown method OverloadedClass::ParamX' in
overload.php:7
Stack trace:
#0 [internal function]: OverloadedClass->__call('ParamX', Array)
#1 overload.php(22): OverloadedClass->ParamX(4, 5, 6, 7)
#2 {main}
thrown in overload.php on line 7

jstubbs at work-at dot co dot jp 02-Sep-2006 09:12


<?php $myclass->foo['bar'] = 'baz'; ?>
When overriding __get and __set, the above code can work (as expected) but it depends on your __get implementation rather than
your __set. In fact, __set is never called with the above code. It appears that PHP (at least as of 5.1) uses a reference to
whatever was returned by __get. To be more verbose, the above code is essentially identical to:

<?php
$tmp_array = &$myclass->foo;
$tmp_array['bar'] = 'baz';
unset($tmp_array);
?>
Therefore, the above won't do anything if your __get implementation resembles this:
<?php
function __get($name) {
return array_key_exists($name, $this->values)
? $this->values[$name] : null;
}
?>
You will actually need to set the value in __get and return that, as in the following code:
<?php
function __get($name) {
if (!array_key_exists($name, $this->values))
$this->values[$name] = null;
return $this->values[$name];
}
?>

mnaul at nonsences dot angelo dot edu 11-Jul-2006 12:58


This is just my contribution. It based off of many diffrent suggestions I've see thought the manual postings.
It should fit into any class and create default get and set methods for all you member variables. Hopfuly its usefull.
<?php
public function __call($name,$params)
{
if( preg_match('/(set|get)(_)?/',$name) )
{
if(substr($name,0,3)=="set")
{

$name = preg_replace('/set(_)?/','',$name);
if(property_exists(__class__,$name))
{
$this->{$name}=array_pop($params);
return true;
}
else
{
//call to class error handler
return false;
}
return true;
}
elseif(substr($name,0,3)=="get")
{
$name = preg_replace('/get(_)?/','',$name);
if(property_exists(__class__,$name) )
{
return $this->{$name};
}
else
{
//call to class error handler
return false;
}
}
else
{
//call to class error handler
return false;
}
}
else
{
die("method $name dose not exist\n");
}
return false;
}

me at brenthagany dot com 12-Apr-2006 10:52


Regarding the post by TJ earlier, about the problems extending DOMElement. Yes, it is true that you can't set
extDOMElement::ownerDocument directly; however, you could append the extDOMElement to a DOMDocument in __construct(), which
indirectly sets ownerDocument. It should work something like so:
<?php
class extDOMElement extends DOMElement {
public function __construct(DOMDocument $doc) {
$doc->appendChild($this); //extDOMElement::ownerDocument is now equal to the object that $doc points to
}
}
?>
Now, I admit I've never actually needed to do this, but I see no reason why it shouldn't work.

Sleepless 23-Feb-2006 11:22

Yet another way of providing support for read-only properties. Any property that has
"pri_" as a prefix will NOT be returned, period, any other property will be returned
and if it was declared to be "protected" or "private" it will be read-only. (scope dependent of course)
<?php
function __get($var){
if (property_exists($this,$var) && (strpos($var,"pri_") !== 0) )
return $this->{$var};
else
//Do something
}
?>

Eric Lafkoff 21-Feb-2006 10:56


If you're wondering how to create read-only properties for your class, the __get() and __set() functions are what you're
looking for. You just have to create the framework and code to implement this functionality.
Here's a quick example I've written. This code doesn't take advantage of the "type" attribute in the properties array, but is
there for ideas.
<?php
class Test {

private $p_arrPublicProperties = array(


"id" => array("value" => 4,
"type" => "int",
"readonly" => true),
"datetime" => array("value" => "Tue 02/21/2006 20:49:23",
"type" => "string",
"readonly" => true),
"data" => array("value" => "foo",
"type" => "string",
"readonly" => false)
);
private function __get($strProperty) {
//Get a property:
if (isset($this->p_arrPublicProperties[$strProperty])) {
return $this->p_arrPublicProperties[$strProperty]["value"];
} else {
throw new Exception("Property not defined");
return false;
}
}

private function __set($strProperty, $varValue) {


//Set a property to a value:
if (isset($this->p_arrPublicProperties[$strProperty])) {
//Check if property is read-only:
if ($this->p_arrPublicProperties[$strProperty]["readonly"]) {
throw new Exception("Property is read-only");
return false;
} else {
$this->p_arrPublicProperties[$strProperty]["value"] = $varValue;
return true;
}
} else {

throw new Exception("Property not defined");


return false;
}
}

private function __isset($strProperty) {


//Determine if property is set:
return isset($this->p_arrPublicProperties[$strProperty]);
}

private function __unset($strProperty) {


//Unset (remove) a property:
unset($this->p_arrPublicProperties[$strProperty]);
}

}
$objTest = new Test();
print $objTest->data . "\n";
$objTest->data = "bar"; //Works.
print $objTest->data;
$objTest->id = 5; //Error: Property is read-only.
?>

derek-php at seysol dot com 10-Feb-2006 12:08


Please note that PHP5 currently doesn't support __call return-by-reference (see PHP Bug #30959).
Example Code:
<?php
class test {
public function &__call($method, $params) {
// Return a reference to var2
return $GLOBALS['var2'];
}
public function &actual() {
// Return a reference to var1
return $GLOBALS['var1'];
}
}
$obj = new test;
$GLOBALS['var1'] = 0;
$GLOBALS['var2'] = 0;
$ref1 =& $obj->actual();
$GLOBALS['var1']++;
echo "Actual function returns: $ref1 which should be equal to " . $GLOBALS['var1'] . "<br/>\n";
$ref2 =& $obj->overloaded();

$GLOBALS['var2']++;
echo "Overloaded function returns: $ref2 which should be equal to " . $GLOBALS['var2'] . "<br/>\n";
?>

PHP at jyopp dotKomm 22-Dec-2005 11:01


Here's a useful class for logging function calls. It stores a sequence of calls and arguments which can then be applied to
objects later. This can be used to script common sequences of operations, or to make "pluggable" operation sequences in header
files that can be replayed on objects later.
If it is instantiated with an object to shadow, it behaves as a mediator and executes the calls on this object as they come
in, passing back the values from the execution.
This is a very general implementation; it should be changed if error codes or exceptions need to be handled during the Replay
process.
<?php
class MethodCallLog {
private $callLog = array();
private $object;

public function __construct($object = null) {


$this->object = $object;
}
public function __call($m, $a) {
$this->callLog[] = array($m, $a);
if ($this->object) return call_user_func_array(array(&$this->object,$m),$a);
return true;
}
public function Replay(&$object) {
foreach ($this->callLog as $c) {
call_user_func_array(array(&$object,$c[0]), $c[1]);
}
}
public function GetEntries() {
$rVal = array();
foreach ($this->callLog as $c) {
$rVal[] = "$c[0](".implode(', ', $c[1]).");";
}
return $rVal;
}
public function Clear() {
$this->callLog = array();
}
}
$log = new MethodCallLog();
$log->Method1();
$log->Method2("Value");
$log->Method1($a, $b, $c);
// Execute these method calls on a set of objects...
foreach ($array as $o) $log->Replay($o);
?>

trash80 at gmail dot com 03-Dec-2005 08:59


Problem: $a->b->c(); when b is not instantiated.

Answer: __get()
<?php
class a
{
function __get($v)
{
$this->$v = new $v;
return $this->$v;
}
}
class b
{
function say($word){
echo $word;
}
}
$a = new a();
$a->b->say('hello world');
// echos 'hello world'
?>

TJ <php at tjworld dot net> 03-Nov-2005 10:11


Using the getter/setter methods to provide read-only access to object properties breaks the conventional understanding of
inheritence.
A super class using __set() to make a property read-only cannot be properly inherited because the visible (read-only) property
- with conventional public or protected visibility - cannot be set in the sub-class.
The sub-class cannot overload the super class's __set() method either, and therefore the inheritence is severely compromised.
I discovered this issue while extending DOMDocument and particularly DOMElement.
When extDOMDocument->createElement() creates a new extDOMElement, extDOMElement->__construct() can't set the extDOMElement>ownerDocument property because it's read-only.
DOMElements are totally read-only if they do not have an ownerDocument, and there's no way to set it in this scenario, which
makes inheritence pretty pointless.

seufert at gmail dot com 01-Nov-2005 04:25


This allows you to seeminly dynamically overload objects using plugins.
<?php
class standardModule{}
class standardPlugModule extends standardModule
{
static $plugptrs;
public $var;
static function plugAdd($name, $mode, $ptr)
{
standardPlugModule::$plugptrs[$name] = $ptr;
}

function __call($fname, $fargs)


{ print "You called __call($fname)\n";
$func = standardPlugModule::$plugptrs[$fname];
$r = call_user_func_array($func, array_merge(array($this),$fargs));
print "Done: __call($fname)\n";
return $r;
}
function dumpplugptrs() {var_dump(standardPlugModule::$plugptrs); }
}
class a extends standardPlugModule
{ function text() { return "Text"; } }
//Class P contained within a seperate file thats included
class p
{ static function plugin1($mthis, $r)
{ print "You called p::plugin1\n";
print_r($mthis);
print_r($r);
}
} a::plugAdd('callme', 0, array('p','plugin1'));
//Class P contained within a seperate file thats included
class p2
{ static function plugin2($mthis, $r)
{ print "You called p2::plugin2\n";
$mthis->callme($r);
}
} a::plugAdd('callme2', 0, array('p2','plugin2'));
$t = new a();
$testr = array(1,4,9,16);
print $t->text()."\n";
$t->callme2($testr);
//$t->dumpplugptrs();
?>
Will result in:
---------Text
You called __call(callme2)
You called p2::plugin2
You called __call(callme)
You called p::plugin1
a Object
(
[var] =>
)
Array
(
[0] => 1
[1] => 4
[2] => 9
[3] => 16
)
Done: __call(callme)
Done: __call(callme2)
---------This also clears up a fact that you can nest __call() functions, you could use this to get around the limits to __get() not

being able to be called recursively.

26-Aug-2005 07:32
To those who wish for "real" overloading: there's not really any advantage to using __call() for this -- it's easy enough with
func_get_args(). For example:
<?php
class Test
{

public function Blah()
{

$args = func_get_args();

switch (count($args))
{
case 1: /* do something */ break;
case 2: /* do something */ break;
}

}

}
?>

NOTE: getter cannot call getter 04-Aug-2005 12:37


By Design (http://bugs.php.net/bug.php?id=33998) you cannot call a getter from a getter or any function triggered by a getter:
<?php
class test
{
protected $_a = 6;
function __get($key) {
if($key == 'stuff') {
return $this->stuff();
} else if($key == 'a') {
return $this->_a;
}
}
function stuff()
{
return array('random' => 'key', 'using_getter' => 10 * $this->a);
}
}
$test = new test();
print 'this should be 60: '.$test->stuff['using_getter'].'<br/>'; // prints "this should be 60: 0"
// [[ Undefined property: test::$a ]] on /var/www/html/test.php logged.
print 'this should be 6: '.$test->a.'<br/>'; // prints "this should be 6: 6"
?>

06-May-2005 03:50
Please note that PHP5's overloading behaviour is not compatible at all with PHP4's overloading behaviour.

Marius 02-May-2005 02:15


for anyone who's thinking about traversing some variable tree
by using __get() and __set(). i tried to do this and found one
problem: you can handle couple of __get() in a row by returning
an object which can handle consequential __get(), but you can't
handle __get() and __set() that way.
i.e. if you want to:
<?php
print($obj->val1->val2->val3); // three __get() calls
?> - this will work,
but if you want to:
<?php
$obj->val1->val2 = $val; // one __get() and one __set() call
?> - this will fail with message:
"Fatal error: Cannot access undefined property for object with
overloaded property access"
however if you don't mix __get() and __set() in one expression,
it will work:
<?php
$obj->val1 = $val; // only one __set() call
$val2 = $obj->val1->val2; // two __get() calls
$val2->val3 = $val; // one __set() call
?>
as you can see you can split __get() and __set() parts of
expression into two expressions to make it work.
by the way, this seems like a bug to me, will have to report it.

ryo at shadowlair dot info 22-Mar-2005 10:22


Keep in mind that when your class has a __call() function, it will be used when PHP calls some other magic functions. This can
lead to unexpected errors:
<?php
class TestClass {
public $someVar;
public function __call($name, $args) {
// handle the overloaded functions we know...
// [...]
// raise an error if the function is unknown, just like PHP would
trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
}
}
$obj = new TestClass();
$obj->someVar = 'some value';
echo $obj; //Fatal error: Call to undefined function: TestClass::__tostring().
$serializedObj = serialize($obj); // Fatal error: Call to undefined function: TestClass::__sleep().
$unserializedObj = unserialize($someSerializedTestClassObject); // Fatal error: Call to undefined function:

TestClass::__wakeup().
?>

thisisroot at gmail dot com 18-Feb-2005 07:27


You can't mix offsetSet() of the ArrayAccess interface (http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html) and
__get() in the same line.
Below, "FileManagerPrefs" is an object of class UserData which implements ArrayAccess. There's a protected array of UserData
objects in the User class, which are returned from __get().
<?php
// This produces an error...
Application::getInstance()->user->FileManagerPrefs[ 'base'] = 'uploads/jack';
?>
Creates this error:
Fatal error: Cannot access undefined property for object with overloaded property access in __FILE__ on line __LINE__
However, __get() and offsetGet() play deceptively well together.
<?php
// This works fine!
echo Application::getInstance()->user->FileManager['base'];
?>
I guess it's a dereferencing issue with __get(). In my case, it makes more sense to have a middle step (user>data['FileManager']['base']), but I wanted to tip off the community before I move on.

mileskeaton at gmail dot com 23-Dec-2004 12:23


<?php
## THE PROBLEM: Class with lots of attributes.
## You want to use $o->getVarName() or $o->get_varname() style getters
## Some attributes have custom get functions, but the rest don't
## THE SOLUTION: __call
class Person
{
## this top stuff is just an example. could be anything.
private $name;
private $age;
private $weight;
function __construct($name, $age, $weight)
{
$this->name = $name;
$this->age = $age;
$this->weight = $weight;
}
## PORTABLE: use this __call function in any class
function __call($val, $x)
{
# see if they're calling a getter method - and try to guess the variable requested
if(substr($val, 0, 4) == 'get_')
{
$varname = substr($val, 4);

}
elseif(substr($val, 0, 3) == 'get')
{
$varname = substr($val, 3);
}
else
{
die("method $val does not exist\n");
}
# now see if that variable exists:
foreach($this as $class_var=>$class_var_value)
{
if(strtolower($class_var) == strtolower($varname))
{
return $class_var_value;
}
}
return false;
}
# IMPORTANT: you can keep some things private - or treat
# some vars differently by giving them their own getter method
# See how this function lies about Person's weight.
function getWeight()
{
return intval($this->weight * .8);
}
}
$a = new Person('Miles', 35, 200);
# these all work (case-insensitive):
print $a->get_name() . "\n";
print $a->getName() . "\n";
print $a->get_Name() . "\n";
print $a->getname() . "\n";
print $a->get_age() . "\n";
print $a->getAge() . "\n";
print $a->getage() . "\n";
print $a->get_Age() . "\n";
# defined functions still override the __call
print $a->getWeight() . "\n";
# trying to get something that doesn't exist returns false
print $a->getNothing();
# this still gets error:
print $a->hotdog();
?>

richard dot quadling at bandvulc dot co dot uk 26-Nov-2004 05:54


<?php
abstract class BubbleMethod
{

public $objOwner;
function __call($sMethod, $aParams)
{
// Has the Owner been assigned?
if (isset($this->objOwner))
{
return call_user_func_array(array($this->objOwner, $sMethod), $aParams);
}
else
{
echo 'Owner for ' . get_class($this) . ' not assigned.';
}
}
}
class A_WebPageContainer
{
private $sName;

public function __construct($sName)


{
$this->sName = $sName;
}

public function GetWebPageContainerName()


{
return $this->sName;
}
}
class A_WebFrame extends BubbleMethod
{
private $sName;

public function __construct($sName)


{
$this->sName = $sName;
}

public function GetWebFrameName()


{
return $this->sName;
}
}
class A_WebDocument extends BubbleMethod
{
private $sName;

public function __construct($sName)


{
$this->sName = $sName;
}

public function GetWebDocumentName()


{
return $this->sName;
}
}

class A_WebForm extends BubbleMethod


{
private $sName;

public function __construct($sName)


{
$this->sName = $sName;
}

public function GetWebFormName()


{
return $this->sName;
}
}
class A_WebFormElement extends BubbleMethod
{
private $sName;

public function __construct($sName)


{
$this->sName = $sName;
}

public function GetWebFormElementName()


{
return $this->sName;
}
}
$objWPC = new A_WebPageContainer('The outer web page container.');
$objWF1 = new A_WebFrame('Frame 1');
$objWF1->objOwner = $objWPC;
$objWF2 = new A_WebFrame('Frame 2');
$objWF2->objOwner = $objWPC;
$objWD1 = new A_WebDocument('Doc 1');
$objWD1->objOwner = $objWF1;
$objWD2 = new A_WebDocument('Doc 2');
$objWD2->objOwner = $objWF2;
$objWFrm1 = new A_WebForm('Form 1');
$objWFrm1->objOwner = $objWD1;
$objWFrm2 = new A_WebForm('Form 2');
$objWFrm2->objOwner = $objWD2;
$objWE1 = new A_WebFormElement('Element 1');
$objWE1->objOwner = $objWFrm1;
$objWE2 = new A_WebFormElement('Element 2');
$objWE2->objOwner = $objWFrm1;
$objWE3 = new A_WebFormElement('Element 3');
$objWE3->objOwner = $objWFrm2;

$objWE4 = new A_WebFormElement('Element 4');


$objWE4->objOwner = $objWFrm2;
echo "The name of the form that '" . $objWE1->GetWebFormElementName() . "' is in is '" . $objWE1->GetWebFormName() . "'<br
/>";
echo "The name of the document that '" . $objWE2->GetWebFormElementName() . "' is in is '" . $objWE2->GetWebDocumentName().
"'<br />";
echo "The name of the frame that '" . $objWE3->GetWebFormElementName() . "' is in is '" . $objWE3->GetWebFrameName(). "'<br
/>";
echo "The name of the page container that '" . $objWE4->GetWebFormElementName() . "' is in is '" .$objWE4>GetWebPageContainerName(). "'<br />";
?>
Results in.
The name of the form that 'Element 1' is in is 'Form 1'
The name of the document that 'Element 2' is in is 'Doc 1'
The name of the frame that 'Element 3' is in is 'Frame 2'
The name of the page container that 'Element 4' is in is 'The outer web page container.'
By using the abstract BubbleMethod class as the starting point for further classes that are contained inside others (i.e.
elements on a form are contained in forms, which are contained in documents which are contained in frames which are contained
in a super wonder global container), you can find properties of owner without knowing their direct name.
Some work needs to be done on what to do if no method exists though.

xorith at gmail dot com 06-Oct-2004 07:40


A few things I've found about __get()...
First off, if you use $obj->getOne->getAnother, both intended to be resolved by __get, the __get() function only sees the
first one at first. You can't access the second one. You can, however, return the pointer to an object that can handle the
second one. In short, you can have the same class handle both by returning a new object with the data changed however you see
fit.
Secondly, when using arrays like: $obj->getArray["one"], only the array name is passed on to __get. However, when you return
the array, PHP treats it just as it should. THat is, you'd have to make an array with the index of "one" in __get in order to
see any results. You can also have other indexes in there as well.
Also, for those of you like me, I've already tried to use func_get_args to see if you can get more than just that one.
If you're like me and were hoping you could pass some sort of argument onto __get in order to help gather the correct data,
you're out of look. I do recommend using __call though. You could easily rig __call up to react to certain things, like:
$account->properties( "type" );, which is my example. I'm using DOM for data storage (for now), and I'm trying to make an
interface that'll let me easily switch to something else - MySQL, flat file, anything. This would work great though!
Hope I've been helpful and I hope I didn't restate something already stated.

anthony at ectrolinux dot com 25-Sep-2004 06:40


For anyone who is interested in overloading a class method based on the number of arguments, here is a simplified example of
how it can be accomplished:
<?php
function Error($message) { trigger_error($message, E_USER_ERROR); exit(1); }
class Framework

{
// Pseudo function overloading
public function __call($func_name, $argv)
{
$argc = sizeof($argv);
switch ($func_name) {
case 'is_available':
$func_name = ($argc == 2) ? 'is_available_single' : 'is_available_multi';
break;
default: // If no applicable function was found, generate the default PHP error message.
Error('Call to undefined function Framework::'. $func_name .'().');
}
return call_user_func_array(array(&$this, $func_name), $argv);
}
// protected array is_available_multi($mod_name, $mod_addon_0 [, $mod_addon_1 [, ...]])
protected function is_available_multi()
{
if (($argc = func_num_args()) < 2) {
Error('A minimum of two arguments are required for Framework::is_available().');
}
$available_addons = array();
// --snip- return $available_addons;
}
protected function is_available_single($mod_name, $mod_addon)
{
// --snip- return true;
}
}
$fw = new Framework;
$test_one = $fw->is_available('A_Module_Name', 'An_Addon');
var_dump($test_one);
// Test one produces a boolean value, supposedly representing whether 'An_Addon' is available and can be used.
$test_two = $fw->is_available('A_Module_Name', 'Addon_0', 'Addon_1', 'Addon_2');
var_dump($test_two);
// Test two produces an array, supposedly listing any of the three 'Addon_N' modules that are available and can be used.
// Here are the actual results of the above:
// bool(true)
// array(0) {
// }
?>
--By adding additional case statements to Framework::__call(), methods can easily be overloaded as needed. It's also possible to
add any other overloading criteria you require inside the switch statement, allowing for more intricate overloading

functionality.

DevilDude at darkmaker dot com 22-Sep-2004 07:57


Php 5 has a simple recursion system that stops you from using overloading within an overloading function, this means you cannot
get an overloaded variable within the __get method, or within any functions/methods called by the _get method, you can however
call __get manualy within itself to do the same thing.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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
classMyClass
{
public$var1='value1';
public$var2='value2';
public$var3='value3';
protected$protected='protectedvar';
private$private='privatevar';
functioniterateVisible(){
echo"MyClass::iterateVisible:\n";
foreach($thisas$key=>$value){
print"$key=>$value\n";
}
}
}
$class=newMyClass();
foreach($classas$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 of the visible properties that could be accessed.
To take it a step further, the Iterator interface may be implemented. This allows the object to dictate how it will
be iterated and what values will be available on each iteration.
Example #2 Object Iteration implementing Iterator

<?php
classMyIteratorimplementsIterator
{
private$var=array();
publicfunction__construct($array)
{
if(is_array($array)){
$this->var=$array;
}
}
publicfunctionrewind()
{
echo"rewinding\n";
reset($this->var);
}

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

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

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

publicfunctionvalid()
{
$key=key($this->var);
$var=($key!==NULL&&$key!==FALSE);
echo"valid:$var\n";
return$var;
}
}
$values=array(1,2,3);
$it=newMyIterator($values);
foreach($itas$a=>$b){
print"$a:$b\n";
}
?>

The above example will output:

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

The IteratorAggregate interface can be used as an alternative to implementing all of the Iterator methods.
IteratorAggregate only requires the implementation of a single method, IteratorAggregate::getIterator(), which
should return an instance of a class implementing Iterator.
Example #3 Object Iteration implementing IteratorAggregate
<?php
classMyCollectionimplementsIteratorAggregate
{
private$items=array();
private$count=0;
//RequireddefinitionofinterfaceIteratorAggregate
publicfunctiongetIterator(){
returnnewMyIterator($this->items);
}
publicfunctionadd($value){
$this->items[$this->count++]=$value;
}
}
$coll=newMyCollection();
$coll->add('value1');
$coll->add('value2');
$coll->add('value3');
foreach($collas$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:

Note:
For more examples of iterators, see the SPL Extension.

User Contributed Notes

Object Iteration

jille at hexon dot cx 15-May-2012 12:29


Please note that if you implement your iterator this way instead of with an IteratorAggregate you can not nest foreach-loops.
This is because when the inner-loop is done the cursor is beyond the last element, then the outer-loop asks for the next
element and finds the cursor beyond the last element as the innter-loop left it there.
<?php
// Wont work!
foreach($collection as $a) {
foreach($collection as $b) {
var_dump($a->someFunc($b));
}
}
?>

uramihsayibok, gmail, com 06-Feb-2010 08:23


With method names like "current", "key", and "next", one might think that you can use the corresponding functions on your
objects. For instance,
<?php
class MyIterator implements Iterator {
// as defined in example #2
}
$iterator = new MyIterator(array(1, 2, 3));
reset($iterator); // calls $iterator->rewind?
var_dump(current($iterator)); // calls $iterator->current()?
?>
This doesn't work. It has been reported as a bug (and honestly it *would* make sense) but was rejected - objects can be
treated as arrays... and that's what happens.

Peter &#39;the Pete&#39; de Pijd 01-Jul-2009 10:12


This is what seems to work for checking isFirst() and isLast() on a class implementing the Iterator interface - without
destroying the internal array pointer:
<?php
// Let $this->_elements be your internal array with
// array("one", "two", "three")
public function isFirst()
{
$hasPrevious = prev($this->_elements);
// now undo
if ($hasPrevious) {
next($this->_elements);
} else {
reset($this->_elements);
}
return !$hasPrevious;
}
public function isLast()
{
$hasNext = next($this->_elements);
// now undo
if ($hasNext) {
prev($this->_elements);
} else {
end($this->_elements);
}
return !$hasNext;
}
// usage
foreach ($myInterator as $value) {
echo $value;
if ($myInterator->isFirst()) {
echo " (first)";
}
if ($myInterator->isLast()) {
echo " (last)";
}
echo " - value is still the same: ", $value, "<br />";
}
?>
output:
one (first) - value is still the same: one
two - value is still the same: two
three (last) - value is still the same: three
This can be helpfull for designing CSS elements where the first or last element must have a different padding/margin than the
others.

hlegius at gmail dot com 15-Oct-2008 05:06


Iterator interface usign key() next() rewind() is MORE slow than extends ArrayIterator with ArrayIterator::next(),
ArrayIterator::rewind(), etc.,

wavetrex A(nospam)T gmail DOT com 01-Mar-2008 02:50


By reading the posts below I wondered if it really is impossible to make an ArrayAccess implementation really behave like a
true array ( by being multi level )
Seems like it's not impossible. Not very preety but usable
<?php
class ArrayAccessImpl implements ArrayAccess {
private $data = array();
public function offsetUnset($index) {}
public function offsetSet($index, $value) {
// echo ("SET: ".$index."<br>");

if(isset($data[$index])) {
unset($data[$index]);
}

$u = &$this->data[$index];
if(is_array($value)) {
$u = new ArrayAccessImpl();
foreach($value as $idx=>$e)
$u[$idx]=$e;
} else
$u=$value;
}
public function offsetGet($index) {
// echo ("GET: ".$index."<br>");
if(!isset($this->data[$index]))
$this->data[$index]=new ArrayAccessImpl();

return $this->data[$index];
}
public function offsetExists($index) {
// echo ("EXISTS: ".$index."<br>");

if(isset($this->data[$index])) {
if($this->data[$index] instanceof ArrayAccessImpl) {
if(count($this->data[$index]->data)>0)
return true;
else
return false;
} else
return true;
} else
return false;
}
}
echo "ArrayAccess implementation that behaves like a multi-level array<hr />";

$data = new ArrayAccessImpl();


$data['string']="Just a simple string";
$data['number']=33;
$data['array']['another_string']="Alpha";
$data['array']['some_object']=new stdClass();
$data['array']['another_array']['x']['y']="LOL @ Whoever said it can't be done !";
$data['blank_array']=array();
echo "'array' Isset? "; print_r(isset($data['array'])); echo "<hr />";
echo "<pre>"; print_r($data['array']['non_existent']); echo "</pre>If attempting to read an offset that doesn't exist it
returns a blank object! Use isset() to check if it exists!<br>";
echo "'non_existent' Isset? "; print_r(isset($data['array']['non_existent'])); echo "<br />";
echo "<pre>"; print_r($data['blank_array']); echo "</pre>A blank array unfortunately returns similar results :(<br />";
echo "'blank_array' Isset? "; print_r(isset($data['blank_array'])); echo "<hr />";
echo "<pre>"; print_r($data); echo "</pre> (non_existent remains in the structure. If someone can help to solve this I'll
appreciate it)<hr />";
echo "Display some value that exists: ".$data['array']['another_string'];
?>
(in the two links mentioned below by artur at jedlinski... they say you can't use references, so I didn't used them.
My implementation uses recursive objects)
If anyone finds a better (cleaner) sollution, please e-mail me.
Thanks,
Wave.

doctorrock83_at_gmail.com 18-May-2007 03:10


Please remember that actually the only PHP iterating structure that uses Iterator is foreach().
Any each() or list() applied to an Object implementing iterator will not provide the expected result

artur at jedlinski dot pl 22-Apr-2007 12:38


One should be aware that ArrayAccess functionality described by "just_somedood at yahoo dot com" below is currently broken and
thus it's pretty unusable.
Read following links to find more:
http://bugs.php.net/bug.php?id=34783
http://bugs.php.net/bug.php?id=32983

rune at zedeler dot dk 27-Feb-2007 08:00


The iterator template from knj at aider dot dk does not yield correct results.
If you do
<?
reset($a);
next($a);
echo current($a);
?>
where $a is defined over the suggested template, then the first element will be output, not the second, as expected.

baldurien at bbnwn dot eu 09-Aug-2006 06:01

Beware of how works iterator in PHP if you come from Java!


In Java, iterator works like this :
<?php
interface Iterator<O> {
boolean hasNext();
O next();
void remove();
}
?>
But in php, the interface is this (I kept the generics and type because it's easier to understand)
<?php
interface Iterator<O> {
boolean valid();
mixed key();
O current();
void next();
void previous();
void rewind();
}
?>
1. valid() is more or less the equivalent of hasNext()
2. next() is not the equivalent of java next(). It returns nothing, while Java next() method return the next object, and move
to next object in Collections. PHP's next() method will simply move forward.
Here is a sample with an array, first in java, then in php :
<?php
class ArrayIterator<O> implements Iterator<O> {
private final O[] array;
private int index = 0;
public ArrayIterator(O[] array) {
this.array = array;
}

public boolean hasNext() {


return index < array.length;
}
public O next() {
if ( !hasNext())
throw new NoSuchElementException('at end of array');
return array[index++];
}
public void remove() {
throw new UnsupportedOperationException('remove() not supported in array');
}
}
?>
And here is the same in php (using the appropriate function) :
<?php
/**
* Since the array is not mutable, it should use an internal

* index over the number of elements for the previous/next


* validation.
*/
class ArrayIterator implements Iterator {
private $array;
public function __construct($array) {
if ( !is_array($array))
throw new IllegalArgumentException('argument 0 is not an array');
$this->array = array;
$this->rewind();
}
public function valid() {
return current($this->array) !== false;
// that's the bad method (should use arrays_keys, + index)
}
public function key() {
return key($this->array);
}
public function current() {
return current($this->array);
}
public function next() {
if ( $this->valid())
throw new NoSuchElementException('at end of array');
next($this->array);
}
public function previous() {
// fails if current() = first item of array
previous($this->array);
}
public function rewind() {
reset($this->array);
}
}
?>
The difference is notable : don't expect next() to return something like in Java, instead use current(). This also means that
you have to prefetch your collection to set the current() object. For instance, if you try to make a Directory iterator (like
the one provided by PECL), rewind should invoke next() to set the first element and so on. (and the constructor should call
rewind())
Also, another difference :
<?php
class ArrayIterable<O> implements Iterable<O> {
private final O[] array;
public ArrayIterable(O[] array) {
this.array = array;
}
public Iterator<O> iterator() {
return new ArrayIterator(array);
}
}
?>
When using an Iterable, in Java 1.5, you may do such loops :
<?php

for ( String s : new ArrayIterable<String>(new String[] {"a", "b"})) {


...
}
?>
Which is the same as :
<?php
Iterator<String> it = new ArrayIterable<String>(new String[] {"a", "b"});
while (it.hasNext()) {
String s = it.next();
...
}
?>
While in PHP it's not the case :
<?php
foreach ( $iterator as $current ) {
...
}
?>
Is the same as :
<?php
for ( $iterator->rewind(); $iterator->valid(); $iterator->next()) {
$current = $iterator->current();
...
}
?>
(I think we may also use IteratorAggregate to do it like with Iterable).
Take that in mind if you come from Java.
I hope this explanation is not too long...

chad 0x40 herballure 0x2e com 05-May-2006 06:46


The example code given for valid() will break if the array contains a FALSE value. This code prints out a single "bool(true)"
and exits the loop when it gets to the FALSE:
<?php
$A = array(TRUE, FALSE, TRUE, TRUE);
while(current($A) !== FALSE) {
var_dump(current($A));
next($A);
}
?>
Instead, the key() function should be used, since it returns NULL only at the end of the array. This code displays all four
elements and then exits:
<?php
$A = array(TRUE, FALSE, TRUE, TRUE);
while(!is_null(key($A))) {
var_dump(current($A));
next($A);
}
?>

markushe at web dot de 06-Aug-2005 11:05


Just something i noticed:
It seems, that when you are implementing the interface Iterator, yout method key() has to return a string or integer.
I was trying to return a object an got this error:
Illegal type returned from MyClass::key()

just_somedood at yahoo dot com 27-Jun-2005 12:20


To clarify on php at moechofe's post, you CAN use the SPL to overide the array operator for a class. This, with the new
features of object, and autoloading (among a buch of other things) has me completely sold on PHP5. You can also find this
information on the SPL portion of the manual, but I'll post it here as well so it isn't passed up. The below Collection class
will let you use the class as an array, while also using the foreach iterator:
<?php
class Collection implements ArrayAccess,IteratorAggregate
{
public $objectArray = Array();
//**these are the required iterator functions
function offsetExists($offset)
{
if(isset($this->objectArray[$offset])) return TRUE;
else return FALSE;
}

function & offsetGet($offset)


{
if ($this->offsetExists($offset)) return $this->objectArray[$offset];
else return (false);
}

function offsetSet($offset, $value)


{
if ($offset) $this->objectArray[$offset] = $value;
else $this->objectArray[] = $value;
}

function offsetUnset($offset)
{
unset ($this->objectArray[$offset]);
}

function & getIterator()


{
return new ArrayIterator($this->objectArray);
}
//**end required iterator functions
public function doSomething()
{
echo "I'm doing something";
}
}
?>
I LOVE the new SPL stuff in PHP! An example of usage is below:

<?php
class Contact
{
protected $name = NULL;
public function set_name($name)
{
$this->name = $name;
}

public function get_name()


{
return ($this->name);
}
}
$bob = new Collection();
$bob->doSomething();
$bob[] = new Contact();
$bob[5] = new Contact();
$bob[0]->set_name("Superman");
$bob[5]->set_name("a name of a guy");
foreach ($bob as $aContact)
{
echo $aContact->get_name() . "\r\n";
}
?>
Would work just fine. This makes code so much simpler and easy to follow, it's great. This is exactly the direction I had
hoped PHP5 was going!

PrzemekG_ at poczta dot onet dot pl 27-May-2005 04:20


If you want to do someting like this:
<?php
foreach($MyObject as $key => &$value)
$value = 'new '.$value;
?>
you must return values by reference in your iterator object:
<?php
class MyObject implements Iterator
{
/* ...... other iterator functions ...... */
/* return by reference */
public function &current()
{
return $something;
}
?>
This won't change values:
<?php
foreach($MyObject as $key => $value)
$value = 'new '.$value;
?>
This will change values:

<?php
foreach($MyObject as $key => &$value)
$value = 'new '.$value;
?>
I think this should be written somewhere in the documentations, but I couldn't find it.

elias at need dot spam 10-Apr-2005 03:15


The MyIterator::valid() method above ist bad, because it
breaks on entries with 0 or empty strings, use key() instead:
<?php
public function valid()
{
return ! is_null(key($this->var));
}
?>
read about current() drawbacks:
http://php.net/current

strrev('ed.relpmeur@ekneos'); 01-Mar-2005 02:25


Use the SPL ArrayAccess interface to call an object as array:
http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html

phpnet at nicecupofteaandasitdown dot com 22-Feb-2005 08:09


You should be prepared for your iterator's current method to be called before its next method is ever called. This certainly
happens in a foreach loop. If your means of finding the next item is expensive you might want to use something like this
private $item;

function next() {
$this->item = &$this->getNextItem();
return $this->item;
}

public function current() {


if(!isset($this->item)) $this->next();
return $this->item;
}

knj at aider dot dk 18-Dec-2004 07:19


if you in a string define classes that implements IteratorAggregate.
you cant use the default;
<?
...
public function getIterator() {
return new MyIterator(\\$this-><What ever>);
}
..
?>
at least not if you want to use eval(<The string>).

You have to use:


<?
...
public function getIterator() {
\\$arrayObj=new ArrayObject(\\$this-><What ever>);
return \\$arrayObj->getIterator();
}
...
?>

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Magic Methods
The function names __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(),
__sleep(), __wakeup(), __toString(), __invoke(), __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()


public array __sleep ( void )
void __wakeup ( void )
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.
Note:
It is not possible for __sleep() to return names of private properties in parent classes. Doing this will result
in an E_NOTICE level error. Instead you may use the Serializable interface.
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
classConnection
{
protected$link;
private$server,$username,$password,$db;

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

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

publicfunction__sleep()
{
returnarray('server','username','password','db');
}

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

__toString()
public string __toString ( void )
The __toString() method allows a class to decide how it will react when it is treated like a string. For example,
what echo $obj; will print. This method must return a string, as otherwise a fatal E_RECOVERABLE_ERROR level error is
emitted.
Example #2 Simple example
<?php
//Declareasimpleclass
classTestClass
{
public$foo;
publicfunction__construct($foo)
{
$this->foo=$foo;
}
publicfunction__toString()
{
return$this->foo;
}
}
$class=newTestClass('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.

__invoke()
mixed __invoke ([

$...

] )

The __invoke() method is called when a script tries to call an object as a function.
Note:
This feature is available since PHP 5.3.0.
Example #3 Using __invoke()
<?php
classCallableClass
{
publicfunction__invoke($x)
{
var_dump($x);
}
}
$obj=newCallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

The above example will output:


int(5)
bool(true)

__set_state()
static object __set_state ( array

$properties

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 #4 Using __set_state() (since PHP 5.1.0)
<?php
classA
{
public$var1;
public$var2;
publicstaticfunction__set_state($an_array)//AsofPHP5.1.0
{
$obj=newA;
$obj->var1=$an_array['var1'];
$obj->var2=$an_array['var2'];
return$obj;
}
}

$a=newA;
$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"
}

User Contributed Notes

Magic Methods

miguel dot perez at afina dot es 15-Jun-2012 08:17


Both __call and __invoke exist and do completely different things. Nice.

Voitcus at wp dot pl 15-Feb-2012 09:48


You don't need to serialize the class default values, only those which have changed. It might be important for large objects.
Note the example below, for simplicity, always serializes arrays and objects.
<?php
class MyBaseClass {
public $name='object'; // these are default class values
public $test=1;
public $test2; // equals to NULL in fact
public function __construct(){
$this->test2='some text'; // this is not a default value, although called in the constructor
}
public function __sleep(){
// default class values:
$defaults=get_class_vars(get_class($this)); // not __CLASS__ or self::, if you'd like to use in descendant classes
// values of $this object:
$present=get_object_vars($this);
$result=array(); // output array
foreach($present as $key=>$value){
if(!is_resource($defaults[$key]) && ( // don't store resources
is_object($defaults[$key]) || // always store objects
is_array($defaults[$key]) || // and arrays
$defaults[$key]!==$value) // and of course all that is not the default value
) // tip: try is_scalar as well
$result[]=$key;
}

return $result;
}
}
$obj1=new MyBaseClass();
echo ($s1=serialize($obj1))."<br>"; // only test2 is stored, as it was changed in the constructor
$obj2=new MyBaseClass();
$obj2->name='object 2'; // change default value here
echo ($s2=serialize($obj2))."<br>"; // stored name and test2
$obj3=new MyBaseClass();
$obj3->test2=NULL; // switch back to default value
echo ($s3=serialize($obj3))."<br>"; // nothing is stored but the class name
// let us check if we can retrieve the objects
unset($obj1, $obj2, $obj3);
$obj1=unserialize($s1);
$obj2=unserialize($s2);
$obj3=unserialize($s3);
var_dump($obj1);
var_dump($obj2);
var_dump($obj3);
?>

daan dot broekhof at gmail dot com 14-Feb-2012 10:54


Ever wondered why you can't throw exceptions from __toString()? Yeah me too.
Well now you can! This trick allows you to throw any type of exception from within a __toString(), with a full & correct
backtrace.
How does it work? Well PHP __toString() handling is not as strict in every case: throwing an Exception from __toString()
triggers a fatal E_ERROR, but returning a non-string value from a __toString() triggers a non-fatal E_RECOVERABLE_ERROR.
Add a little bookkeeping, and can circumvented this PHP deficiency!
(tested to work PHP 5.3+)
<?php
set_error_handler(array('My_ToStringFixer', 'errorHandler'));
error_reporting(E_ALL | E_STRICT);
class My_ToStringFixer
{
protected static $_toStringException;
public static function errorHandler($errorNumber, $errorMessage, $errorFile, $errorLine)
{
if (isset(self::$_toStringException))
{
$exception = self::$_toStringException;
// Always unset '_toStringException', we don't want a straggler to be found later if something came between the
setting and the error
self::$_toStringException = null;
if (preg_match('~^Method .*::__toString\(\) must return a string value$~', $errorMessage))
throw $exception;
}
return false;
}


public static function throwToStringException($exception)
{
// Should not occur with prescribed usage, but in case of recursion: clean out exception, return a valid string, and
weep
if (isset(self::$_toStringException))
{
self::$_toStringException = null;
return '';
}
self::$_toStringException = $exception;
return null;
}
}
class My_Class
{
public function doComplexStuff()
{
throw new Exception('Oh noes!');
}
public function __toString()
{
try
{
// do your complex thing which might trigger an exception
return $this->doComplexStuff();
}
catch (Exception $e)
{
// The 'return' is required to trigger the trick
return My_ToStringFixer::throwToStringException($e);
}
}
}
$x = new My_Class();
try
{
echo $x;
}
catch (Exception $e)
{
echo 'Caught Exception! : '. $e;
}
?>

osbertv at yahoo dot com 29-Dec-2011 09:42


Invoking a class inside a class results in an error.
<?php
class A
{
public function __invoke()

{
echo "Invoking A() Class";
}
}
class B
{
public $a;

public function __construct()


{
$this->a = new A();
}

public function __invoke()


{
echo "Invoking B() Class";
}
}
$a = new A();
$b = new B();
$a();
$b();
$b->a();
?>
returns
Invoking B() Class
PHP Fatal error: Call to undefined method B::a()

hyponiq at gmail dot com 26-Sep-2011 06:07


I think it's fair to note the undocumented fact that the __invoke magic method can take any number of arguments (or none).
Example:
<?php
class InvokeNoParams {
function __invoke()
{
print __METHOD__ . PHP_EOL;
$i = 1;
foreach (func_get_args() as $arg) {
print "The value of \$param{$i} is: " . $arg . PHP_EOL;
++$i;
}
print PHP_EOL;
}
}

class InvokeSingleParam {
function __invoke($param1)
{
print __METHOD__ . PHP_EOL;
print "Value of \$param1 is: " . $param1 . PHP_EOL . PHP_EOL;
}
}

class InvokeMultiParams {
function __invoke($param1, $param2, $param3) {
print __METHOD__ . PHP_EOL;
print "Value of \$param1 is: " . $param1 . PHP_EOL;
print "Value of \$param2 is: " . $param2 . PHP_EOL;
print "Value of \$param3 is: " . $param3 . PHP_EOL . PHP_EOL;
}
}

$no = new InvokeNoParams;


$single = new InvokeSingleParam;
$multi = new InvokeMultiParams;

$no(1, 2, 3);
$single('one param');
$multi('param 1', 'param 2', 'param 3');
?>
This outputs:
InvokeNoParams::__invoke
The value of $param1 is: 1
The value of $param2 is: 2
The value of $param3 is: 3
InvokeSingleParam::__invoke
Value of $param1 is: one param
InvokeMultiParams::__invoke
Value of $param1 is: param 1
Value of $param2 is: param 2
Value of $param3 is: param 3

Wesley 25-May-2011 12:10


Warning __toString can be triggerd more then one time
<?php
if(strstr(substr($obj,0,1024), 'somestuff')
echo $obj;
return 'missing somestuff at the start, create container!';
substr() will trigger a __toString aswell as echo $obj;
?>
wich cause a performance issue since it will gather all data twice.
what i used as a hotfix:
<?php
__toString(){
if(null === $this->sToString)
$this->sToString = $this->_show();
return $this->sToString;
}
?>

Sammaye 18-Aug-2010 08:13

Thought I would just explain something about __get and __set here.
Imgine you have a class like so:
<?php
class user_bo{
protected $attributes = Array();

public function __get($key){



return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null;
}

public function __set($key, $value){

$this->attributes[$key] = $value;
}

/** Constructor **/
public function __construct(){}
}
?>
now imagine you add a function like so to this class:
<?php
public function update(){
global $database;

$fields = $database->connection->getTable("users");

$set = "";
foreach($fields as $field => $info){

if(isset($this->$field)){
if($this->$field == "now()"){
$set .= $field."=".mysql_real_escape_string($this->$field).", ";
}elseif($this->$field == null){
$set .= $field."=null, ";
}else{
$set .= $field."='".mysql_real_escape_string($this->$field)."', ";
}
}
}
$output_set = substr($set, 0, -2);

$query = "UPDATE users SET $output_set WHERE sequal_user_id = '$this->sequal_user_id'";
mysql_query($query) or sqlerrorhandler("(".mysql_errno().") ".mysql_error(), $query, $_SERVER['PHP_SELF'], __LINE__);

return true;
}
?>
The if(isset($this->$field)) will return false everytime. Instead of isset in loops like this you should use ($this->$field).
isset returns false even when the field is populated and in theory it should never return false since in my __get:
<?php
return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null;

?>
I return null if my variable don't exist.

Anonymous 24-Jul-2010 07:41


Concerning __set() with protected/private/overloaded properties, the behavior might not be so intuitive without knowing some
underlying rules. Consider this test object for the following examples...
<?php
class A {
protected $test_int = 2;
protected $test_array = array('key' => 'test');
protected $test_obj;

function __construct() {
$this->test_obj = new stdClass();
}

function __get($prop) {
return $this->$prop;
}

function __set($prop, $val) {
$this->$prop = $val;
}
}
$a = new A();
?>
Combined Operators (.=, +=, *=, etc): you must also define a companion __get() method to grant write -and- read access to the
property. Remember, "$x += $y" is shorthand for "$x = $x + $y". In other words, "__set($x, (__get($x) + $y))".
Properties that are Arrays: attempting to set array values like "$a->test_array[] = 'asdf';" from outside this object will
result in an "Indirect modification of overloaded property" notice and the operation completely ignored. You can't use '[]'
for array value assignment in this context (with the exception only if you made __get() return by reference, in which case, it
would work fine and bypass the __set() method altogether). You can work around this doing something like unioning the array
instead:
<?php
$a->test_array[] = 'asdf'; // notice given and ignored unless __get() was declared to return by reference
$a->test_array += array(1 => 'asdf'); // to add a key/value
$a->test_array = array("key" => 'asdf') + $a->test_array; // to overwrite a key/value.
?>
Properties that are Objects: as long as you have that __get() method, you can freely access and alter that sub object's own
properties, bypassing __set() entirely. Remember, objects are assigned and passed by reference naturally.
<?php
$a->test_obj->prop = 1; // fine if $a did not have a set method declared.
?>
All above tested in 5.3.2.

tom 18-Jul-2010 03:20


Note a common pitfall when using __wakeup.
If you unserialize a datastructure, you may not rely on the parent object to have been fully unserialized by the time __wakeup
is called. Example
<?php
class A {
public $b;
public $name;
}
class B extends A {
public $parent;
public function __wakeup() {
var_dump($parent->name);
}
}
$a = new A();
$a->name = "foo";
$a->b = new B();
$a->b->parent = $a;
$s = serialize($a);
$a = unserialize($s);
?>
Expected output: "foo".
Actual output: NULL.
Reason: $b is unserialized before $name. By the time B::__wakeup is called, $a->name does not yet have a value.
So be aware that the order in which your class variables are defined is important! You need to manually order them by
dependencies - or write a __sleep function and order them by depencies there. (Currently I can't tell which option I hate more)

Anonymous 30-Jun-2010 09:29


C++-style operator overloading finally makes an appearance with the introduction to __invoke(). Unfortunately, with just
'()'. In that sense, it is no more useful than having a default class method (probably quite useful actually) and not having
to type out an entire method name. Complimenting wbcarts at juno dot com's point class below, the following allows calculating
distance between one or more graph points...
<?php
class point {
public $x;
public $y;
function __construct($x=0, $y=0) {
$this->x = (int) $x;
$this->y = (int) $y;
}

function __invoke() {
$args = func_get_args();
$total_distance = 0;
$current_loc = $this;

foreach ($args as $arg) {


if (is_object($arg) and (get_class($arg) === get_class($this))) {
$total_distance += sqrt(pow($arg->x - $current_loc->x, 2) + pow((int) $arg->y - $current_loc->y, 2));
$current_loc = $arg;
}
else {
trigger_error("Arguments must be objects of this class.");
return;
}
}
return $total_distance;
}

}
$p1 = new point(1,1);
$p2 = new point(23,-6);
$p3 = new point(15,20);
echo $p1($p2,$p3,$p1); // round trip 73.89
?>
Functionally, __invoke() can also be used to mimic the use of variable functions. Sadly, attempting any calling of __invoke()
on a static level will produce a fatal error.

tfn dot yldrm at hotmail dot com 15-Jun-2010 03:26


Properties can be used for getter and setter as C# methods get_PropertyName and set_PropertyName for full event-based
programming.
<?php
/**
* @author Tufan Baris YILDIRIM
* @name getter and setter magics.
*/
Class GetSet
{
public $Name,$Surname; // they will be deleted those only for autocompletion.
private $_Name,$_Surname;
public function __construct()
{
foreach(get_class_vars('GetSet') as $varName=>$varValue)
{
if(substr($varName,0,1)!="_")
unset($this->$varName);
}
}
public function __get($varName)
{
if(method_exists($this,$MethodName='get_'.$varName))
return $this->$MethodName();
else
trigger_error($varName.' is not avaliable .',E_USER_ERROR);
}
public function __set($varName,$value)

{
if(method_exists($this,$MethodName='set_'.$varName))
return $this->$MethodName($value);
else
trigger_error($varName.' is not avaliable .',E_USER_ERROR);
}
private function set_Surname($value)
{
// On surname changed Events.
echo "Surname Changed as ".$value."\r\n";
$this->_Surname=$value;
}
private function get_Surname()
{
// On Get Events.
echo "Surname Getted\r\n";
return $this->_Surname;
}
private function set_Name($value)
{
// On Name changed Events.
echo "Name Changed as ".$value."\r\n";
$this->_Name=$value;
}
private function get_Name()
{
// On Get Name Events.
echo "Name getted\r\n";
return $this->_Name;
}
}
?>
Using :
<?php
$get=new GetSet();
$get->Name="Tufan Baris";
$get->Surname="YILDIRIM";
echo $get->Name.' '.$get->Surname;
?>
Output
Name Changed as Tufan Baris
Surname Changed asYILDIRIM
Name getted
Surname Getted
Tufan Baris YILDIRIM

xmontero at dsitelecom dot com 05-Dec-2009 08:01


This "tip" is for those who receive the error "Object of class X could not be converted to string" when __toString() is not
possible, and it is not a choice to process or not - for example when received via debug_backtrace().

HOW IT HAPPENED:
I use to have a logging function called LogEnter() and another called LogExit() that I use to call at every function when
intensively debugging.
For example all my functions look like:
<?php
function AnyFunction( $a, $b, $c )
{
LogEnter();
// DoSomeStuffHere.
LogExit();
}
?>
Then inside LogEnter(), I use debug_backtrace() to discover the parameters that were used when calling the function (in this
example the values of $a, $b, $c).
The LogEnter() deals without knowing the number of parameters to treat, and formats something like ( 2, 3, 4 ) if those were
the values. That info is printed among other info to a log-file.
Doing this, keeps me with a single-very-simple way to trace all te calls.
The thing is that if the the following are met at the same time, I have a problem:
- The function accepts (and is called with) a class as a parameter.
- The function is being debuggd by calling LogEnter();
- The class does not have __toString() coded.
- For some reason I am not allowed to edit the class nor inherit from it.
Then the debug function performs an "Object of class X could not be converted to string" error when trying to "dump" the
parameter list (containing the object) into the file.
LOG FUNCTION:
This looks for the "parameters array" and then calls BuildArgs to format them. LogWrite finds the function name, file, line
number, and so on, but does not matter here.
<?php
public function LogEnter()
{
$Debug = debug_backtrace();
$DebugLine = $Debug[ 1 ];
// [0] would be this very same function.
// [1] is the caller of this function.
$Args = isset( $DebugLine[ 'args' ] ) ? $DebugLine[ 'args' ] : '[x]';

$Msg = 'Entering with ' . BuildArgs( $Args );
LogWrite( $Msg );
}
// CAUTION, THIS NEXT ONE FAILS
private function BuildArgs( $Args )
{
$Result = '( ' . implode( ', ', $Args ) . ' )';
return $Result;

}
?>
The problem is that if you call a function where a parameter being an object that has not the __toString() defined, then
automatically "imploding" the argument list into a string, fails.
SOLUTION:
The solution is that the __toString is "checkable for its existance". The "tips" are to manually traverse the result of
debug_backtrace()['args'] and then, for each element, check:
- if it is or not an object with is_object( $Value )
- in case it is, check if __toString() is defined with method_exists( $Value, '__toString' )
- in case it is not an object or the method exist, perform a normal assignation.
- in case it is an object without that method, print something else. I choose to output the class name with get_class( $Value
) and put it between square brackets.
The final function becomes like this:
<?php
private function BuildArgs( $Args )
{
// This function gets an 'args' array from debug_backtrace() and formats it in the printable format (a, b, c) including the
parenthesis.

$FormattedParams = '';
$Glue = '';

foreach( $Args as $Value )
{
if( is_object( $Value ) )
{
if( method_exists( $Value, "__toString" ) )
{
$PrintableValue = $Value;
}
else
{
$PrintableValue = '[' . get_class( $Value ) . ']';
}
}
else
{
$PrintableValue = $Value;
}

$FormattedParams .= $Glue . $PrintableValue;
$Glue = ', ';
}

$Result = sprintf( '( %s )', $FormattedParams );

return $Result;
}
?>

vad dot viktor at gmail dot com 15-Oct-2009 03:06


If you are using __autoload to dynamically load your classes, then __invoke won't work. Calling a class like SomeClass() will

give and error in this case as it is evaluated first as a function, not as a class and so __autoload won't be triggered.

moechofe 25-Jul-2009 02:47


__invoke() cannot be used to create fluente interface like in the "D language"
<?php
class CallableClass
{
var $next;
function __invoke($x)
{
var_dump($x);
return $this;
}
}
$obj = new CallableClass;
$obj->next = new CallableClass;
var_dump( $obj(5) ); // OK!
var_dump( $obj(5)(6) ); // Parse error
var_dump( $obj->next(7) ); // Fatal error: Call to undefined method CallableClass::next()
var_dump( {$obj->next}(7) ); // Parse error
?>

zach at bygeekz dot com 25-May-2009 12:45


Try this one on.
<?php
$ret = new Test(true);
var_dump((bool)(string)$ret);
var_dump($ret);
$ret=null;
$ret = new Test();
var_dump((bool)(string)$ret);
var_dump($ret);
class Test {
protected $state=null;
function __construct($state=null) {
$this->state = $state;
}
function __toString() {
if ($this->state) { return "1"; } else { return "0"; }
}
}
?>
You could for instance do..
if(!(bool)(string)$ret) { do_something!; }
Alternatively, just make state public, and check it.
if(!$ret->state) {}.
There is no automatic way I have found aside from some internal state check to verify a class. It will always return an
object. The only way around that is to force it out to string either where I did, or $ret = (string) new Test(); then test the

bool of your output..


if (!$ret) { echo "noooo!"; }
But now you have no calling methods, so I hope you passed some data in to get a usable string out.
Of course, if your class isn't named test, you can add a method..
public function test() {
return $this->state;
}
Logically that will work regardless of the _toString(), but I had hoped to post this to help others see that there are a
multitude of ways to check the validity of a class once it is loaded. In __construct you can add any number of checks and set
your state appropriately.

jahanaddison6 at hotmail dot com 03-May-2009 03:16


If you're expecting this code to work think again:
<?php
class Example
{
public function __construct()
{
return false;
}
public function Test()
{
return true;
}
}
?>
The above code will not work as expected, The Test method will still return true.

rudie-de-hotblocks at osu1 dot php dot net 09-Apr-2009 06:35


Note also that the constructor is executed also, and before __set_state(), making this magic function less magic, imho, (except
for the ability to assign private members).

muratyaman at gmail dot com 07-Jan-2009 07:54


Regarding __toString:
<?php
class my_tag_A{
public $id='';
public $href='';
public $target='';
public $class='';

public $label='';

function __construct($href, $label){


$this->href = $href;

$this->label = $label;
}

public function __toString(){


return '<a '.$this->nz_arr(array('id', 'href', 'target', 'class')). ' >' . $this->label . '</a>';
}

function nz_arr($attrib_arr){
$s = '';
foreach($attrib_arr as $attrib){
$s .= $this->nz($attrib);
}
return $s;
}
/**
* Print the tag attribute if it is not blank, such as id="$this->id"
* @param string $attrib
* @return string
*/
function nz($attrib){
$s = '';
if($this->$attrib != '') $s = $attrib .' = "' . $this->$attrib . '"';
return $s;
}
//This causes RECURSION because of parsing between double quotes. This is a very UNEXPECTED behaviour!
function nz_($attrib){
$s = '';
if($this->$attrib != '') $s = "$attrib = \"$this->$attrib\"";
return $s;
}

}//end class
//usage
$a = new my_tag_A('abc.php', 'ABC'); $a->target = '_blank';
echo $a;
//prints:
// <a href="abc.php" target="_blank" >ABC</a>
?>

jsnell at e-normous dot com 03-Dec-2008 02:01


Be very careful to define __set_state() in classes which inherit from a parent using it, as the static __set_state() call will
be called for any children. If you are not careful, you will end up with an object of the wrong type. Here is an example:
<?php
class A
{
public $var1;
public static function __set_state($an_array)
{
$obj = new A;
$obj->var1 = $an_array['var1'];
return $obj;
}
}

class B extends A {
}
$b = new B;
$b->var1 = 5;
eval('$new_b = ' . var_export($b, true) . ';');
var_dump($new_b);
/*
object(A)#2 (1) {
["var1"]=>
int(5)
}
*/
?>

patricknegri at gmail dot com 26-Oct-2008 03:57


Imports Pattern - Extend Classes in Real Time:
<?php
class BaseClass
{
var $__imported;
var $__imported_functions;

function __construct()
{
$__imported = Array();
$__imported_functions = Array();
}

function Imports($object)
{
$new_imports = new $object();
$imports_name = get_class($new_imports);
array_push( $__imported, Array($imports_name,$new_imports) );
$imports_function = get_class_methods($new_imports);
foreach ($imports_function as $i=>$function_name)
{
$this->__imported_functions[$function_name] = &$new_imports;
}
}

function __call($m, $a)


{
if (array_key_exists($m,$this->__imported_functions))
{
return call_user_func_array(Array($this->__imported_functions[$m],$m),$a);
}
throw new ErrorException ('Call to Undefined Method/Class Function', 0, E_ERROR);
}
}
class ExternalFunc
{
function TestB()
{

echo "External Imported!";


}
}
class B extends BaseClass
{
function __construct()
{
$this->Imports("ExternalFunc");
}

function Msg()
{
echo "Hello world<br />";
}
}
$b = new B();
$b->Msg();
// or call $b->Imports("ExternalFunc");
$b->TestB();
//$b->TestB(1,3,4);
?>

jon at webignition dot net 03-Oct-2008 07:26


The __toString() method is extremely useful for converting class attribute names and values into common string representations
of data (of which there are many choices). I mention this as previous references to __toString() refer only to debugging uses.
I have previously used the __toString() method in the following ways:
- representing a data-holding object as:
- XML
- raw POST data
- a GET query string
- header name:value pairs
- representing a custom mail object as an actual email (headers then body, all correctly represented)
When creating a class, consider what possible standard string representations are available and, of those, which would be the
most relevant with respect to the purpose of the class.
Being able to represent data-holding objects in standardised string forms makes it much easier for your internal
representations of data to be shared in an interoperable way with other applications.

wbcarts at juno dot com 02-Oct-2008 04:12


To be helpful, the __toString() method should return the class name and the state of all its properties inside square brackets.
<?php
class Point {
protected $x, $y;
public function __construct($xVal = 0, $yVal = 0) {
$this->x = $xVal;
$this->y = $yVal;
}

public function __toString() { // the function we're interested in...


return "Point[x=$this->x, y=$this->y]";
}
}
$point1 = new Point(10, 10);
$point2 = new Point(50, 50);
echo $point1 . '<br>';
echo $point2 . '<br><br>';
?>
Point[x=10, y=10]
Point[x=50, y=50]
Classes that include objects, should call that objects __toString() method.
<?php
class Line {
protected $start, $end;
public function __construct(Point $p1, Point $p2){
$this->start = $p1;
$this->end = $p2;
}
public function __toString() { // the function we're interested in...
return 'Line[start=' . $this->start->__toString() . // call __toString()
', end=' . $this->end->__toString() . ']'; // call __toString()
}
}
echo (new Line($point1, $point2));
?>
Line[start=Point[x=10, y=10], end=Point[x=50, y=50]]

rc @ nospam @ vorklift dot sea oh em 07-Aug-2008 07:03


A note: __wakeup occurs before saving the unserialization of an session object.
Therefore, $_SESSION['var']::__wakeup() setting $_SESSION['var'] = new Class() will fail and $_SESSION['var'] will remain
unchanged.
This means that if you have a pseudo-temporary object that contains a class to auto revert to, you have to revert that session
object in the initialization of the website rather than via a __wakeup() script.

Anonymous 31-May-2008 04:24


Serializing objects is problematic with references. This is solved redefining the __sleep() magic method. This is also
problematic when parent class has private variables since the parent object is not accessible nor its private variables from
within the child object.
I found a solution that seems working for classes that implements this __sleep() method, and for its subclasses. Without more
work in subclasses. The inheritance system does the trick.
Recursively __sleep() call parent' __sleep() and return the whole array of variables of the object instance to be serialized.
<?php

class foo {
}
class a {
private $var1;
function __construct(foo &$obj = NULL) {
$this->var1 = &$obj;
}
/** Return its variables array, if its parent exists and the __sleep method is accessible, call it and push the result into
the array and return the whole thing. */
public function __sleep() {
$a = array_keys(get_object_vars(&$this));
if (method_exists(parent, '__sleep')) {
$p = parent::__sleep();
array_push($a, $p);
};
return $a;
}
}
class b extends a {
function __construct(foo &$obj = NULL) {
parent::__construct($obj);
}
}
session_start();
$myfoo = &new foo();
$myb = &new b($myfoo);
$myb = unserialize(serialize(&$myb));
?>
This should work, I haven't tested deeper.

yanleech at gmail dot com 10-May-2008 06:24


Maybe we can using unserialize() & __wakeup() instead "new" when creating a new instance of class.
Consider following codes:
class foo
{
static public $WAKEUP_STR = 'O:3:"foo":0:{}';
public function foo(){}
public function bar(){}
}
$foo = unserialize(foo::$WAKEUP_STR);

michal dot kocarek at seznam dot cz 18-Apr-2008 02:34


Remember that setters and getters (__set, __get) will work in your class as long as you NOT SET the property with given name.
If you still want to have the public property definition in the class source code (phpDocumentor, editor code completition, or
any other reason) when using these magic methods, simply unset() your public properties inside the constructor.
__set/__get function will be called and code reader will see at first sight, which public properties are available.

Example:
<?php
class user {
/**
* @var int Gets and sets the user ID
*/
public $UserID;
private $_userID;
public function __construct() {
// All the magic is in single line:
// We unset public property, so our setters and getters
// are used and phpDoc and editors with code completition are happy
unset($this->UserID);
}
public function __set($key, $value) {
// assign value for key UserID to _userID property
}
public function __get($key) {
// return value of _userID for UserID property
}
}
?>

dhuseby domain getback tld com 29-Feb-2008 06:22


The above hint for using array_keys((array)$obj) got me investigating how to get __sleep to really work with object
hierarchies.
With PHP 5.2.3, If you want to serialize an object that is part of an object hierarchy and you want to selectively serialize
members (public, private, and protected) by manually specifying the array of members, there are a few simple rules for naming
members that you must follow:
1. public members should be named using just their member name, like so:
<?php
class Foo {
public $bar;
public function __sleep() {
return array("bar");
}
}
?>
2. protected members should be named using "\0" . "*" . "\0" . member name, like so:
<?php
class Foo {
protected $bar;
public function __sleep() {
return array("\0*\0bar");
}

}
?>
3. private members should be named using "\0" . class name . "\0" . member name, like so:
<?php
class Foo {
private $bar;
public function __sleep() {
return array("\0Foo\0bar");
}
}
?>
So with this information let us serialize a class hierarchy correctly:
<?php
class Base {
private $foo = "foo_value";
protected $bar = "bar_value";
public function __sleep() {
return array("\0Base\0foo", "\0*\0bar");
}
}
class Derived extends Base {
public $baz = "baz_value";
private $boo = "boo_value";
public function __sleep() {
// we have to merge our members with our parent's
return array_merge(array("baz", "\0Derived\0boo"), parent::__sleep());
}
}
class Leaf extends Derived {
private $qux = "qux_value";
protected $zaz = "zaz_value";
public $blah = "blah_value";
public function __sleep() {
// again, merge our members with our parent's
return array_merge(array("\0Leaf\0qux", "\0*\0zaz", "blah"), parent::__sleep());
}
}
// test it
$test = new Leaf();
$s = serialize($test);
$test2 = unserialize($s);
echo $s;
print_r($test);
print_r($test2);
?>
Now if you comment out all of the __sleep() functions and output the serialized string, you will see that the output doesn't

change. The most important part of course is that with the proper __sleep() functions, we can unserialize the string and get a
properly set up object.
I hope this solves the mystery for everybody. __sleep() does work, if you use it correctly :-)

andrew dot minerd at sellingsource dot com 08-Nov-2007 07:55


Until __sleep is "fixed" (here's hoping), a function that will return ALL members of a given object -- public, protected, AND
private:
<?php
public function getPropertyNames(array $filter = NULL)
{
$rc = new ReflectionObject($this);
$names = array();
while ($rc instanceof ReflectionClass)
{
foreach ($rc->getProperties() as $prop)
{
if (!$filter || !in_array($prop->getName(), $filter))
$names[] = $prop->getName();
}
$rc = $rc->getParentClass();
}
return $names;
}
?>

amir_abiri at ipcmedia dot com 24-Jul-2007 04:58


Another small thing that is important to note about __sleep() and privte member variables:
<?php
class A
{
private $a;

public function __construct()


{
$this->a = 1;
}
}
class B extends A
{
protected $b;

public function __construct()


{
parent::__construct();
$this->b = 2;
}

function __sleep()
{

return array('a', 'b');


}
}
serialize(new B);
?>
result:
Notice: serialize(): "a" returned as member variable from __sleep() but does not exist in ...
To summerize: in a given class hierarchy in which parent classes contain private member variables, those variables are
serialized when __sleep() is not defined. However, once __sleep() is defined, there is no way to make those private member
variables serialized as well. From that point on, serialization is performed from the visibility scope of the subclass.
It is particularly important to note this little quirk when designing base classes that their derivables may be serialized, or
when subclassing an external library class.

alejandro dot gama at gmail dot com 09-May-2007 07:47


Referering my previus note: there was an error in the code. But i find a better way:
<?
session_start();
class Classes{
private $name;
private $statics;

function __construct($name){
$this->name=$name;
$this->statics=array();
}

function setStatic($k,$v){
if(!is_resource($v))
$this->statics[$k]=$v;
}

function __wakeup(){
foreach($this->statics as $k=>$v)
eval($this->name."::\$".$k."=\$this->statics['".$k."'];");
}
}
function storeStaticAttributes(){
$classes=get_declared_classes();
foreach($classes as $name){
$reflect=new ReflectionClass($name);
if($reflect->isUserDefined()){
$statics=$reflect->getStaticProperties();
if(empty($_SESSION["_classes"]))
$_SESSION["_classes"]=array();

if(empty($_SESSION["_classes"][$name]))
$_SESSION["_classes"][$name]=new Classes($name);

foreach($statics as $k=>$v)
$_SESSION["_classes"][$name]->setStatic($k,$v);
}
}
}
register_shutdown_function('storeStaticAttributes');
?>

Travis Swicegood 08-May-2007 07:43


There is no need to use eval() to mimic mixins (i.e., multiple inheritance) within PHP 5. You only need to:
<?php
class MyClass
{
private $_obj = null;
public function __construct($obj)
{
$this->_obj = $obj;
}
public function __call($method, $args)
{
if (!method_exists($this->_obj, $method)) {
throw new Exception("unknown method [$method]");
}
return call_user_func_array(
array($this->_obj, $method),
$args
);
}
}
?>
You could just as easily add an addMixin() method that would allow you to add multiple objects to an array, and then iterate
over that array until you found the right method. As noted, these are referred to as a Mixins in other languages.

adar at darkpoetry dot de 04-May-2007 06:09


Maybe not really new and all in all definitely not the best solution,but if you cant extend a class (if your class alreay
extends an abstract or other things like that) you can 'fake' a extend.
<?php
class MyClass
extends SomeAbstractUnknownClass {
private $classObject;
public function __construct ( classObject $classToExtend ) {
$this->classObject = $classToExtend;
}
public function __call($func, $var) {
if ( !count($var) ) {
return $this->classObject->$func($var);

} else {
$str = '';
$values = array_values($var);
for ( $i=0; $i<count($values); $i++ ) {
$str .= "'".$values[$i]."' ,";
}
$str = substr($str, 0, -2);
return eval('return $this->classObject->'.$func.'('.$str.');');
}
}
}
?>
So if you'll do a $myClass->unknownMethod() and it is found neither in MyClass nor in SomeAbstractUnknownClass, MyClass will
try to call this method in $classObject.
I use this for 'extending' a UserObject-Class which already extends an other one.
Better solutions are always welcome ;)

Drico Filho 23-Jan-2007 07:33


Since PHP 5.2.0, you'll always get an error like this:
"Object of class foo could not be converted to string"
When one tries to use an object as string, for instance:
class Test{}
echo new Test();
Thus, one way to avoid this problem is to programme the magic method __toString.
However, in the older versions, it would output a string saying that it was an object together a unique obj id. Therefore, the
__toString() method must comply with this behaviour.
My suggestion:
class Test{
function __toString(){
if(!isset($this->__uniqid))
$this->__uniqid = md5(uniqid(rand(), true));
return(get_class($this)."@".$this->__uniqid);
}
}
echo new Test();
would output something like this:
Test@6006ba04f5569544c10a588b04849cf7

jstubbs at work-at dot co dot jp 02-Sep-2006 12:32


$myclass->foo['bar'] = 'baz';
When overriding __get and __set, the above code can work (as expected) but it depends on your __get implementation rather than
your __set. In fact, __set is never called with the above code. It appears that PHP (at least as of 5.1) uses a reference to

whatever was returned by __get. To be more verbose, the above code is essentially identical to:
$tmp_array = &$myclass->foo;
$tmp_array['bar'] = 'baz';
unset($tmp_array);
Therefore, the above won't do anything if your __get implementation resembles this:
function __get($name) {
return array_key_exists($name, $this->values)
? $this->values[$name] : null;
}
You will actually need to set the value in __get and return that, as in the following code:
function __get($name) {
if (!array_key_exists($name, $this->values))
$this->values[$name] = null;
return $this->values[$name];
}

taylorbarstow at google's mail service 15-May-2006 01:54


I've just come accross something interesting relating to storing PHP5 objects in a session. If you don't provide an
__autoload(), then you MUST load the class definition before calling session_start(). I guess that when you call
session_start(), any objects in the session are unserialized then and there and placed into $_SESSION. If you don't provide
the class definition before calling session_start(), your object will get the class __PHP_Incomplete_Class, and you won't be
able to use it for anything.
Examples:
<?php
session_start();
require_once 'MyClass.php';
$obj = new MyClass;
$_SESSION['obj'] = $obj;
?>
Works fine. Then on a subsequent page load:
<?php
session_start();
require_once 'MyClass.php';
$_SESSION['obj']->callSomeMethod();
?>
Fatal error: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class
definition "MyClass" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a
__autoload() function to load the class definition.
But if you do this instead, it works fine:
<?php
require_once 'MyClass.php';
session_start();
$_SESSION['obj']->callSomeMethod();
?>
Hopefully in some future release of PHP, __PHP_Incomplete_Class will be smart enough to check for a class definition at time of

use (method call or property operation), and, if the class exists, magically "complete" itself and turn into the desired
object.

rayRO 02-Apr-2006 09:55


If you use the Magical Method '__set()', be shure that the call of
<?php
$myobject->test['myarray'] = 'data';
?>
will not appear!
For that u have to do it the fine way if you want to use __set Method ;)
<?php
$myobject->test = array('myarray' => 'data');
?>
If a Variable is already set, the __set Magic Method already wont appear!
My first solution was to use a Caller Class.
With that, i ever knew which Module i currently use!
But who needs it... :]
There are quiet better solutions for this...
Here's the Code:
<?php
class Caller {
public $caller;
public $module;
function __call($funcname, $args = array()) {
$this->setModuleInformation();
if (is_object($this->caller) && function_exists('call_user_func_array'))
$return = call_user_func_array(array(&$this->caller, $funcname), $args);
else
trigger_error("Call to Function with call_user_func_array failed", E_USER_ERROR);

$this->unsetModuleInformation();
return $return;
}
function __construct($callerClassName = false, $callerModuleName = 'Webboard') {
if ($callerClassName == false)
trigger_error('No Classname', E_USER_ERROR);
$this->module = $callerModuleName;
if (class_exists($callerClassName))
$this->caller = new $callerClassName();
else
trigger_error('Class not exists: \''.$callerClassName.'\'', E_USER_ERROR);
if (is_object($this->caller))
{
$this->setModuleInformation();
if (method_exists($this->caller, '__init'))
$this->caller->__init();
$this->unsetModuleInformation();
}

else
trigger_error('Caller is no object!', E_USER_ERROR);
}
function __destruct() {
$this->setModuleInformation();
if (method_exists($this->caller, '__deinit'))
$this->caller->__deinit();
$this->unsetModuleInformation();
}
function __isset($isset) {
$this->setModuleInformation();
if (is_object($this->caller))
$return = isset($this->caller->{$isset});
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
return $return;
}
function __unset($unset) {
$this->setModuleInformation();
if (is_object($this->caller)) {
if (isset($this->caller->{$unset}))
unset($this->caller->{$unset});
}
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
}
function __set($set, $val) {
$this->setModuleInformation();
if (is_object($this->caller))
$this->caller->{$set} = $val;
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
}
function __get($get) {
$this->setModuleInformation();
if (is_object($this->caller)) {
if (isset($this->caller->{$get}))
$return = $this->caller->{$get};
else
$return = false;
}
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
return $return;
}

function setModuleInformation() {
$this->caller->module = $this->module;
}
function unsetModuleInformation() {

$this->caller->module = NULL;
}
}
// Well this can be a Config Class?
class Config {
public $module;
public $test;
function __construct()
{
print('Constructor will have no Module Information... Use __init() instead!<br />');
print('--> '.print_r($this->module, 1).' <--');
print('<br />');
print('<br />');
$this->test = '123';
}

function __init()
{
print('Using of __init()!<br />');
print('--> '.print_r($this->module, 1).' <--');
print('<br />');
print('<br />');
}

function testFunction($test = false)


{
if ($test != false)
$this->test = $test;
}
}
echo('<pre>');
$wow = new Caller('Config', 'Guestbook');
print_r($wow->test);
print('<br />');
print('<br />');
$wow->test = '456';
print_r($wow->test);
print('<br />');
print('<br />');
$wow->testFunction('789');
print_r($wow->test);
print('<br />');
print('<br />');
print_r($wow->module);
echo('</pre>');
?>
Outputs something Like:
Constructor will have no Module Information... Use __init() instead!
--> <-Using of __init()!
--> Guestbook <-123

456
789
Guestbook

ksamvel at gmail dot com 10-Feb-2006 09:29


To copy base part of derived class appropriate method in base should be defined. E.g.:
class A {
public function setAVar( $oAVar) { $this->oAVar = $oAVar; }
public function getAVar() { return $this->oAVar; }
public function copyA( &$roDest) {
if( $roDest instanceof A)
$this->oAVar = $roDest->oAVar;
}
private $oAVar;
}
class B extends A {
public function setBVar( $oBVar) { $this->oBVar = $oBVar; }
public function getBVar() { return $this->oBVar; }
private $oBVar;
}
$oA = new A();
$oB = new B();
$oA->setAVar( 4);
$oB->setAVar( 5);
$oB->setBVar( 6);
echo "oA::oAVar " . $oA->getAVar() . "<br>";
echo "oB::oAVar " . $oB->getAVar() . "<br>";
echo "oB::oBVar " . $oB->getBVar() . "<br>";
echo "<br>";
$oB->copyA( $oA);
echo "oA::oAVar " . $oA->getAVar() . "<br>";
echo "oB::oAVar " . $oB->getAVar() . "<br>";
echo "oB::oBVar " . $oB->getBVar() . "<br>";
Output:
oA::oAVar 4
oB::oAVar 5
oB::oBVar 6
oA::oAVar 4
oB::oAVar 4
oB::oBVar 6

b dot schoppmeier at bas-consult dot de 26-Jan-2006 03:18


The sequence of events regarding __sleep and __destruct is unusual __ as __destruct is called before __sleep. The following
code snippet:
<?php
$sequence = 0;
class foo {
public $stuff;
public function __construct($param) {
global $sequence;
echo "Seq: ", $sequence++, " - constructor\n";
$this->stuff = $param;
}
public function __destruct() {
global $sequence;
echo "Seq: ", $sequence++, " - destructor\n";
}
public function __sleep() {
global $sequence;
echo "Seq: ", $sequence++, " - __sleep\n";
return array("stuff");
}
public function __wakeup() {
global $sequence;
echo "Seq: ", $sequence++, " - __wakeup\n";
}
}
session_start();
$_SESSION["obj"] = new foo("A foo");
?>
yields the output:
Seq: 0 - constructor
Seq: 1 - destructor
Seq: 2 - __sleep
Only when you end your script with a call to session_write_close() as in:
<?php
$sequence = 0;
class foo {
public $stuff;
public function __construct($param) {
global $sequence;
echo "Seq: ", $sequence++, " - constructor\n";
$this->stuff = $param;
}
public function __destruct() {
global $sequence;
echo "Seq: ", $sequence++, " - destructor\n";
}
public function __sleep() {
global $sequence;
echo "Seq: ", $sequence++, " - __sleep\n";
return array("stuff");
}
public function __wakeup() {
global $sequence;

echo "Seq: ", $sequence++, " - __wakeup\n";


}
}
session_start();
$_SESSION["obj"] = new foo("A foo");
session_write_close();
?>
the sequence is as common sense would expect it to be as the following output shows:
Seq: 0 - constructor
Seq: 1 - __sleep
Seq: 2 - destructor

docey 09-Dec-2005 08:44


about __sleep and _wakeup, consider using a method like this:
class core
{
var $sub_core; //ref of subcore
var $_sleep_subcore; // place where serialize version of sub_core will be stored
function core(){
$this->sub_core = new sub_core();
return true;
}
function __wakeup()
{
// on wakeup of core, core unserializes sub_core
// wich it had stored when it was serialized itself
$this->sub_core = unserialize($this->_sleep_subcore);
return true;
}
function __sleep()
{
// sub_core will be serialized when core is serialized.
// the serialized subcore will be stored as a string inside core.
$this->_sleep_subcore = serialize($this->sub_core);
$return_arr[] = "_sleep_subcore";
return $return_arr;
}
}
class sub_core
{
var $info;
function sub_core()
{
$this->info["somedata"] = "somedata overhere"
}
function __wakeup()
{

return true;
}
function __sleep()
{
$return_arr[] = "info"
return $return_arr;
}
}
this way subcore is being serialized by core when core is being serialized. subcore handles its own data and core stores it as
a serialize string inside itself. on wakeup core unserializes subcore.
this may have a performance cost, but if you have many objects connected this way this is the best way of serializing them.
you only need to serialize the the main object wich will serialize all those below which will serialize all those below them
again. in effect causing a sort of chainreaction in wich each object takes care of its own info.
offcoarse you always need to store the eventualy serialized string in a safe place. somebody got experience with this way of
__wakeup and __sleep.
works in PHP4&5

martin dot goldinger at netserver dot ch 15-Aug-2005 04:47


When you use sessions, its very important to keep the sessiondata small, due to low performance with unserialize. Every class
shoud extend from this class. The result will be, that no null Values are written to the sessiondata. It will increase
performance.
<?
class BaseObject
{
function __sleep()
{
$vars = (array)$this;
foreach ($vars as $key => $val)
{
if (is_null($val))
{
unset($vars[$key]);
}
}
return array_keys($vars);
}
};
?>

jeffxlevy at gmail dot com 13-Aug-2005 06:26


Intriguing what happens when __sleep() and __wakeup() and sessions() are mixed. I had a hunch that, as session data is
serialized, __sleep would be called when an object, or whatever, is stored in _SESSION. true. The same hunch applied when
session_start() was called. Would __wakeup() be called? True. Very helpful, specifically as I'm building massive objects (well,
lots of simple objects stored in sessions), and need lots of automated tasks (potentially) reloaded at "wakeup" time. (for
instance, restarting a database session/connection).

mastabog at hotmail dot com 12-Aug-2005 05:06


In reply to krisj1010 at gmail.com below:

__sleep() handles protected/private properties very well. You should never rely on get_class_vars() to retrieve property names
since this function only returns the public properties. Use the Reflection API instead for that purpose. Better yet, if you
know which ones you want to save it is always faster to specify the return array manually.

Domenic Denicola 23-Jun-2005 08:52


This small sentence tripped me up for a half an hour:
"It is worth noting that the __toString method will only be called when it is directly combined with echo() or print()."
So code like this will _not_ work, even though you might think it would:
<?
//$x is some variable with a __toString method defined.
$y = "x's value is: " . $x;
$y = "x's value is: " . (string)$x;
?>
In _em_ both situations, $y will contain "x's value is: Object id #42" (or whatever object ID). So, the only recourse I guess
is this:
<?
$y = "x's value is: " . $x->__toString();
?>

elias 11-Apr-2005 09:48


The default toString output is very useful for visual debuggin
because it shows the object id.
There is no function to resolve the id directly(?), but you
can do this:
<?php
function __toString()
{
sscanf((string)$this, "Object id #%d", $id);
return "Object(Template) id #$id";
}
?>
HTH,
elias

ddavenport at newagedigital dot com 26-Jan-2005 11:09


One of the principles of OOP is encapsulation--the idea that an object should handle its own data and no others'. Asking base
classes to take care of subclasses' data, esp considering that a class can't possibly know how many dozens of ways it will be
extended, is irresponsible and dangerous.
Consider the following...
<?php
class SomeStupidStorageClass

{
public function getContents($pos, $len) { ...stuff... }
}
class CryptedStorageClass extends SomeStupidStorageClass
{
private $decrypted_block;
public function getContents($pos, $len) { ...decrypt... }
}
?>
If SomeStupidStorageClass decided to serialize its subclasses' data as well as its own, a portion of what was once an encrypted
thingie could be stored, in the clear, wherever the thingie was stored. Obviously, CryptedStorageClass would never have chosen
this...but it had to either know how to serialize its parent class's data without calling parent::_sleep(), or let the base
class do what it wanted to.
Considering encapsulation again, no class should have to know how the parent handles its own private data. And it certainly
shouldn't have to worry that users will find a way to break access controls in the name of convenience.
If a class wants both to have private/protected data and to survive serialization, it should have its own __sleep() method
which asks the parent to report its own fields and then adds to the list if applicable. Like so....
<?php
class BetterClass
{
private $content;
public function __sleep()
{
return array('basedata1', 'basedata2');
}
public function getContents() { ...stuff... }
}
class BetterDerivedClass extends BetterClass
{
private $decrypted_block;
public function __sleep()
{
return parent::__sleep();
}
public function getContents() { ...decrypt... }
}
?>
The derived class has better control over its data, and we don't have to worry about something being stored that shouldn't be.

krisj1010 at gmail.com 09-Jan-2005 12:09


If you are attempting to write an abstract/base class which automates the __sleep process in PHP5 you will run into some
trouble if the subclasses which are being serialized have private/protected variables you need to be serialized.
The reason is, even though get_class($this) within the base class will return the subclass -- get_class_vars(get_class($this))
will *not* return the subclass' protected/private variables. Which makes sense -- using OO principles.

However, when automating __sleep it becomes necissary to have access to the private/protected subclass variables because their
names have to be returned by __sleep.
So here is the work around:
<?php
public function __sleep()
{
... code ...
$sleepVars = array_keys((array)$this);
return $sleepVars;
}
?>
Even though array_keys includes more information about the variable names than just the variable names -- it still seems to
work appropriately.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Magic Methods
The function names __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(),
__sleep(), __wakeup(), __toString(), __invoke(), __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()


public array __sleep ( void )
void __wakeup ( void )
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.
Note:
It is not possible for __sleep() to return names of private properties in parent classes. Doing this will result
in an E_NOTICE level error. Instead you may use the Serializable interface.
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
classConnection
{
protected$link;
private$server,$username,$password,$db;

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

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

publicfunction__sleep()
{
returnarray('server','username','password','db');
}

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

__toString()
public string __toString ( void )
The __toString() method allows a class to decide how it will react when it is treated like a string. For example,
what echo $obj; will print. This method must return a string, as otherwise a fatal E_RECOVERABLE_ERROR level error is
emitted.
Example #2 Simple example
<?php
//Declareasimpleclass
classTestClass
{
public$foo;
publicfunction__construct($foo)
{
$this->foo=$foo;
}
publicfunction__toString()
{
return$this->foo;
}
}
$class=newTestClass('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.

__invoke()
mixed __invoke ([

$...

] )

The __invoke() method is called when a script tries to call an object as a function.
Note:
This feature is available since PHP 5.3.0.
Example #3 Using __invoke()
<?php
classCallableClass
{
publicfunction__invoke($x)
{
var_dump($x);
}
}
$obj=newCallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

The above example will output:


int(5)
bool(true)

__set_state()
static object __set_state ( array

$properties

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 #4 Using __set_state() (since PHP 5.1.0)
<?php
classA
{
public$var1;
public$var2;
publicstaticfunction__set_state($an_array)//AsofPHP5.1.0
{
$obj=newA;
$obj->var1=$an_array['var1'];
$obj->var2=$an_array['var2'];
return$obj;
}
}

$a=newA;
$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"
}

User Contributed Notes

Magic Methods

miguel dot perez at afina dot es 15-Jun-2012 08:17


Both __call and __invoke exist and do completely different things. Nice.

Voitcus at wp dot pl 15-Feb-2012 09:48


You don't need to serialize the class default values, only those which have changed. It might be important for large objects.
Note the example below, for simplicity, always serializes arrays and objects.
<?php
class MyBaseClass {
public $name='object'; // these are default class values
public $test=1;
public $test2; // equals to NULL in fact
public function __construct(){
$this->test2='some text'; // this is not a default value, although called in the constructor
}
public function __sleep(){
// default class values:
$defaults=get_class_vars(get_class($this)); // not __CLASS__ or self::, if you'd like to use in descendant classes
// values of $this object:
$present=get_object_vars($this);
$result=array(); // output array
foreach($present as $key=>$value){
if(!is_resource($defaults[$key]) && ( // don't store resources
is_object($defaults[$key]) || // always store objects
is_array($defaults[$key]) || // and arrays
$defaults[$key]!==$value) // and of course all that is not the default value
) // tip: try is_scalar as well
$result[]=$key;
}

return $result;
}
}
$obj1=new MyBaseClass();
echo ($s1=serialize($obj1))."<br>"; // only test2 is stored, as it was changed in the constructor
$obj2=new MyBaseClass();
$obj2->name='object 2'; // change default value here
echo ($s2=serialize($obj2))."<br>"; // stored name and test2
$obj3=new MyBaseClass();
$obj3->test2=NULL; // switch back to default value
echo ($s3=serialize($obj3))."<br>"; // nothing is stored but the class name
// let us check if we can retrieve the objects
unset($obj1, $obj2, $obj3);
$obj1=unserialize($s1);
$obj2=unserialize($s2);
$obj3=unserialize($s3);
var_dump($obj1);
var_dump($obj2);
var_dump($obj3);
?>

daan dot broekhof at gmail dot com 14-Feb-2012 10:54


Ever wondered why you can't throw exceptions from __toString()? Yeah me too.
Well now you can! This trick allows you to throw any type of exception from within a __toString(), with a full & correct
backtrace.
How does it work? Well PHP __toString() handling is not as strict in every case: throwing an Exception from __toString()
triggers a fatal E_ERROR, but returning a non-string value from a __toString() triggers a non-fatal E_RECOVERABLE_ERROR.
Add a little bookkeeping, and can circumvented this PHP deficiency!
(tested to work PHP 5.3+)
<?php
set_error_handler(array('My_ToStringFixer', 'errorHandler'));
error_reporting(E_ALL | E_STRICT);
class My_ToStringFixer
{
protected static $_toStringException;
public static function errorHandler($errorNumber, $errorMessage, $errorFile, $errorLine)
{
if (isset(self::$_toStringException))
{
$exception = self::$_toStringException;
// Always unset '_toStringException', we don't want a straggler to be found later if something came between the
setting and the error
self::$_toStringException = null;
if (preg_match('~^Method .*::__toString\(\) must return a string value$~', $errorMessage))
throw $exception;
}
return false;
}


public static function throwToStringException($exception)
{
// Should not occur with prescribed usage, but in case of recursion: clean out exception, return a valid string, and
weep
if (isset(self::$_toStringException))
{
self::$_toStringException = null;
return '';
}
self::$_toStringException = $exception;
return null;
}
}
class My_Class
{
public function doComplexStuff()
{
throw new Exception('Oh noes!');
}
public function __toString()
{
try
{
// do your complex thing which might trigger an exception
return $this->doComplexStuff();
}
catch (Exception $e)
{
// The 'return' is required to trigger the trick
return My_ToStringFixer::throwToStringException($e);
}
}
}
$x = new My_Class();
try
{
echo $x;
}
catch (Exception $e)
{
echo 'Caught Exception! : '. $e;
}
?>

osbertv at yahoo dot com 29-Dec-2011 09:42


Invoking a class inside a class results in an error.
<?php
class A
{
public function __invoke()

{
echo "Invoking A() Class";
}
}
class B
{
public $a;

public function __construct()


{
$this->a = new A();
}

public function __invoke()


{
echo "Invoking B() Class";
}
}
$a = new A();
$b = new B();
$a();
$b();
$b->a();
?>
returns
Invoking B() Class
PHP Fatal error: Call to undefined method B::a()

hyponiq at gmail dot com 26-Sep-2011 06:07


I think it's fair to note the undocumented fact that the __invoke magic method can take any number of arguments (or none).
Example:
<?php
class InvokeNoParams {
function __invoke()
{
print __METHOD__ . PHP_EOL;
$i = 1;
foreach (func_get_args() as $arg) {
print "The value of \$param{$i} is: " . $arg . PHP_EOL;
++$i;
}
print PHP_EOL;
}
}

class InvokeSingleParam {
function __invoke($param1)
{
print __METHOD__ . PHP_EOL;
print "Value of \$param1 is: " . $param1 . PHP_EOL . PHP_EOL;
}
}

class InvokeMultiParams {
function __invoke($param1, $param2, $param3) {
print __METHOD__ . PHP_EOL;
print "Value of \$param1 is: " . $param1 . PHP_EOL;
print "Value of \$param2 is: " . $param2 . PHP_EOL;
print "Value of \$param3 is: " . $param3 . PHP_EOL . PHP_EOL;
}
}

$no = new InvokeNoParams;


$single = new InvokeSingleParam;
$multi = new InvokeMultiParams;

$no(1, 2, 3);
$single('one param');
$multi('param 1', 'param 2', 'param 3');
?>
This outputs:
InvokeNoParams::__invoke
The value of $param1 is: 1
The value of $param2 is: 2
The value of $param3 is: 3
InvokeSingleParam::__invoke
Value of $param1 is: one param
InvokeMultiParams::__invoke
Value of $param1 is: param 1
Value of $param2 is: param 2
Value of $param3 is: param 3

Wesley 25-May-2011 12:10


Warning __toString can be triggerd more then one time
<?php
if(strstr(substr($obj,0,1024), 'somestuff')
echo $obj;
return 'missing somestuff at the start, create container!';
substr() will trigger a __toString aswell as echo $obj;
?>
wich cause a performance issue since it will gather all data twice.
what i used as a hotfix:
<?php
__toString(){
if(null === $this->sToString)
$this->sToString = $this->_show();
return $this->sToString;
}
?>

Sammaye 18-Aug-2010 08:13

Thought I would just explain something about __get and __set here.
Imgine you have a class like so:
<?php
class user_bo{
protected $attributes = Array();

public function __get($key){



return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null;
}

public function __set($key, $value){

$this->attributes[$key] = $value;
}

/** Constructor **/
public function __construct(){}
}
?>
now imagine you add a function like so to this class:
<?php
public function update(){
global $database;

$fields = $database->connection->getTable("users");

$set = "";
foreach($fields as $field => $info){

if(isset($this->$field)){
if($this->$field == "now()"){
$set .= $field."=".mysql_real_escape_string($this->$field).", ";
}elseif($this->$field == null){
$set .= $field."=null, ";
}else{
$set .= $field."='".mysql_real_escape_string($this->$field)."', ";
}
}
}
$output_set = substr($set, 0, -2);

$query = "UPDATE users SET $output_set WHERE sequal_user_id = '$this->sequal_user_id'";
mysql_query($query) or sqlerrorhandler("(".mysql_errno().") ".mysql_error(), $query, $_SERVER['PHP_SELF'], __LINE__);

return true;
}
?>
The if(isset($this->$field)) will return false everytime. Instead of isset in loops like this you should use ($this->$field).
isset returns false even when the field is populated and in theory it should never return false since in my __get:
<?php
return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null;

?>
I return null if my variable don't exist.

Anonymous 24-Jul-2010 07:41


Concerning __set() with protected/private/overloaded properties, the behavior might not be so intuitive without knowing some
underlying rules. Consider this test object for the following examples...
<?php
class A {
protected $test_int = 2;
protected $test_array = array('key' => 'test');
protected $test_obj;

function __construct() {
$this->test_obj = new stdClass();
}

function __get($prop) {
return $this->$prop;
}

function __set($prop, $val) {
$this->$prop = $val;
}
}
$a = new A();
?>
Combined Operators (.=, +=, *=, etc): you must also define a companion __get() method to grant write -and- read access to the
property. Remember, "$x += $y" is shorthand for "$x = $x + $y". In other words, "__set($x, (__get($x) + $y))".
Properties that are Arrays: attempting to set array values like "$a->test_array[] = 'asdf';" from outside this object will
result in an "Indirect modification of overloaded property" notice and the operation completely ignored. You can't use '[]'
for array value assignment in this context (with the exception only if you made __get() return by reference, in which case, it
would work fine and bypass the __set() method altogether). You can work around this doing something like unioning the array
instead:
<?php
$a->test_array[] = 'asdf'; // notice given and ignored unless __get() was declared to return by reference
$a->test_array += array(1 => 'asdf'); // to add a key/value
$a->test_array = array("key" => 'asdf') + $a->test_array; // to overwrite a key/value.
?>
Properties that are Objects: as long as you have that __get() method, you can freely access and alter that sub object's own
properties, bypassing __set() entirely. Remember, objects are assigned and passed by reference naturally.
<?php
$a->test_obj->prop = 1; // fine if $a did not have a set method declared.
?>
All above tested in 5.3.2.

tom 18-Jul-2010 03:20


Note a common pitfall when using __wakeup.
If you unserialize a datastructure, you may not rely on the parent object to have been fully unserialized by the time __wakeup
is called. Example
<?php
class A {
public $b;
public $name;
}
class B extends A {
public $parent;
public function __wakeup() {
var_dump($parent->name);
}
}
$a = new A();
$a->name = "foo";
$a->b = new B();
$a->b->parent = $a;
$s = serialize($a);
$a = unserialize($s);
?>
Expected output: "foo".
Actual output: NULL.
Reason: $b is unserialized before $name. By the time B::__wakeup is called, $a->name does not yet have a value.
So be aware that the order in which your class variables are defined is important! You need to manually order them by
dependencies - or write a __sleep function and order them by depencies there. (Currently I can't tell which option I hate more)

Anonymous 30-Jun-2010 09:29


C++-style operator overloading finally makes an appearance with the introduction to __invoke(). Unfortunately, with just
'()'. In that sense, it is no more useful than having a default class method (probably quite useful actually) and not having
to type out an entire method name. Complimenting wbcarts at juno dot com's point class below, the following allows calculating
distance between one or more graph points...
<?php
class point {
public $x;
public $y;
function __construct($x=0, $y=0) {
$this->x = (int) $x;
$this->y = (int) $y;
}

function __invoke() {
$args = func_get_args();
$total_distance = 0;
$current_loc = $this;

foreach ($args as $arg) {


if (is_object($arg) and (get_class($arg) === get_class($this))) {
$total_distance += sqrt(pow($arg->x - $current_loc->x, 2) + pow((int) $arg->y - $current_loc->y, 2));
$current_loc = $arg;
}
else {
trigger_error("Arguments must be objects of this class.");
return;
}
}
return $total_distance;
}

}
$p1 = new point(1,1);
$p2 = new point(23,-6);
$p3 = new point(15,20);
echo $p1($p2,$p3,$p1); // round trip 73.89
?>
Functionally, __invoke() can also be used to mimic the use of variable functions. Sadly, attempting any calling of __invoke()
on a static level will produce a fatal error.

tfn dot yldrm at hotmail dot com 15-Jun-2010 03:26


Properties can be used for getter and setter as C# methods get_PropertyName and set_PropertyName for full event-based
programming.
<?php
/**
* @author Tufan Baris YILDIRIM
* @name getter and setter magics.
*/
Class GetSet
{
public $Name,$Surname; // they will be deleted those only for autocompletion.
private $_Name,$_Surname;
public function __construct()
{
foreach(get_class_vars('GetSet') as $varName=>$varValue)
{
if(substr($varName,0,1)!="_")
unset($this->$varName);
}
}
public function __get($varName)
{
if(method_exists($this,$MethodName='get_'.$varName))
return $this->$MethodName();
else
trigger_error($varName.' is not avaliable .',E_USER_ERROR);
}
public function __set($varName,$value)

{
if(method_exists($this,$MethodName='set_'.$varName))
return $this->$MethodName($value);
else
trigger_error($varName.' is not avaliable .',E_USER_ERROR);
}
private function set_Surname($value)
{
// On surname changed Events.
echo "Surname Changed as ".$value."\r\n";
$this->_Surname=$value;
}
private function get_Surname()
{
// On Get Events.
echo "Surname Getted\r\n";
return $this->_Surname;
}
private function set_Name($value)
{
// On Name changed Events.
echo "Name Changed as ".$value."\r\n";
$this->_Name=$value;
}
private function get_Name()
{
// On Get Name Events.
echo "Name getted\r\n";
return $this->_Name;
}
}
?>
Using :
<?php
$get=new GetSet();
$get->Name="Tufan Baris";
$get->Surname="YILDIRIM";
echo $get->Name.' '.$get->Surname;
?>
Output
Name Changed as Tufan Baris
Surname Changed asYILDIRIM
Name getted
Surname Getted
Tufan Baris YILDIRIM

xmontero at dsitelecom dot com 05-Dec-2009 08:01


This "tip" is for those who receive the error "Object of class X could not be converted to string" when __toString() is not
possible, and it is not a choice to process or not - for example when received via debug_backtrace().

HOW IT HAPPENED:
I use to have a logging function called LogEnter() and another called LogExit() that I use to call at every function when
intensively debugging.
For example all my functions look like:
<?php
function AnyFunction( $a, $b, $c )
{
LogEnter();
// DoSomeStuffHere.
LogExit();
}
?>
Then inside LogEnter(), I use debug_backtrace() to discover the parameters that were used when calling the function (in this
example the values of $a, $b, $c).
The LogEnter() deals without knowing the number of parameters to treat, and formats something like ( 2, 3, 4 ) if those were
the values. That info is printed among other info to a log-file.
Doing this, keeps me with a single-very-simple way to trace all te calls.
The thing is that if the the following are met at the same time, I have a problem:
- The function accepts (and is called with) a class as a parameter.
- The function is being debuggd by calling LogEnter();
- The class does not have __toString() coded.
- For some reason I am not allowed to edit the class nor inherit from it.
Then the debug function performs an "Object of class X could not be converted to string" error when trying to "dump" the
parameter list (containing the object) into the file.
LOG FUNCTION:
This looks for the "parameters array" and then calls BuildArgs to format them. LogWrite finds the function name, file, line
number, and so on, but does not matter here.
<?php
public function LogEnter()
{
$Debug = debug_backtrace();
$DebugLine = $Debug[ 1 ];
// [0] would be this very same function.
// [1] is the caller of this function.
$Args = isset( $DebugLine[ 'args' ] ) ? $DebugLine[ 'args' ] : '[x]';

$Msg = 'Entering with ' . BuildArgs( $Args );
LogWrite( $Msg );
}
// CAUTION, THIS NEXT ONE FAILS
private function BuildArgs( $Args )
{
$Result = '( ' . implode( ', ', $Args ) . ' )';
return $Result;

}
?>
The problem is that if you call a function where a parameter being an object that has not the __toString() defined, then
automatically "imploding" the argument list into a string, fails.
SOLUTION:
The solution is that the __toString is "checkable for its existance". The "tips" are to manually traverse the result of
debug_backtrace()['args'] and then, for each element, check:
- if it is or not an object with is_object( $Value )
- in case it is, check if __toString() is defined with method_exists( $Value, '__toString' )
- in case it is not an object or the method exist, perform a normal assignation.
- in case it is an object without that method, print something else. I choose to output the class name with get_class( $Value
) and put it between square brackets.
The final function becomes like this:
<?php
private function BuildArgs( $Args )
{
// This function gets an 'args' array from debug_backtrace() and formats it in the printable format (a, b, c) including the
parenthesis.

$FormattedParams = '';
$Glue = '';

foreach( $Args as $Value )
{
if( is_object( $Value ) )
{
if( method_exists( $Value, "__toString" ) )
{
$PrintableValue = $Value;
}
else
{
$PrintableValue = '[' . get_class( $Value ) . ']';
}
}
else
{
$PrintableValue = $Value;
}

$FormattedParams .= $Glue . $PrintableValue;
$Glue = ', ';
}

$Result = sprintf( '( %s )', $FormattedParams );

return $Result;
}
?>

vad dot viktor at gmail dot com 15-Oct-2009 03:06


If you are using __autoload to dynamically load your classes, then __invoke won't work. Calling a class like SomeClass() will

give and error in this case as it is evaluated first as a function, not as a class and so __autoload won't be triggered.

moechofe 25-Jul-2009 02:47


__invoke() cannot be used to create fluente interface like in the "D language"
<?php
class CallableClass
{
var $next;
function __invoke($x)
{
var_dump($x);
return $this;
}
}
$obj = new CallableClass;
$obj->next = new CallableClass;
var_dump( $obj(5) ); // OK!
var_dump( $obj(5)(6) ); // Parse error
var_dump( $obj->next(7) ); // Fatal error: Call to undefined method CallableClass::next()
var_dump( {$obj->next}(7) ); // Parse error
?>

zach at bygeekz dot com 25-May-2009 12:45


Try this one on.
<?php
$ret = new Test(true);
var_dump((bool)(string)$ret);
var_dump($ret);
$ret=null;
$ret = new Test();
var_dump((bool)(string)$ret);
var_dump($ret);
class Test {
protected $state=null;
function __construct($state=null) {
$this->state = $state;
}
function __toString() {
if ($this->state) { return "1"; } else { return "0"; }
}
}
?>
You could for instance do..
if(!(bool)(string)$ret) { do_something!; }
Alternatively, just make state public, and check it.
if(!$ret->state) {}.
There is no automatic way I have found aside from some internal state check to verify a class. It will always return an
object. The only way around that is to force it out to string either where I did, or $ret = (string) new Test(); then test the

bool of your output..


if (!$ret) { echo "noooo!"; }
But now you have no calling methods, so I hope you passed some data in to get a usable string out.
Of course, if your class isn't named test, you can add a method..
public function test() {
return $this->state;
}
Logically that will work regardless of the _toString(), but I had hoped to post this to help others see that there are a
multitude of ways to check the validity of a class once it is loaded. In __construct you can add any number of checks and set
your state appropriately.

jahanaddison6 at hotmail dot com 03-May-2009 03:16


If you're expecting this code to work think again:
<?php
class Example
{
public function __construct()
{
return false;
}
public function Test()
{
return true;
}
}
?>
The above code will not work as expected, The Test method will still return true.

rudie-de-hotblocks at osu1 dot php dot net 09-Apr-2009 06:35


Note also that the constructor is executed also, and before __set_state(), making this magic function less magic, imho, (except
for the ability to assign private members).

muratyaman at gmail dot com 07-Jan-2009 07:54


Regarding __toString:
<?php
class my_tag_A{
public $id='';
public $href='';
public $target='';
public $class='';

public $label='';

function __construct($href, $label){


$this->href = $href;

$this->label = $label;
}

public function __toString(){


return '<a '.$this->nz_arr(array('id', 'href', 'target', 'class')). ' >' . $this->label . '</a>';
}

function nz_arr($attrib_arr){
$s = '';
foreach($attrib_arr as $attrib){
$s .= $this->nz($attrib);
}
return $s;
}
/**
* Print the tag attribute if it is not blank, such as id="$this->id"
* @param string $attrib
* @return string
*/
function nz($attrib){
$s = '';
if($this->$attrib != '') $s = $attrib .' = "' . $this->$attrib . '"';
return $s;
}
//This causes RECURSION because of parsing between double quotes. This is a very UNEXPECTED behaviour!
function nz_($attrib){
$s = '';
if($this->$attrib != '') $s = "$attrib = \"$this->$attrib\"";
return $s;
}

}//end class
//usage
$a = new my_tag_A('abc.php', 'ABC'); $a->target = '_blank';
echo $a;
//prints:
// <a href="abc.php" target="_blank" >ABC</a>
?>

jsnell at e-normous dot com 03-Dec-2008 02:01


Be very careful to define __set_state() in classes which inherit from a parent using it, as the static __set_state() call will
be called for any children. If you are not careful, you will end up with an object of the wrong type. Here is an example:
<?php
class A
{
public $var1;
public static function __set_state($an_array)
{
$obj = new A;
$obj->var1 = $an_array['var1'];
return $obj;
}
}

class B extends A {
}
$b = new B;
$b->var1 = 5;
eval('$new_b = ' . var_export($b, true) . ';');
var_dump($new_b);
/*
object(A)#2 (1) {
["var1"]=>
int(5)
}
*/
?>

patricknegri at gmail dot com 26-Oct-2008 03:57


Imports Pattern - Extend Classes in Real Time:
<?php
class BaseClass
{
var $__imported;
var $__imported_functions;

function __construct()
{
$__imported = Array();
$__imported_functions = Array();
}

function Imports($object)
{
$new_imports = new $object();
$imports_name = get_class($new_imports);
array_push( $__imported, Array($imports_name,$new_imports) );
$imports_function = get_class_methods($new_imports);
foreach ($imports_function as $i=>$function_name)
{
$this->__imported_functions[$function_name] = &$new_imports;
}
}

function __call($m, $a)


{
if (array_key_exists($m,$this->__imported_functions))
{
return call_user_func_array(Array($this->__imported_functions[$m],$m),$a);
}
throw new ErrorException ('Call to Undefined Method/Class Function', 0, E_ERROR);
}
}
class ExternalFunc
{
function TestB()
{

echo "External Imported!";


}
}
class B extends BaseClass
{
function __construct()
{
$this->Imports("ExternalFunc");
}

function Msg()
{
echo "Hello world<br />";
}
}
$b = new B();
$b->Msg();
// or call $b->Imports("ExternalFunc");
$b->TestB();
//$b->TestB(1,3,4);
?>

jon at webignition dot net 03-Oct-2008 07:26


The __toString() method is extremely useful for converting class attribute names and values into common string representations
of data (of which there are many choices). I mention this as previous references to __toString() refer only to debugging uses.
I have previously used the __toString() method in the following ways:
- representing a data-holding object as:
- XML
- raw POST data
- a GET query string
- header name:value pairs
- representing a custom mail object as an actual email (headers then body, all correctly represented)
When creating a class, consider what possible standard string representations are available and, of those, which would be the
most relevant with respect to the purpose of the class.
Being able to represent data-holding objects in standardised string forms makes it much easier for your internal
representations of data to be shared in an interoperable way with other applications.

wbcarts at juno dot com 02-Oct-2008 04:12


To be helpful, the __toString() method should return the class name and the state of all its properties inside square brackets.
<?php
class Point {
protected $x, $y;
public function __construct($xVal = 0, $yVal = 0) {
$this->x = $xVal;
$this->y = $yVal;
}

public function __toString() { // the function we're interested in...


return "Point[x=$this->x, y=$this->y]";
}
}
$point1 = new Point(10, 10);
$point2 = new Point(50, 50);
echo $point1 . '<br>';
echo $point2 . '<br><br>';
?>
Point[x=10, y=10]
Point[x=50, y=50]
Classes that include objects, should call that objects __toString() method.
<?php
class Line {
protected $start, $end;
public function __construct(Point $p1, Point $p2){
$this->start = $p1;
$this->end = $p2;
}
public function __toString() { // the function we're interested in...
return 'Line[start=' . $this->start->__toString() . // call __toString()
', end=' . $this->end->__toString() . ']'; // call __toString()
}
}
echo (new Line($point1, $point2));
?>
Line[start=Point[x=10, y=10], end=Point[x=50, y=50]]

rc @ nospam @ vorklift dot sea oh em 07-Aug-2008 07:03


A note: __wakeup occurs before saving the unserialization of an session object.
Therefore, $_SESSION['var']::__wakeup() setting $_SESSION['var'] = new Class() will fail and $_SESSION['var'] will remain
unchanged.
This means that if you have a pseudo-temporary object that contains a class to auto revert to, you have to revert that session
object in the initialization of the website rather than via a __wakeup() script.

Anonymous 31-May-2008 04:24


Serializing objects is problematic with references. This is solved redefining the __sleep() magic method. This is also
problematic when parent class has private variables since the parent object is not accessible nor its private variables from
within the child object.
I found a solution that seems working for classes that implements this __sleep() method, and for its subclasses. Without more
work in subclasses. The inheritance system does the trick.
Recursively __sleep() call parent' __sleep() and return the whole array of variables of the object instance to be serialized.
<?php

class foo {
}
class a {
private $var1;
function __construct(foo &$obj = NULL) {
$this->var1 = &$obj;
}
/** Return its variables array, if its parent exists and the __sleep method is accessible, call it and push the result into
the array and return the whole thing. */
public function __sleep() {
$a = array_keys(get_object_vars(&$this));
if (method_exists(parent, '__sleep')) {
$p = parent::__sleep();
array_push($a, $p);
};
return $a;
}
}
class b extends a {
function __construct(foo &$obj = NULL) {
parent::__construct($obj);
}
}
session_start();
$myfoo = &new foo();
$myb = &new b($myfoo);
$myb = unserialize(serialize(&$myb));
?>
This should work, I haven't tested deeper.

yanleech at gmail dot com 10-May-2008 06:24


Maybe we can using unserialize() & __wakeup() instead "new" when creating a new instance of class.
Consider following codes:
class foo
{
static public $WAKEUP_STR = 'O:3:"foo":0:{}';
public function foo(){}
public function bar(){}
}
$foo = unserialize(foo::$WAKEUP_STR);

michal dot kocarek at seznam dot cz 18-Apr-2008 02:34


Remember that setters and getters (__set, __get) will work in your class as long as you NOT SET the property with given name.
If you still want to have the public property definition in the class source code (phpDocumentor, editor code completition, or
any other reason) when using these magic methods, simply unset() your public properties inside the constructor.
__set/__get function will be called and code reader will see at first sight, which public properties are available.

Example:
<?php
class user {
/**
* @var int Gets and sets the user ID
*/
public $UserID;
private $_userID;
public function __construct() {
// All the magic is in single line:
// We unset public property, so our setters and getters
// are used and phpDoc and editors with code completition are happy
unset($this->UserID);
}
public function __set($key, $value) {
// assign value for key UserID to _userID property
}
public function __get($key) {
// return value of _userID for UserID property
}
}
?>

dhuseby domain getback tld com 29-Feb-2008 06:22


The above hint for using array_keys((array)$obj) got me investigating how to get __sleep to really work with object
hierarchies.
With PHP 5.2.3, If you want to serialize an object that is part of an object hierarchy and you want to selectively serialize
members (public, private, and protected) by manually specifying the array of members, there are a few simple rules for naming
members that you must follow:
1. public members should be named using just their member name, like so:
<?php
class Foo {
public $bar;
public function __sleep() {
return array("bar");
}
}
?>
2. protected members should be named using "\0" . "*" . "\0" . member name, like so:
<?php
class Foo {
protected $bar;
public function __sleep() {
return array("\0*\0bar");
}

}
?>
3. private members should be named using "\0" . class name . "\0" . member name, like so:
<?php
class Foo {
private $bar;
public function __sleep() {
return array("\0Foo\0bar");
}
}
?>
So with this information let us serialize a class hierarchy correctly:
<?php
class Base {
private $foo = "foo_value";
protected $bar = "bar_value";
public function __sleep() {
return array("\0Base\0foo", "\0*\0bar");
}
}
class Derived extends Base {
public $baz = "baz_value";
private $boo = "boo_value";
public function __sleep() {
// we have to merge our members with our parent's
return array_merge(array("baz", "\0Derived\0boo"), parent::__sleep());
}
}
class Leaf extends Derived {
private $qux = "qux_value";
protected $zaz = "zaz_value";
public $blah = "blah_value";
public function __sleep() {
// again, merge our members with our parent's
return array_merge(array("\0Leaf\0qux", "\0*\0zaz", "blah"), parent::__sleep());
}
}
// test it
$test = new Leaf();
$s = serialize($test);
$test2 = unserialize($s);
echo $s;
print_r($test);
print_r($test2);
?>
Now if you comment out all of the __sleep() functions and output the serialized string, you will see that the output doesn't

change. The most important part of course is that with the proper __sleep() functions, we can unserialize the string and get a
properly set up object.
I hope this solves the mystery for everybody. __sleep() does work, if you use it correctly :-)

andrew dot minerd at sellingsource dot com 08-Nov-2007 07:55


Until __sleep is "fixed" (here's hoping), a function that will return ALL members of a given object -- public, protected, AND
private:
<?php
public function getPropertyNames(array $filter = NULL)
{
$rc = new ReflectionObject($this);
$names = array();
while ($rc instanceof ReflectionClass)
{
foreach ($rc->getProperties() as $prop)
{
if (!$filter || !in_array($prop->getName(), $filter))
$names[] = $prop->getName();
}
$rc = $rc->getParentClass();
}
return $names;
}
?>

amir_abiri at ipcmedia dot com 24-Jul-2007 04:58


Another small thing that is important to note about __sleep() and privte member variables:
<?php
class A
{
private $a;

public function __construct()


{
$this->a = 1;
}
}
class B extends A
{
protected $b;

public function __construct()


{
parent::__construct();
$this->b = 2;
}

function __sleep()
{

return array('a', 'b');


}
}
serialize(new B);
?>
result:
Notice: serialize(): "a" returned as member variable from __sleep() but does not exist in ...
To summerize: in a given class hierarchy in which parent classes contain private member variables, those variables are
serialized when __sleep() is not defined. However, once __sleep() is defined, there is no way to make those private member
variables serialized as well. From that point on, serialization is performed from the visibility scope of the subclass.
It is particularly important to note this little quirk when designing base classes that their derivables may be serialized, or
when subclassing an external library class.

alejandro dot gama at gmail dot com 09-May-2007 07:47


Referering my previus note: there was an error in the code. But i find a better way:
<?
session_start();
class Classes{
private $name;
private $statics;

function __construct($name){
$this->name=$name;
$this->statics=array();
}

function setStatic($k,$v){
if(!is_resource($v))
$this->statics[$k]=$v;
}

function __wakeup(){
foreach($this->statics as $k=>$v)
eval($this->name."::\$".$k."=\$this->statics['".$k."'];");
}
}
function storeStaticAttributes(){
$classes=get_declared_classes();
foreach($classes as $name){
$reflect=new ReflectionClass($name);
if($reflect->isUserDefined()){
$statics=$reflect->getStaticProperties();
if(empty($_SESSION["_classes"]))
$_SESSION["_classes"]=array();

if(empty($_SESSION["_classes"][$name]))
$_SESSION["_classes"][$name]=new Classes($name);

foreach($statics as $k=>$v)
$_SESSION["_classes"][$name]->setStatic($k,$v);
}
}
}
register_shutdown_function('storeStaticAttributes');
?>

Travis Swicegood 08-May-2007 07:43


There is no need to use eval() to mimic mixins (i.e., multiple inheritance) within PHP 5. You only need to:
<?php
class MyClass
{
private $_obj = null;
public function __construct($obj)
{
$this->_obj = $obj;
}
public function __call($method, $args)
{
if (!method_exists($this->_obj, $method)) {
throw new Exception("unknown method [$method]");
}
return call_user_func_array(
array($this->_obj, $method),
$args
);
}
}
?>
You could just as easily add an addMixin() method that would allow you to add multiple objects to an array, and then iterate
over that array until you found the right method. As noted, these are referred to as a Mixins in other languages.

adar at darkpoetry dot de 04-May-2007 06:09


Maybe not really new and all in all definitely not the best solution,but if you cant extend a class (if your class alreay
extends an abstract or other things like that) you can 'fake' a extend.
<?php
class MyClass
extends SomeAbstractUnknownClass {
private $classObject;
public function __construct ( classObject $classToExtend ) {
$this->classObject = $classToExtend;
}
public function __call($func, $var) {
if ( !count($var) ) {
return $this->classObject->$func($var);

} else {
$str = '';
$values = array_values($var);
for ( $i=0; $i<count($values); $i++ ) {
$str .= "'".$values[$i]."' ,";
}
$str = substr($str, 0, -2);
return eval('return $this->classObject->'.$func.'('.$str.');');
}
}
}
?>
So if you'll do a $myClass->unknownMethod() and it is found neither in MyClass nor in SomeAbstractUnknownClass, MyClass will
try to call this method in $classObject.
I use this for 'extending' a UserObject-Class which already extends an other one.
Better solutions are always welcome ;)

Drico Filho 23-Jan-2007 07:33


Since PHP 5.2.0, you'll always get an error like this:
"Object of class foo could not be converted to string"
When one tries to use an object as string, for instance:
class Test{}
echo new Test();
Thus, one way to avoid this problem is to programme the magic method __toString.
However, in the older versions, it would output a string saying that it was an object together a unique obj id. Therefore, the
__toString() method must comply with this behaviour.
My suggestion:
class Test{
function __toString(){
if(!isset($this->__uniqid))
$this->__uniqid = md5(uniqid(rand(), true));
return(get_class($this)."@".$this->__uniqid);
}
}
echo new Test();
would output something like this:
Test@6006ba04f5569544c10a588b04849cf7

jstubbs at work-at dot co dot jp 02-Sep-2006 12:32


$myclass->foo['bar'] = 'baz';
When overriding __get and __set, the above code can work (as expected) but it depends on your __get implementation rather than
your __set. In fact, __set is never called with the above code. It appears that PHP (at least as of 5.1) uses a reference to

whatever was returned by __get. To be more verbose, the above code is essentially identical to:
$tmp_array = &$myclass->foo;
$tmp_array['bar'] = 'baz';
unset($tmp_array);
Therefore, the above won't do anything if your __get implementation resembles this:
function __get($name) {
return array_key_exists($name, $this->values)
? $this->values[$name] : null;
}
You will actually need to set the value in __get and return that, as in the following code:
function __get($name) {
if (!array_key_exists($name, $this->values))
$this->values[$name] = null;
return $this->values[$name];
}

taylorbarstow at google's mail service 15-May-2006 01:54


I've just come accross something interesting relating to storing PHP5 objects in a session. If you don't provide an
__autoload(), then you MUST load the class definition before calling session_start(). I guess that when you call
session_start(), any objects in the session are unserialized then and there and placed into $_SESSION. If you don't provide
the class definition before calling session_start(), your object will get the class __PHP_Incomplete_Class, and you won't be
able to use it for anything.
Examples:
<?php
session_start();
require_once 'MyClass.php';
$obj = new MyClass;
$_SESSION['obj'] = $obj;
?>
Works fine. Then on a subsequent page load:
<?php
session_start();
require_once 'MyClass.php';
$_SESSION['obj']->callSomeMethod();
?>
Fatal error: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class
definition "MyClass" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a
__autoload() function to load the class definition.
But if you do this instead, it works fine:
<?php
require_once 'MyClass.php';
session_start();
$_SESSION['obj']->callSomeMethod();
?>
Hopefully in some future release of PHP, __PHP_Incomplete_Class will be smart enough to check for a class definition at time of

use (method call or property operation), and, if the class exists, magically "complete" itself and turn into the desired
object.

rayRO 02-Apr-2006 09:55


If you use the Magical Method '__set()', be shure that the call of
<?php
$myobject->test['myarray'] = 'data';
?>
will not appear!
For that u have to do it the fine way if you want to use __set Method ;)
<?php
$myobject->test = array('myarray' => 'data');
?>
If a Variable is already set, the __set Magic Method already wont appear!
My first solution was to use a Caller Class.
With that, i ever knew which Module i currently use!
But who needs it... :]
There are quiet better solutions for this...
Here's the Code:
<?php
class Caller {
public $caller;
public $module;
function __call($funcname, $args = array()) {
$this->setModuleInformation();
if (is_object($this->caller) && function_exists('call_user_func_array'))
$return = call_user_func_array(array(&$this->caller, $funcname), $args);
else
trigger_error("Call to Function with call_user_func_array failed", E_USER_ERROR);

$this->unsetModuleInformation();
return $return;
}
function __construct($callerClassName = false, $callerModuleName = 'Webboard') {
if ($callerClassName == false)
trigger_error('No Classname', E_USER_ERROR);
$this->module = $callerModuleName;
if (class_exists($callerClassName))
$this->caller = new $callerClassName();
else
trigger_error('Class not exists: \''.$callerClassName.'\'', E_USER_ERROR);
if (is_object($this->caller))
{
$this->setModuleInformation();
if (method_exists($this->caller, '__init'))
$this->caller->__init();
$this->unsetModuleInformation();
}

else
trigger_error('Caller is no object!', E_USER_ERROR);
}
function __destruct() {
$this->setModuleInformation();
if (method_exists($this->caller, '__deinit'))
$this->caller->__deinit();
$this->unsetModuleInformation();
}
function __isset($isset) {
$this->setModuleInformation();
if (is_object($this->caller))
$return = isset($this->caller->{$isset});
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
return $return;
}
function __unset($unset) {
$this->setModuleInformation();
if (is_object($this->caller)) {
if (isset($this->caller->{$unset}))
unset($this->caller->{$unset});
}
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
}
function __set($set, $val) {
$this->setModuleInformation();
if (is_object($this->caller))
$this->caller->{$set} = $val;
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
}
function __get($get) {
$this->setModuleInformation();
if (is_object($this->caller)) {
if (isset($this->caller->{$get}))
$return = $this->caller->{$get};
else
$return = false;
}
else
trigger_error('Caller is no object!', E_USER_ERROR);
$this->unsetModuleInformation();
return $return;
}

function setModuleInformation() {
$this->caller->module = $this->module;
}
function unsetModuleInformation() {

$this->caller->module = NULL;
}
}
// Well this can be a Config Class?
class Config {
public $module;
public $test;
function __construct()
{
print('Constructor will have no Module Information... Use __init() instead!<br />');
print('--> '.print_r($this->module, 1).' <--');
print('<br />');
print('<br />');
$this->test = '123';
}

function __init()
{
print('Using of __init()!<br />');
print('--> '.print_r($this->module, 1).' <--');
print('<br />');
print('<br />');
}

function testFunction($test = false)


{
if ($test != false)
$this->test = $test;
}
}
echo('<pre>');
$wow = new Caller('Config', 'Guestbook');
print_r($wow->test);
print('<br />');
print('<br />');
$wow->test = '456';
print_r($wow->test);
print('<br />');
print('<br />');
$wow->testFunction('789');
print_r($wow->test);
print('<br />');
print('<br />');
print_r($wow->module);
echo('</pre>');
?>
Outputs something Like:
Constructor will have no Module Information... Use __init() instead!
--> <-Using of __init()!
--> Guestbook <-123

456
789
Guestbook

ksamvel at gmail dot com 10-Feb-2006 09:29


To copy base part of derived class appropriate method in base should be defined. E.g.:
class A {
public function setAVar( $oAVar) { $this->oAVar = $oAVar; }
public function getAVar() { return $this->oAVar; }
public function copyA( &$roDest) {
if( $roDest instanceof A)
$this->oAVar = $roDest->oAVar;
}
private $oAVar;
}
class B extends A {
public function setBVar( $oBVar) { $this->oBVar = $oBVar; }
public function getBVar() { return $this->oBVar; }
private $oBVar;
}
$oA = new A();
$oB = new B();
$oA->setAVar( 4);
$oB->setAVar( 5);
$oB->setBVar( 6);
echo "oA::oAVar " . $oA->getAVar() . "<br>";
echo "oB::oAVar " . $oB->getAVar() . "<br>";
echo "oB::oBVar " . $oB->getBVar() . "<br>";
echo "<br>";
$oB->copyA( $oA);
echo "oA::oAVar " . $oA->getAVar() . "<br>";
echo "oB::oAVar " . $oB->getAVar() . "<br>";
echo "oB::oBVar " . $oB->getBVar() . "<br>";
Output:
oA::oAVar 4
oB::oAVar 5
oB::oBVar 6
oA::oAVar 4
oB::oAVar 4
oB::oBVar 6

b dot schoppmeier at bas-consult dot de 26-Jan-2006 03:18


The sequence of events regarding __sleep and __destruct is unusual __ as __destruct is called before __sleep. The following
code snippet:
<?php
$sequence = 0;
class foo {
public $stuff;
public function __construct($param) {
global $sequence;
echo "Seq: ", $sequence++, " - constructor\n";
$this->stuff = $param;
}
public function __destruct() {
global $sequence;
echo "Seq: ", $sequence++, " - destructor\n";
}
public function __sleep() {
global $sequence;
echo "Seq: ", $sequence++, " - __sleep\n";
return array("stuff");
}
public function __wakeup() {
global $sequence;
echo "Seq: ", $sequence++, " - __wakeup\n";
}
}
session_start();
$_SESSION["obj"] = new foo("A foo");
?>
yields the output:
Seq: 0 - constructor
Seq: 1 - destructor
Seq: 2 - __sleep
Only when you end your script with a call to session_write_close() as in:
<?php
$sequence = 0;
class foo {
public $stuff;
public function __construct($param) {
global $sequence;
echo "Seq: ", $sequence++, " - constructor\n";
$this->stuff = $param;
}
public function __destruct() {
global $sequence;
echo "Seq: ", $sequence++, " - destructor\n";
}
public function __sleep() {
global $sequence;
echo "Seq: ", $sequence++, " - __sleep\n";
return array("stuff");
}
public function __wakeup() {
global $sequence;

echo "Seq: ", $sequence++, " - __wakeup\n";


}
}
session_start();
$_SESSION["obj"] = new foo("A foo");
session_write_close();
?>
the sequence is as common sense would expect it to be as the following output shows:
Seq: 0 - constructor
Seq: 1 - __sleep
Seq: 2 - destructor

docey 09-Dec-2005 08:44


about __sleep and _wakeup, consider using a method like this:
class core
{
var $sub_core; //ref of subcore
var $_sleep_subcore; // place where serialize version of sub_core will be stored
function core(){
$this->sub_core = new sub_core();
return true;
}
function __wakeup()
{
// on wakeup of core, core unserializes sub_core
// wich it had stored when it was serialized itself
$this->sub_core = unserialize($this->_sleep_subcore);
return true;
}
function __sleep()
{
// sub_core will be serialized when core is serialized.
// the serialized subcore will be stored as a string inside core.
$this->_sleep_subcore = serialize($this->sub_core);
$return_arr[] = "_sleep_subcore";
return $return_arr;
}
}
class sub_core
{
var $info;
function sub_core()
{
$this->info["somedata"] = "somedata overhere"
}
function __wakeup()
{

return true;
}
function __sleep()
{
$return_arr[] = "info"
return $return_arr;
}
}
this way subcore is being serialized by core when core is being serialized. subcore handles its own data and core stores it as
a serialize string inside itself. on wakeup core unserializes subcore.
this may have a performance cost, but if you have many objects connected this way this is the best way of serializing them.
you only need to serialize the the main object wich will serialize all those below which will serialize all those below them
again. in effect causing a sort of chainreaction in wich each object takes care of its own info.
offcoarse you always need to store the eventualy serialized string in a safe place. somebody got experience with this way of
__wakeup and __sleep.
works in PHP4&5

martin dot goldinger at netserver dot ch 15-Aug-2005 04:47


When you use sessions, its very important to keep the sessiondata small, due to low performance with unserialize. Every class
shoud extend from this class. The result will be, that no null Values are written to the sessiondata. It will increase
performance.
<?
class BaseObject
{
function __sleep()
{
$vars = (array)$this;
foreach ($vars as $key => $val)
{
if (is_null($val))
{
unset($vars[$key]);
}
}
return array_keys($vars);
}
};
?>

jeffxlevy at gmail dot com 13-Aug-2005 06:26


Intriguing what happens when __sleep() and __wakeup() and sessions() are mixed. I had a hunch that, as session data is
serialized, __sleep would be called when an object, or whatever, is stored in _SESSION. true. The same hunch applied when
session_start() was called. Would __wakeup() be called? True. Very helpful, specifically as I'm building massive objects (well,
lots of simple objects stored in sessions), and need lots of automated tasks (potentially) reloaded at "wakeup" time. (for
instance, restarting a database session/connection).

mastabog at hotmail dot com 12-Aug-2005 05:06


In reply to krisj1010 at gmail.com below:

__sleep() handles protected/private properties very well. You should never rely on get_class_vars() to retrieve property names
since this function only returns the public properties. Use the Reflection API instead for that purpose. Better yet, if you
know which ones you want to save it is always faster to specify the return array manually.

Domenic Denicola 23-Jun-2005 08:52


This small sentence tripped me up for a half an hour:
"It is worth noting that the __toString method will only be called when it is directly combined with echo() or print()."
So code like this will _not_ work, even though you might think it would:
<?
//$x is some variable with a __toString method defined.
$y = "x's value is: " . $x;
$y = "x's value is: " . (string)$x;
?>
In _em_ both situations, $y will contain "x's value is: Object id #42" (or whatever object ID). So, the only recourse I guess
is this:
<?
$y = "x's value is: " . $x->__toString();
?>

elias 11-Apr-2005 09:48


The default toString output is very useful for visual debuggin
because it shows the object id.
There is no function to resolve the id directly(?), but you
can do this:
<?php
function __toString()
{
sscanf((string)$this, "Object id #%d", $id);
return "Object(Template) id #$id";
}
?>
HTH,
elias

ddavenport at newagedigital dot com 26-Jan-2005 11:09


One of the principles of OOP is encapsulation--the idea that an object should handle its own data and no others'. Asking base
classes to take care of subclasses' data, esp considering that a class can't possibly know how many dozens of ways it will be
extended, is irresponsible and dangerous.
Consider the following...
<?php
class SomeStupidStorageClass

{
public function getContents($pos, $len) { ...stuff... }
}
class CryptedStorageClass extends SomeStupidStorageClass
{
private $decrypted_block;
public function getContents($pos, $len) { ...decrypt... }
}
?>
If SomeStupidStorageClass decided to serialize its subclasses' data as well as its own, a portion of what was once an encrypted
thingie could be stored, in the clear, wherever the thingie was stored. Obviously, CryptedStorageClass would never have chosen
this...but it had to either know how to serialize its parent class's data without calling parent::_sleep(), or let the base
class do what it wanted to.
Considering encapsulation again, no class should have to know how the parent handles its own private data. And it certainly
shouldn't have to worry that users will find a way to break access controls in the name of convenience.
If a class wants both to have private/protected data and to survive serialization, it should have its own __sleep() method
which asks the parent to report its own fields and then adds to the list if applicable. Like so....
<?php
class BetterClass
{
private $content;
public function __sleep()
{
return array('basedata1', 'basedata2');
}
public function getContents() { ...stuff... }
}
class BetterDerivedClass extends BetterClass
{
private $decrypted_block;
public function __sleep()
{
return parent::__sleep();
}
public function getContents() { ...decrypt... }
}
?>
The derived class has better control over its data, and we don't have to worry about something being stored that shouldn't be.

krisj1010 at gmail.com 09-Jan-2005 12:09


If you are attempting to write an abstract/base class which automates the __sleep process in PHP5 you will run into some
trouble if the subclasses which are being serialized have private/protected variables you need to be serialized.
The reason is, even though get_class($this) within the base class will return the subclass -- get_class_vars(get_class($this))
will *not* return the subclass' protected/private variables. Which makes sense -- using OO principles.

However, when automating __sleep it becomes necissary to have access to the private/protected subclass variables because their
names have to be returned by __sleep.
So here is the work around:
<?php
public function __sleep()
{
... code ...
$sleepVars = array_keys((array)$this);
return $sleepVars;
}
?>
Even though array_keys includes more information about the variable names than just the variable names -- it still seems to
work appropriately.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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
classBaseClass{
publicfunctiontest(){
echo"BaseClass::test()called\n";
}

finalpublicfunctionmoreTesting(){
echo"BaseClass::moreTesting()called\n";
}
}
classChildClassextendsBaseClass{
publicfunctionmoreTesting(){
echo"ChildClass::moreTesting()called\n";
}
}
//ResultsinFatalerror:CannotoverridefinalmethodBaseClass::moreTesting()
?>

Example #2 Final class example


<?php
finalclassBaseClass{
publicfunctiontest(){
echo"BaseClass::test()called\n";
}
//Hereitdoesn'tmatterifyouspecifythefunctionasfinalornot
finalpublicfunctionmoreTesting(){
echo"BaseClass::moreTesting()called\n";
}
}
classChildClassextendsBaseClass{
}
//ResultsinFatalerror:ClassChildClassmaynotinheritfromfinalclass(BaseClass)
?>

Note: Properties cannot be declared final, only classes and methods may be declared as final.

User Contributed Notes

Final Keyword

Anonymous 28-Sep-2010 07:06

The behaviour of FINAL is not as serious as you may think. A little explample:
<?php
class A {
final private function method(){}
}
class B extends A {
private function method(){}
}
?>
Normally you would expect some of the following will happen:
- An error that final and private keyword cannot be used together
- No error as the private visibility says, that a method/var/etc. is only visible within the same class
But what happens is PHP is a little curios: "Cannot override final method A::method()"
So its possible to deny method names in subclasses! Don't know if this is a good behavior, but maybe its useful for your
purpose.

Baldurien 31-Aug-2010 01:37


"Note for Java developers: the 'final' keyword is not used for class constants in PHP. We use the keyword 'const'."
http://php.net/manual/en/language.oop5.constants.php
This is more or less true, regardless of the fact that constant (being defined at class level or not) in PHP are only scalar
(int, string, etc) while in Java they may be pure object (ex: java.awat.Color.BLACK). The only possible solution of having such
kind of constant is :
<?php
class Bar {...}
class Foo {
public static $FOOBAR;
static function __init() {
static $init = false;
if ($init) throw new Exception('Constants were already initialized');
self::$FOOBAR = new Bar();
$init = true;
}
}
Foo::__init();
?>
That said, perhaps it is useless unless PHP automatically calls the __init() method.
However, one alternative that could be done in certain case is this :
<?php
function __autoload($className) {
... require the file where the class is ...
if (interface_exists($className, false)) return;
if (class_exists($className, false)) {
$rc = new ReflectionClass($className);
if (!$rc->hasMethod('__init')) return;
$m = $rc->getMethod('__init');
if (!($m->isStatic() && $m->isPrivate())) {
throw new Exception($className . ' __init() method must be private and static !');
}

$m->invoke(null);
return;
}
throw new Exception('Class or interface not found ' . $className);
}
?>
This can only work when one class is defined per file, since we are assured that __autoload() will be called to load the file
containing the class.
eg:
test2.php:
<?php
class B {
public static $X;
private static function __init() {
echo 'B', "\n";
self::$X = array(1, 2);
}
}
class A {
public static $Y;
private static function __init() {
echo 'A', "\n";
self::$Y = array(3, 4);
}
}
?>
test.php:
<?php
function __autoload($n) {
if ($n == 'A' || $n == 'B') require 'test2.php';
... do our __init() trick ...
}
var_dump(B::$X); // shows B, then array(2) (1, 2)
var_dump(A::$Y); // shows NULL.
?>

Kiam 31-Jul-2009 04:49


The final keyword doesn't change the visibility of a property / method, which is public by default.

jriddy at gmail dot com 17-Jul-2009 02:20


Note for Java developers: the 'final' keyword is not used for class constants in PHP. We use the keyword 'const'.
http://php.net/manual/en/language.oop5.constants.php

sunil dot boodram at gmail dot com 18-Mar-2009 09:54


Using the scope resolution operator, we can easily access constants, static variables, public functions and final functions
from Final Classes
Note: even by omitting the "public" keyword from the "nightNews()" method, we can see that the function defaults to public even
if prefixed with the keyword final.
<?php

final class news{

const micCheck = "test1"; // will work


static public $promptCheck = "test2"; //will work

//will work
public function morningNews(){
print 'good morning world!';
}
//will work
final public function eveningNews(){
print 'good evening world!';
}
//will work
final function nightNews(){
print 'good night world!';
}
}
print news::micCheck; // output: test1
print '<br/>';
print news::$promptCheck; // output: test2
print '<br/>';
print news::morningNews(); // output: good morning world!
print '<br/>';
print news::eveningNews(); // output: good evening world!
print '<br/>';
print news::nightNews(); // output: good night world!
?>

santoshjoshi2003 at yahoo dot co dot in 05-Dec-2008 02:45


The use of final keyword is just like that occurs in Java
In java final has three uses
1) prevent class Inheritance
2) prevent method overriding or redifination of
method in subclass
3) and to declare constants
But the third point seems to be missing from the PHP
I guess, as i am a java developer Currently gaining competence in PHP

slorenzo at clug dot org dot ve 30-Oct-2007 11:13


<?php
class parentClass {
public function someMethod() { }
}
class childClass extends parentClass {
public final function someMethod() { } //override parent function
}
$class = new childClass;
$class->someMethod(); //call the override function in chield class
?>

penartur at yandex dot ru 22-Mar-2007 01:39


Note that you cannot ovverride final methods even if they are defined as private in parent class.
Thus, the following example:
<?php
class parentClass {
final private function someMethod() { }
}
class childClass extends parentClass {
private function someMethod() { }
}
?>
dies with error "Fatal error: Cannot override final method parentClass::someMethod() in ***.php on line 7"
Such behaviour looks slight unexpected because in child class we cannot know, which private methods exists in a parent class
and vice versa.
So, remember that if you defined a private final method, you cannot place method with the same name in child class.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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.
void __clone ( void )
Once the cloning is complete, 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
classSubObject
{
static$instances=0;
public$instance;
publicfunction__construct(){
$this->instance=++self::$instances;
}
publicfunction__clone(){
$this->instance=++self::$instances;
}
}
classMyCloneable
{
public$object1;
public$object2;
function__clone()
{
//Forceacopyofthis->object,otherwise
//itwillpointtosameobject.
$this->object1=clone$this->object1;
}
}
$obj=newMyCloneable();
$obj->object1=newSubObject();
$obj->object2=newSubObject();

$obj2=clone$obj;

print("OriginalObject:\n");
print_r($obj);
print("ClonedObject:\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
)
)

User Contributed Notes

Object Cloning

seriously at something dot com 06-Jun-2012 04:58


If you want a property that gets the same value in every clone if changed, you can do this simple trick:
<?php
class A
{
public static $name ;
}
$a = new A;
$a::$name = 'George';
$b = clone $a;

$b::$name = "Somebody else";


echo 'a: ' . $a::$name . "\n";
echo 'b: ' . $b::$name . "\n";
?>
this will output:
a: Somebody else
b: Somebody else
You can change any of the clones property and all of the others will change accordingly.

walkman at walkman dot pk 13-Oct-2011 05:11


If you want a property that gets the same value in every clone if changed, you can do this simple trick:
<?php
class A
{
public $name ;

public function __construct()


{
$this->name = & $this->name;
}
}
$a = new A;
$a->name = "George";
$b = clone $a;
$b->name = "Somebody else";
var_dump($a);
var_dump($b);
?>
this will output:
object(A)#1 (1) {
["name"]=>
&string(13) "Somebody else"
}
object(A)#2 (1) {
["name"]=>
&string(13) "Somebody else"
}
You can change any of the clones property and all of the others will change accordingly.

user at somethiong dot com 01-Apr-2011 04:35


Creating a Deep Copy
<?php

protected function deepCopy($object){


return unserialize(serialize($object));
}// End Function
?>

gratcypalma at gmail dot com 10-Nov-2010 08:12


this is my simple method, use class_alias function
<?php
class Y {
function __construct($a) {
$this -> a = $a;
}
function __destruct() {
echo $this -> a;
}
}
$mam = new Y('Foo');
class_alias('Y', 'bar'); // clone class use class_alias function
$m = new bar('Bar');
?>

jojor at gmx dot net 07-Jun-2010 01:47


Here is test script i wrote to test the behaviour of clone when i have arrays with primitive values in my class - as an
additonal test of the note below by jeffrey at whinger dot nl
<pre>
<?php
class MyClass {
private $myArray = array();
function pushSomethingToArray($var) {
array_push($this->myArray, $var);
}
function getArray() {
return $this->myArray;
}
}
//push some values to the myArray of Mainclass
$myObj = new MyClass();
$myObj->pushSomethingToArray('blue');
$myObj->pushSomethingToArray('orange');
$myObjClone = clone $myObj;
$myObj->pushSomethingToArray('pink');
//testing
print_r($myObj->getArray()); //Array([0] => blue,[1] => orange,[2] => pink)
print_r($myObjClone->getArray());//Array([0] => blue,[1] => orange)
//so array cloned
?>

</pre>

jeffrey at whinger dot nl 15-Apr-2010 05:41


For me it wasn't very clear to how this cloning of objects really worked so I made this little bit of code:
<?php
class foo
{
public $test;

public function test()


{
echo 'give us a '.$this->test."<br>\n";
}
}
class bar
{
public $foo;

public function insertFoo($foo)


{
$this->foo = $foo;
}
}
$foo = new foo();
$foo->test = 'foo';
$bar = new bar();
$bar->insertFoo($foo);
$foo->test();
$bar->foo->test();
$foo->test = 'bar';
$foo->test();
$bar->foo->test();
$bar->foo = clone $foo;
$bar->foo->test = 'woop woop';
$foo->test();
$bar->foo->test();
// result:
// give us a foo
// give us a foo
// give us a bar
// give us a bar
// give us a bar

// give us a woop woop


?>

henke at henke37 dot cjb dot net 10-Apr-2010 03:31


Arrays are shallow cloned on assignment, so don't use the clone keyword on them, just assign it to a new variable. That would
lead to an error instead.

olivier dot pons at goo dot without dot oo dot mail dot com 18-Mar-2010 10:14
If you think "clone" will create a new instance, thus calling "__constructor", you're wrong. clone seems to only allocate
memory for the object cloned, and simply copies the variables memory from the original to the new one (imagine something alike
memcpy() in C). Nothing more. Keep in mind you'll have to do all the rest by yourself.

emile at webflow dot nl 02-Mar-2010 01:27


Another gotcha I encountered: like __construct and __desctruct, you must call parent::__clone() yourself from inside a child's
__clone() function. The manual kind of got me on the wrong foot here: "An object's __clone() method cannot be called directly."

ben at last dot fm 05-Jun-2009 10:33


Here are some cloning and reference gotchas we came up against at Last.fm.
1. PHP treats variables as either 'values types' or 'reference types', where the difference is supposed to be transparent.
Object cloning is one of the few times when it can make a big difference. I know of no programmatic way to tell if a variable
is intrinsically a value or reference type. There IS however a non-programmatic ways to tell if an object property is value or
reference type:
<?php
class A { var $p; }
$a = new A;
$a->p = 'Hello'; // $a->p is a value type
var_dump($a);
/*
object(A)#1 (1) {
["p"]=>
string(5) "Hello" // <-- no &
}
*/
$ref =& $a->p; // note that this CONVERTS $a->p into a reference type!!
var_dump($a);
/*
object(A)#1 (1) {
["p"]=>
&string(5) "Hello" // <-- note the &, this indicates it's a reference.
}
*/
?>
2. unsetting all-but-one of the references will convert the remaining reference back into a value. Continuing from the previous
example:

<?php
unset($ref);
var_dump($a);
/*
object(A)#1 (1) {
["p"]=>
string(5) "Hello"
}
*/
?>
I interpret this as the reference-count jumping from 2 straight to 0. However...
2. It IS possible to create a reference with a reference count of 1 - i.e. to convert an property from value type to reference
type, without any extra references. All you have to do is declare that it refers to itself. This is HIGHLY idiosyncratic, but
nevertheless it works. This leads to the observation that although the manual states that 'Any properties that are references
to other variables, will remain references,' this is not strictly true. Any variables that are references, even to *themselves*
(not necessarily to other variables), will be copied by reference rather than by value.
Here's an example to demonstrate:
<?php
class ByVal
{
var $prop;
}
class ByRef
{
var $prop;
function __construct() { $this->prop =& $this->prop; }
}
$a = new ByVal;
$a->prop = 1;
$b = clone $a;
$b->prop = 2; // $a->prop remains at 1
$a = new ByRef;
$a->prop = 1;
$b = clone $a;
$b->prop = 2; // $a->prop is now 2
?>

koyama 03-Mar-2009 07:28


The __clone() method for deep cloning by cheetah at tanabi dot org also works when the object to be cloned contains references
to itself. This is not the case for any variation of the __clone() method in edit by danbrown at php dot net.
We are taking advantage of the fact that one can serialize an object that references itself.
Example:

<?php
class Foo
{
function __construct()
{
$this->_myself = $this;
}
function __clone() {
foreach ($this as $key => $val) {
if (is_object($val) || (is_array($val))) {
$this->{$key} = unserialize(serialize($val));
}
}
}
}
// this object references itself
$foo = new Foo();
// create a deep clone
$bar = clone $foo;
// check if we reach this point
echo 'Finished cloning!';
?>
Replacing the __clone() method with the one shown in edit by danbrown at php dot net we run into an infinite loop, and we
never get message 'Finished cloning!'.

cheetah at tanabi dot org 18-Nov-2008 05:15


Want deep cloning without too much hassle?
<?php
function __clone() {
foreach($this as $key => $val) {
if(is_object($val)||(is_array($val))){
$this->{$key} = unserialize(serialize($val));
}
}
}
?>
That will insure any object, or array that may potentially contain objects, will get cloned without using recursion or other
support methods.

[EDIT BY danbrown AT php DOT net: An almost exact function was contributed on 02-DEC-2008-10:18 by (david ashe AT metabin):
<?php
function __clone(){
foreach($this as $name => $value){
if(gettype($value)=='object'){
$this->$name= clone($this->$name);
}
}
}

?>
Giving credit where it's due. ~DPB]

wbcarts at juno dot com 02-Oct-2008 11:41


CLONED ARMIES? USE STATIC DATA
When I think of cloning, I always think of Star Wars "Cloned Army"... where the number of clones are in the hundreds of
thousands. So far, I have only seen examples of one or two clones with either shallow, deep, or recursive references. My fix is
to use the static keyword. With static, you choose the properties your objects share... and makes scaling up the number of socalled "clones" much easier.
<?php
class Soldier {
public static $status; // this is the property I'm trying to clone
protected static $idCount = 0; // used to increment ID numbers
protected $id; // each Soldier will have a unique ID
public function __construct() {
$this->id = ++self::$idCount;
}
public function issueCommand($task) {
switch($task){
case 'Deploy Troops': self::$status = 'deploying'; break;
case 'March Forward': self::$status = 'marching forward'; break;
case 'Fire!': self::$status = 'shot fired'; break;
case 'Retreat!': self::$status = 'course reversed'; break;
default: self::$status = 'at ease'; break;
}
echo 'COMMAND ISSUED: ' . $task . '<br>';
}
public function __toString() {
return "Soldier[id=$this->id, status=" . self::$status . ']';
}
}
# create the General and the Cloned Army
$general = new Soldier();
$platoon = array();
for($i = 0; $i < 250; $i++) $platoon[] = new Soldier();
# issue commands, then check what soldiers are doing
$general->issueCommand('Deploy Troops');
echo $general . '<br>';
echo $platoon[223] . '<br>';
echo $platoon[12] . '<br>';
$general->issueCommand('March Forward');
echo $platoon[47] . '<br>';
echo $platoon[163] . '<br>';
$general->issueCommand('Fire!');
echo $platoon[248] . '<br>';
echo $platoon[68] . '<br>';

$general->issueCommand('Retreat!');
echo $platoon[26] . '<br>';
echo $platoon[197] . '<br>';
?>
COMMAND ISSUED: Deploy Troops
Soldier[id=1, status=deploying]
Soldier[id=225, status=deploying]
Soldier[id=14, status=deploying]
COMMAND ISSUED: March Forward
Soldier[id=49, status=marching forward]
Soldier[id=165, status=marching forward]
COMMAND ISSUED: Fire!
Soldier[id=250, status=shot fired]
Soldier[id=70, status=shot fired]
COMMAND ISSUED: Retreat!
Soldier[id=28, status=course reversed]
Soldier[id=199, status=course reversed]

Jim Brown 19-Jul-2008 03:34


Regarding the generic deep __clone() example provided by david ashe at metabin:
If your object has a variable that stores an array of objects, that particular __clone() example will NOT perform a deep copy
on your array of objects.

alex dot offshore at gmail dot com 19-May-2008 03:23


Remember that in PHP 5 ALL objects are assigned BY REFERENCE.
<?php
function foo($a) // notice that '&' near $a is missing
{
$a['bar'] = 10;
}
$x = array('bar' => 0); // built-in array() is not an object
$y = new ArrayObject(array('bar' => 0));
echo "\$x['bar'] == ${x['bar']};\n\$y['bar'] == ${y['bar']};\n\n";
foo($x);
foo($y);
echo "\$x['bar'] == ${x['bar']};\n\$y['bar'] == ${y['bar']};\n";
?>
Output:
$x['bar'] == 0;
$y['bar'] == 0;
$x['bar'] == 0;

$y['bar'] == 10;
Hope this will be useful.
By the way, to determine whether the variable is compatible with ArrayAccess/ArrayObject see
http://php.net/manual/en/function.is-array.php#48083

crrodriguez at suse dot de 12-Mar-2008 09:52


Keep in mind that since PHP 5.2.5, trying to clone a non-object correctly results in a fatal error, this differs from previous
versions where only a Warning was thrown.

Hayley Watson 17-Dec-2007 03:51


It should go without saying that if you have circular references, where a property of object A refers to object B while a
property of B refers to A (or more indirect loops than that), then you'll be glad that clone does NOT automatically make a
deep copy!
<?php
class Foo
{
var $that;
function __clone()
{
$this->that = clone $this->that;
}
}
$a = new Foo;
$b = new Foo;
$a->that = $b;
$b->that = $a;
$c = clone $a;
echo 'What happened?';
var_dump($c);

tomi at cumulo dot fi 13-Nov-2007 03:57


It should be noticed that __clone() does not allow you to return a value. Basically the idea is that you implement this magic
method only when you want to execute operations inside the cloned object, immediately prior to the cloning. In this way
__clone() is similar to the default destructor (__destruct()), in that it executes code right before the object is destroyed.

muratyaman at gmail dot com 08-Oct-2007 07:43


I think this is a bit awkward:
<?php
class A{
public $aaa;
}
class B{
public $a;

public $bbb;

function __clone(){
$this->a = clone $this->a;//clone MANUALLY!!!
}
}
$b1 = new B();
$b1->a = new A();
$b1->a->aaa = 111;
$b1->bbb = 1;
$b2 = clone $b1;
$b2->a->aaa = 222;//BEWARE!!
$b2->bbb = 2;//no problem on basic types
var_dump($b1); echo '<br />';
var_dump($b2);
/*
OUTPUT BEFORE implementing the function __clone()
object(B)#2 (3) { ["a"]=> object(A)#3 (1) { ["aaa"]=> int(222) } ["bbb"]=> int(1) }
object(B)#4 (3) { ["a"]=> object(A)#3 (1) { ["aaa"]=> int(222) } ["bbb"]=> int(2) }
OUTPUT AFTER implementing the function __clone()
object(B)#1 (3) { ["a"]=> object(A)#2 (1) { ["aaa"]=> int(111) } ["bbb"]=> int(1) }
object(B)#3 (3) { ["a"]=> object(A)#4 (1) { ["aaa"]=> int(222) } ["bbb"]=> int(2) }
*/
?>
Whenever we use another class inside, we must clone it manually. If you have 10s of classes related, this is rather tedious. I
don't want to even think about classes dynamically populated with other objects. Be careful when designing your classes! You
should look after your objects all the time! This major change on PHP5 vs PHP4 regarding "references" definitely has very good
performance improvements but comes with very dangerous side effects as well..

Alexey 08-Feb-2007 07:18


To implement __clone() method in complex classes I use this simple function:
function clone_($some)
{
return (is_object($some)) ? clone $some : $some;
}
In this way I don't need to care about type of my class properties.

MakariVerslund at gmail dot com 21-Jan-2007 04:30


I ran into the same problem of an array of objects inside of an object that I wanted to clone all pointing to the same
objects. However, I agreed that serializing the data was not the answer. It was relatively simple, really:
public function __clone() {
foreach ($this->varName as &$a) {
foreach ($a as &$b) {
$b = clone $b;
}
}
}

Note, that I was working with a multi-dimensional array and I was not using the Key=>Value pair system, but basically, the
point is that if you use foreach, you need to specify that the copied data is to be accessed by reference.

jorge dot villalobos at gmail dot com 30-Mar-2005 03:29


I think it's relevant to note that __clone is NOT an override. As the example shows, the normal cloning process always occurs,
and it's the responsibility of the __clone method to "mend" any "wrong" action performed by it.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

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
functionbool2str($bool)
{
if($bool===false){
return'FALSE';
}else{
return'TRUE';
}
}
functioncompareObjects(&$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";
}
classFlag
{
public$flag;
functionFlag($flag=true){
$this->flag=$flag;
}
}
classOtherFlag
{
public$flag;
functionOtherFlag($flag=true){
$this->flag=$flag;
}
}
$o=newFlag();
$p=newFlag();
$q=$o;
$r=newOtherFlag();
echo"Twoinstancesofthesameclass\n";
compareObjects($o,$p);

echo"\nTworeferencestothesameinstance\n";
compareObjects($o,$q);
echo"\nInstancesoftwodifferentclasses\n";
compareObjects($o,$r);
?>

The above example will output:


Two instances of the same class
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : FALSE
o1 !== o2 : TRUE
Two references to the same instance
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE
Instances of two different classes
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Note:
Extensions can define own rules for their objects comparison.

User Contributed Notes

Comparing Objects

f at francislacroix dot info 18-Nov-2011 11:36


It should be noted that objects can be compared using only their accessible properties using get_object_vars().
Per example, in this class:
class X {
public $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
}
You can ignore the private properties when comparing them outside the class scope, like this:
$a = new X(1, 1);
$b = new X(1, 0);
var_dump(get_object_vars($a) == get_object_vars($b));
Just remember that get_object_vars() return different properties depending on the scope where you call it, so calling the above

within one of X member will compare the private properties.

d dot e dot pope at gmail dot com 27-Mar-2011 12:27


Note that ALL object fields, public and private, are used in the equivalence check. If you want public-only equivalence you'll
have to roll your own.
<?php
function bool2str($bool)
{
if ($bool === false) {
return 'FALSE';
} else {
return 'TRUE';
}
}
class PubPrivFlag
{
public $pubFlag;
private $privFlag;
public function __construct($pub, $priv)
{
$this->pubFlag = $pub;
$this->privFlag = $priv;
}
}
echo "Two instances of the same class with identical private fields\n";
$s = new PubPrivFlag(true, true);
$t = new PubPrivFlag(true, true);
echo 'o1 == o2 : ' . bool2str($s == $t) . "\n";
echo "Two instances of the same class with different private fields\n";
$s = new PubPrivFlag(true, true);
$t = new PubPrivFlag(true, false);
echo 'o1 == o2 : ' . bool2str($s == $t) . "\n";
?>
This will output the following:
Two instances of the same class with identical private fields
o1 == o2 : TRUE
Two instances of the same class with different private fields
o1 == o2 : FALSE

SjH 02-Feb-2011 04:15


Interestingly enough due to the operator precidences changing the values of identical objects may not be as obvious as
expected.
<?php
class A {
private $val;

public function set($val)


{
$this->val = $val;
return $this;
}
}
$a = new A;
$b = new A;
$c = $a;
echo var_dump($a->set('foo') == $b->set('bar'));
// Will evaluate as boolean false
echo var_dump($a->set('foo') == $c->set('bar'));
// Will evaluate a boolean true
?>

Anonymous 02-Jul-2010 09:00


Comparison using <> operators should be documented. Between two objects, at least in PHP5.3, the comparison operation stops
and returns at the first unequal property found.
<?php
$o1 = new stdClass();
$o1->prop1 = 'c';
$o1->prop2 = 25;
$o1->prop3 = 201;
$o1->prop4 = 1000;
$o2 = new stdClass();
$o2->prop1 = 'c';
$o2->prop2 = 25;
$o2->prop3 = 200;
$o2->prop4 = 9999;
echo (int)($o1 < $o2); // 0
echo (int)($o1 > $o2); // 1
$o1->prop3 = 200;
echo (int)($o1 < $o2); // 1
echo (int)($o1 > $o2); // 0
?>

RPaseur at NationalPres dot org 08-Oct-2009 04:09


SimpleXML Objects are different, even if made from the same XML.
<?php // RAY_SimpleXML_compare.php
error_reporting(E_ALL);
echo "<pre>\n";
// TWO SimpleXML OBJECTS ARE NOT EQUAL WITH COMPARISON OPERATORS. PHP 5.2.10

// AN XML STRING
$xml = '<?xml version="1.0" encoding="utf-8"?>
<thing>
<number>123456</number>
<email>user@example.com</email>
<state>CA</state>
</thing>';
// SHOW THE XML STRING
echo htmlentities($xml);
// MAKE TWO OBJECTS
$obj1 = SimpleXML_Load_String($xml);
$obj2 = SimpleXML_Load_String($xml);
// COMPARE OBJECTS AND FIND THAT THIS ECHOS NOTHING AT ALL
if ($obj1 === $obj2) echo "\n\nOBJECTS IDENTICAL ";
if ($obj1 == $obj2) echo "\n\nOBJECTS EQUAL ";
// SHOW THE OBJECTS - NOTE DIFFERENT SimpleXMLElement NUMBERS
echo "\n\n";
var_dump($obj1);
var_dump($obj2);
// ITERATE OVER THE OBJECTS
foreach ($obj1 as $key => $val1)
{
$val2 = $obj2->$key;
var_dump($val1);
var_dump($val2);
if ($val1 == $val2) echo "\n\nOBJECTS EQUAL"; // ECHOS NOTHING
// RECAST AS STRINGS AND COMPARE AGAIN
$val1 = (string)$val1;
$val2 = (string)$val2;
if ($val1 === $val2) echo "STRINGS IDENTICAL: $key => $val1 \n\n"; // CONMPARISON SHOWS STRINGS IDENTICAL
}
?>

Hayley Watson 16-Sep-2008 03:33


This has already been mentioned (see jazfresh at hotmail.com's note), but here it is again in more detail because for objects
the difference between == and === is significant.
Loose equality (==) over objects is recursive: if the properties of the two objects being compared are themselves objects, then
those properties will also be compared using ==.
<?php
class Link
{
public $link; function __construct($link) { $this->link = $link; }
}
class Leaf
{
public $leaf; function __construct($leaf) { $this->leaf = $leaf; }
}
$leaf1 = new Leaf(42);

$leaf2 = new Leaf(42);


$link1 = new Link($leaf1);
$link2 = new Link($leaf2);
echo "Comparing Leaf object equivalence: is \$leaf1==\$leaf2? ", ($leaf1 == $leaf2 ? "Yes" : "No"), "\n";
echo "Comparing Leaf object identity: is \$leaf1===\$leaf2? ", ($leaf1 === $leaf2 ? "Yes" : "No"), "\n";
echo "\n";
echo "Comparing Link object equivalence: is \$link1==\$link2? ",($link1 == $link2 ? "Yes" : "No"), "\n";
echo "Comparing Link object identity: is \$link1===\$link2? ", ($link1 === $link2 ? "Yes" : "No"), "\n";
?>
Even though $link1 and $link2 contain different Leaf objects, they are still equivalent because the Leaf objects are themselves
equivalent.
The practical upshot is that using "==" when "===" would be more appropriate can result in a severe performance penalty,
especially if the objects are large and/or complex. In fact, if there are any circular relationships involved between the
objects or (recursively) any of their properties, then a fatal error can result because of the implied infinite loop.
<?php
class Foo { public $foo; }
$t = new Foo; $t->foo = $t;
$g = new Foo; $g->foo = $g;
echo "Strict identity: ", ($t===$g ? "True" : "False"),"\n";
echo "Loose equivalence: ", ($t==$g ? "True" : "False"), "\n";
?>
So preference should be given to comparing objects with "===" rather than "=="; if two distinct objects are to be compared for
equivalence, try to do so by examining suitable individual properties. (Maybe PHP could get a magic "__equals" method that gets
used to evaluate "=="? :) )

wbcarts at juno dot com 08-Sep-2008 01:36


COMPARING OBJECTS using PHP's usort() method.
PHP and MySQL both provide ways to sort your data already, and it is a good idea to use that if possible. However, since this
section is on comparing your own PHP objects (and that you may need to alter the sorting method in PHP), here is an example of
how you can do that using PHP's "user-defined" sort method, usort() and your own class compare() methods.
<?php
/*
* Employee.php
*
* This class defines a compare() method, which tells PHP the sorting rules
* for this object - which is to sort by emp_id.
*
*/
class Employee
{
public $first;
public $last;
public $emp_id; // the property we're interested in...
public function __construct($emp_first, $emp_last, $emp_ID)
{
$this->first = $emp_first;
$this->last = $emp_last;

$this->emp_id = $emp_ID;
}
/*
* define the rules for sorting this object - using emp_id.
* Make sure this function returns a -1, 0, or 1.
*/
public static function compare($a, $b)
{
if ($a->emp_id < $b->emp_id) return -1;
else if($a->emp_id == $b->emp_id) return 0;
else return 1;
}
public function __toString()
{
return "Employee[first=$this->first, last=$this->last, emp_id=$this->emp_id]";
}
}
# create a PHP array and initialize it with Employee objects.
$employees = array(
new Employee("John", "Smith", 345),
new Employee("Jane", "Doe", 231),
new Employee("Mike", "Barnes", 522),
new Employee("Vicky", "Jones", 107),
new Employee("John", "Doe", 2),
new Employee("Kevin", "Patterson", 89)
);
# sort the $employees array using Employee compare() method.
usort($employees, array("Employee", "compare"));
# print the results
foreach($employees as $employee)
{
echo $employee . '<br>';
}
?>
Results are now sorted by emp_id:
Employee[first=John, last=Doe, emp_id=2]
Employee[first=Kevin, last=Patterson, emp_id=89]
Employee[first=Vicky, last=Jones, emp_id=107]
Employee[first=Jane, last=Doe, emp_id=231]
Employee[first=John, last=Smith, emp_id=345]
Employee[first=Mike, last=Barnes, emp_id=522]
Important Note: Your PHP code will never directly call the Employee's compare() method, but PHP's usort() calls it many many
times. Also, when defining the rules for sorting, make sure to get to a "primitive type" level... that is, down to a number or
string, and that the function returns a -1, 0, or 1, for reliable and consistent results.
Also see: http://www.php.net/manual/en/function.usort.php for more examples of PHP's sorting facilities.

wbcarts at juno dot com 06-Sep-2008 02:02


COMPARISONS AND EQUALITY are NOT the same

I'm not sure that the PHP Example #1 above is clear enough. In my own experience, I have found there is a distinct difference
between a "comparison" and a "test for equality". The difference is found in the possible return values of the function being
used, for example.
/*
* Test two values for EQUALITY - returns (boolean) TRUE or FALSE.
*/
function equals($a, $b)
{
return ($a == $b);
}
/*
* COMPARE two values - returns (int) -1, 0, or 1.
*/
function compare($a, $b)
{
if($a < $b) return -1;
else if($a == $b) return 0;
else if($a > $b) return 1;
else return -1;
}
My examples clarify the difference between "making a comparison" and "testing for equality". You can substitute any of the "=="
with "===" for example, but the point is on the possible return values of the function. All tests for EQUALITY will return TRUE
or FALSE, and a COMPARISON will give a "<", "==", or ">" answers... which you can then use for sorting.

cross+php at distal dot com 05-Mar-2008 08:50


In response to "rune at zedeler dot dk"s comment about class contents being equal, I have a similar issue. I want to sort an
array of objects using sort().
I know I can do it with usort(), but I'm used to C++ where you can define operators that allow comparison. I see in the zend
source code that it calls a compare_objects function, but I don't see any way to implement that function for an object. Would
it have to be an extension to provide that interface?
If so, I'd like to suggest that you allow equivalence and/or comparison operations to be defined in a class definition in PHP.
Then, the sorts of things rune and I want to do would be much easier.

dionyziz at deviantart dot com 10-Mar-2007 07:20


Note that classes deriving from the same parent aren't considered equal when comparing even using ==; they should also be
objects of the same child class.
<?php
class Mom {
private $mAttribute;

public function Mom( $attribute ) {
$this->mAttribute = $attribute;
}
public function Attribute() {
return $this->mAttribute;
}
}

final class Sister extends Mom {


public function Sister( $attribute ) {

$this->Mom( $attribute );
}
}

final class Brother extends Mom {


public function Brother( $attribute ) {
$this->Mom( $attribute );
}
}

$sister = new Sister( 5 );


$brother = new Brother( 5 );

assert( $sister == $brother ); // will FAIL!


?>
This assertion will fail, because sister and brother are not of the same child class!
If you want to compare based on the parent class object type only, you might have to define a function for comparisons like
these, and use it instead of the == operator:
<?php
function SiblingsEqual( $a, $b ) {
if ( !( $a instanceof Mom ) ) {
return false;
}
if ( !( $b instanceof Mom ) ) {
return false;
}
if ( $a->Attribute() != $b->Attribute() ) {
return false;
}
return true;
}
assert( SiblingsEqual( $sister, $brother ) ); // will succeed
?>

rune at zedeler dot dk 28-Feb-2007 08:34


Whoops, apparently I hadn't checked the array-part of the below very well.
Forgot to test if the arrays had same length, and had some misaligned parenthesis.
This one should work better :+)
<?
function deepCompare($a,$b) {
if(is_object($a) && is_object($b)) {
if(get_class($a)!=get_class($b))
return false;
foreach($a as $key => $val) {
if(!deepCompare($val,$b->$key))
return false;
}
return true;
}
else if(is_array($a) && is_array($b)) {
while(!is_null(key($a)) && !is_null(key($b))) {
if (key($a)!==key($b) || !deepCompare(current($a),current($b)))
return false;

next($a); next($b);
}
return is_null(key($a)) && is_null(key($b));
}
else
return $a===$b;
}
?>

rune at zedeler dot dk 27-Feb-2007 08:27


I haven't found a build-in function to check whether two obects are identical - that is, all their fields are identical.
In other words,
<?
class A {
var $x;
function __construct($x) { $this->x = $x; }
}
$identical1 = new A(42);
$identical2 = new A(42);
$different = new A('42');
?>
Comparing the objects with "==" will claim that all three of them are equal. Comparing with "===" will claim that all are unequal.
I have found no build-in function to check that the two identicals are
identical, but not identical to the different.
The following function does that:
<?
function deepCompare($a,$b) {
if(is_object($a) && is_object($b)) {
if(get_class($a)!=get_class($b))
return false;
foreach($a as $key => $val) {
if(!deepCompare($val,$b->$key))
return false;
}
return true;
}
else if(is_array($a) && is_array($b)) {
while(!is_null(key($a) && !is_null(key($b)))) {
if (key($a)!==key($b) || !deepCompare(current($a),current($b)))
return false;
next($a); next($b);
}
return true;
}
else
return $a===$b;
}
?>

jazfresh at hotmail.com 08-Dec-2006 02:36

Note that when comparing object attributes, the comparison is recursive (at least, it is with PHP 5.2). That is, if $a->x
contains an object then that will be compared with $b->x in the same manner. Be aware that this can lead to recursion errors:
<?php
class Foo {
public $x;
}
$a = new Foo();
$b = new Foo();
$a->x = $b;
$b->x = $a;
print_r($a == $b);
?>
Results in:
PHP Fatal error: Nesting level too deep - recursive dependency? in test.php on line 11

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Type Hinting
PHP 5 introduces type hinting. Functions are now able to force parameters to be objects (by specifying the
name of the class in the function prototype), interfaces, arrays (since PHP 5.1) or callable (since PHP 5.4).
However, if NULL is used as the default parameter value, it will be allowed as an argument for any later call.
If class or interface is specified as type hint then all its children or implementations are allowed too.
Type hints can not be used with scalar types such as int or string. Traits are not allowed either.
Example #1 Type Hinting examples
<?php
//Anexampleclass
classMyClass
{
/**
*Atestfunction
*
*FirstparametermustbeanobjectoftypeOtherClass
*/
publicfunctiontest(OtherClass$otherclass){
echo$otherclass->var;
}

/**
*Anothertestfunction
*
*Firstparametermustbeanarray
*/
publicfunctiontest_array(array$input_array){
print_r($input_array);
}

/**
*Firstparametermustbeiterator
*/
publicfunctiontest_interface(Traversable$iterator){
echoget_class($iterator);
}

/**
*Firstparametermustbecallable
*/
publicfunctiontest_callable(callable$callback,$data){
call_user_func($callback,$data);
}
}
//Anotherexampleclass
classOtherClass{
public$var='HelloWorld';
}
?>

Failing to satisfy the type hint results in a catchable fatal error.

<?php
//Aninstanceofeachclass
$myclass=newMyClass;
$otherclass=newOtherClass;
//FatalError:Argument1mustbeanobjectofclassOtherClass
$myclass->test('hello');
//FatalError:Argument1mustbeaninstanceofOtherClass
$foo=newstdClass;
$myclass->test($foo);
//FatalError:Argument1mustnotbenull
$myclass->test(null);
//Works:PrintsHelloWorld
$myclass->test($otherclass);
//FatalError:Argument1mustbeanarray
$myclass->test_array('astring');
//Works:Printsthearray
$myclass->test_array(array('a','b','c'));
//Works:PrintsArrayObject
$myclass->test_interface(newArrayObject(array()));
//Works:Printsint(1)
$myclass->test_callable('var_dump',1);
?>

Type hinting also works with functions:


<?php
//Anexampleclass
classMyClass{
public$var='HelloWorld';
}
/**
*Atestfunction
*
*FirstparametermustbeanobjectoftypeMyClass
*/
functionmyFunction(MyClass$foo){
echo$foo->var;
}
//Works
$myclass=newMyClass;
myFunction($myclass);
?>

Type hinting allowing NULL value:


<?php
/*AcceptingNULLvalue*/
functiontest(stdClass$obj=NULL){

}
test(NULL);
test(newstdClass);
?>

User Contributed Notes

Type Hinting

john at cast dot com 29-Apr-2011 06:33


i use eclipse ganymede as an IDE and it offers "intellisense" where it can, i.e. when variables are "declared" via type hinting
or a "new"-statement . i found using the following pattern helps eclipse along as well:
<?php
class MyClass{
public static function Cast(MyClass &$object=NULL){
return $object;
}
public method CallMe(){
}
}
$x=unserialize($someContent);
$x=MyObject::Cast($x);
$x->CallMe();
?>
after calling Cast(), due to the type hinting, eclipse offers me the "CallMe" function in a dropdown when i type "$x->" in the
code afterwards.
i found this very practical und included the Cast() function in my code template for new classes. i've been wondering, if there
is a drawback i oversaw, but i haven't noticed any negative effects so far... maybe some of you will find this just as handy
as i do ;o)
p.s. do note: when used in inherited classes a STRICT-notice comes up, because the function definition of the inherited class
doesn't match the parent's definition (different type hinting) - but it works great!

Anonymous 14-Apr-2011 07:43


Please note, there is a strong typing in PHP.
You have to import one PHP library to your existing projects, and create some classes, in which the scalar values will be
automatically wrapped by an autoboxing mechanism known from Java, like so:
<?php
class String extends AutoBoxedObject
{
public $value;

public function __construct($value) {


$this->value = $value;
}

public function __toString() {


return "$this->value";
}

public function toUpperCase() {


return strtoupper($this->value);
}
}

function & string($value = null) {


$x = & VariablesManager::getNewPointer(new String($value));
return $x;
}
?>
From now on you can declare the type of data in your variables, and validate their values in a class constructor.
See this example:
<?php
$y = & string("aaa");
// lets check, that $y is an object
var_dump($y);

// now we are overwritting $y variable with a scalar value of "zzz"


$y = "zzz";
// var_dump() shows us, that "zzz" is still an object, not the scalar type as in regular PHP
var_dump($y);
// the line below should raise a fatal error, because "zzz" was a scalar type (string), but it will be ok, because $y is still
an object (thanks to autoboxing)
var_dump($y->toUpperCase());
?>
Now, the output is:
object(String)#1 (2) {
["value"]=>
string(3) "aaa"
["ref":protected]=>
int(1)
}
object(String)#2 (2) {
["value"]=>
string(3) "zzz"
["ref":protected]=>
int(1)
}
string(3) "ZZZ"
As you can see, PHP can be as good as Java or C#:)
To enforce strong data types you just have to do it in the wrapper class, like so:
<?php
class Integer extends AutoBoxedObject
{
public $value;

public function __construct($value) {


if(!is_int($value)) { throw new Exception("Invalid data type"); }
$this->value = $value;
}


public function getValue() {
return $this->value;
}
public function __toString() {
return (string)$this->value;
}
}
?>
To download the library, just google for 'strong data typing autoboxing' . There is an article describing how to use it, and a
download link to the appropriate PHP library.

macobex dot exe at gmail dot com 10-Feb-2011 06:48


I agree [that] using object/wrapper is faster than using the is_* functions.
But I think we must also consider the fact that when we pass an argument to a function, most likely we will use it's value. So
I've done a little test to see which approach is faster.
Primitive Approach:
<?php
function testPrimitive($str) {
if ( is_string($str) )
$x = $str . ' world'; // using the argument's value
else
trigger_error('Argument passed must be of type string.');
}
?>
Wrapper Approach:
<?php
function testWrapper(StringWrapper $str) {
$x = $str->getValue() . ' world'; // using the argument's value
}
?>
Test: 10,000 iterations
Results:
primitive average: 0.026113033294678
wrapper average: 0.063039064407349
primitive is faster than wrapper approach by 41.42357368431%
Using the is_* function is faster than using wrapper class, given the fact that we just not want to check the type of the
argument, but we also want to use the value of the argument.

alejosimon at gmail dot com 22-Oct-2010 11:55


For PHP 5.3 version and namespaces support.
<?php

function phpErrorHandler( $code, $message, $file, $line ) {


if ( error_reporting() & $code ) {
if ( $code == E_RECOVERABLE_ERROR ) { // Scalar Type-Hinting patch.
$regexp = '/^Argument (\d)+ passed to (.+) must be an instance of (?<hint>.+), (?<given>.+) given/i' ;
if ( preg_match( $regexp, $message, $match ) ) {
$given = $match[ 'given' ] ;
$hint = end( explode( '\\', $match[ 'hint' ] ) ) ; // namespaces support.
if ( $hint == $given ) return true ;
}
}
return false ;
}
}
set_error_handler( 'phpErrorHandler' ) ;
/************************************/
function typeHintTest( integer $arg1 ) {
print_r( $arg1 ) ;
}
typeHintTest( true ) ; // Error throw because not integer type.
?>

gdecad at NOSPAM dot example dot com 22-Oct-2010 06:02


I have made a little bench between three method of type hinting for native type (string, integer, ...).
First method : by test type in function like :
<?php
function testTest($arg) {
if (!is_string($arg)) {
trigger_error('Argument $arg passed to test must be an instance of string, other given');
}
return $arg;
}
?>
Second method : by object representing native type :
<?php
function testObject(StringObj $arg) {
return $arg;
}
?>
Third method : by class TypeHint proposed by Daniel :
<?php
function testHint(string $arg) {

return $arg;
}
?>
the results are here :
bench for 100000 iterations, in seconds
avg min max total
test 5.3275489807129E-6 2.8610229492188E-6 0.0033020973205566 0.53275895118713
object 4.9089097976685E-6 3.814697265625E-6 0.0025870800018311 0.49089503288269
hint 3.2338891029358E-5 2.9802322387695E-5 0.0025920867919922 3.2338931560516
As you can see, the method by object is the best
now you know...

bogdan dot wrobel at gmail dot com 02-Feb-2010 12:10


Regarding "simple" type hints, you may use SPL: http://pl.php.net/manual/en/book.spl-types.php

reinier dot kip at gmail dot com 15-Sep-2009 01:22


Please note that when using the type hinting class together with namespaces, you're asking for trouble:
<?php
namespace a {
interface A {
public function execute(string $sth);
}
}
namespace ab {
class B implements aA {
public function execute(string $sth){} // Wrong
public function execute(astring $sth){} // Correct
}
} // Causes a fatal error on this line. 'string' is considered an object from the namespace 'a'
?>

dpariyskiy at netatwork dot com 08-Sep-2009 08:36


Daniel, thank you for the type hinting class. Very useful.
For anyone having a problem where php isn't setting Daniel's error handler, as was the case for me, try changing
initializeHandler function to the following:
<?php
public static function initializeHandler()
{

set_error_handler(array('Typehint','handleTypehint'));

return TRUE;
}
?>
Hope this helps,
--Dmitriy

bantam at banime dot com 06-Jan-2009 02:53

Daniel's typehint implementation was just what I was looking for but performance in production wasn't going to cut it. Calling
a backtrace every time hurts performance. For my implementation I didn't use it, after all, PHP tells us what the data type is
in the error message, I don't feel I need to evaluate the argument where I am using typehinting. Here is the cut down version
I use in my error handling class:
<?php
public static function typehint($level, $message)
{
if($level == E_RECOVERABLE_ERROR)
{
if(preg_match('/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/',
$message, $match))
{
if($match[4] == $match[5])
return true;
}
}

return false;
}
?>
Hope this can be of use to somebody.

r dot wilczek at web-appz dot de 18-Dec-2008 07:41


It has already been mentioned here that you can use 'self' as a typehint (in methods of classes and interfaces, not in
functions of course), which is useful in interfaces and abstract method declarations to force the implementor to accept an
instance of it's own type:
<?php
interface Foo
{
public function baz(self $object);
}
class Bar implements Foo
{
public function baz(self $object)
{
//
}
}
?>
What has not been mentioned by now is that you can use 'parent' as a typehint too. Example with an interface:
<?php
interface Foo
{
public function baz(parent $object);
}
class Baz {}
class Bar extends Baz implements Foo
{
public function baz(parent $object)
{
//
}

}
?>
Bar::baz() will now accept any instance of Baz.
If Bar is not a heir of any class (no 'extends') PHP will raise a fatal error:
'Cannot access parent:: when current class scope has no parent'.

wickedmuso at gmail dot com 24-Oct-2008 08:26


One useful thing with Type Hinting that I could not find in the documentation (but tested) is that you can also use an
Interface in the hint (versus a Class). This is a very useful tool if you are trying to code to Interfaces rather than
Classes (which is common in Test Driven Development and Dependency Injection paradigms). It means your external class can
present itself into the method as long as it implements the nominated Interface (obviously).

info at thewebsiteguy dot com dot au 08-Oct-2008 06:30


I find it rather frustrating that PHP has internal data types but doesn't allow optional hinting for it. I REALLY needed it
for something, so I found a way around it.
<?php
abstract class DataType
{
protected $length;
protected $precision;
protected $number;

public function __construct()


{
$this->number = false;
$this->precision = null;
}

public function GetLength()


{
return $this->length;
}

public function IsNumber()


{
return $this->number;
}
public function GetPrecision()
{
return $this->precision;
}
}
class Integer extends DataType
{
public function __construct($length = 12)
{
parent::__construct();
$this->number = true;
$this->length = $length;
$this->precision = 0;
}
}

class Float extends DataType


{
public function __construct($length = 12, $precision = 2)
{
parent::__construct();
$this->number = true;
$this->length = $length;
$this->precision = $precision;
}
}
class String extends DataType
{
public function __construct($length = 255)
{
parent::__constructor();
$this->length = $length;
}
}
//etc etc through the types...
?>
then later I can do this...
<?php
final class Field
{
public $Name;
public $Mandatory;
public $Hidden;
public $ListField;
public $Value;
public $ForeignClass;
public $ReadOnly;
public $DataType;

public function __construct($name, DataType $dataType, $mandatory = false, $listField = true, $value = null, $readOnly =
false, BaseCBO $foreignClass = null)
{
$this->Name = $name;
$this->DataType = $dataType;
$this->Mandatory = $mandatory;
$this->ListField = $listField;
$this->Value = $value;
$this->ReadOnly = $readOnly;
$this->ForeignClass = $foreignClass;
}
}
// ....
class DoSomeStuff
{
public function DoGenericThings(Field $field)
{
if ($field->DataType instanceof Integer)
{
// do things for an integer field...
}
}

}
?>

wbcarts at juno dot com 01-Oct-2008 06:20


TYPE-HINTING and VISIBILITY
Type-hinting is just one more small piece of PHP that protects our objects when visibility cannot.
<?php
class Point {
public $x, $y;
public function __construct($xVal = 0, $yVal = 0) {
$this->x = $xVal;
$this->y = $yVal;
}
}
class Polyline {
protected $points = array();
public function addPoint(Point $p) { // the line we're interested in...
$this->points[] = $p;
}
}
$point1 = new Point(15, 12);
$polyline = new Polyline();
$polyline->addPoint($point1);
$polyline->addPoint(new Point(55, 22));
$polyline->addPoint(new Point(33, 31));
$polyline->addPoint(new stdClass()); // PHP will throw an error for us!
?>
Since our Polyline::addPoint() function has to be public, any outside code can try to pass anything. But, when type-hinting is
declared, PHP throws an error when phoney data tries to sneak by.

DanielLWood [at] Gmail [dot] Com 08-Sep-2008 05:59


To follow up on my original post dealing with the type hinting class I provided:
Kalkamar is absolutely correct, it is slow and is a hack. Everyone who uses it and wants to see this type of syntax native
needs to post on the 'php internals' development thread in support.
Thanks,
Dan

kalkamar at web dot de 04-Sep-2008 02:24


I really like the Daniel`s Typehinting-Class, but you please not that it may be relevant for the performance if you use
Typehinting for scalar values very often.
Here is my performance-test:

<?php
function notypehinting($x)
{
is_string($x); //checking the type manually instead
}
function typehinting(string $x)
{
}
$test=new timer;
for($i=0;$i<10000;$i++)
{
try{
notypehinting('test');
}
catch(Exception $e){}
}
echo $test.'<br>';
$test2=new timer;
for($i=0;$i<10000;$i++)
{
try{
typehinting('test');
}
catch(Exception $e){}
}
echo $test2.'<br>';
?>
Output:
0.0088460445404053
0.21634602546692
Result:
typehinting() ist more than 20 times slower than notypehinting()
You see: typehinting for scalar types (like suggested by Daniel) is not the best thing for the performance if you use it very
often.

comments at ignorethis netweblogic com 17-Jul-2008 07:39


Note that you cannot add a type hint and give a default value, apart from arrays. You will get an internal server error, or
fatal error.
e.g.
<?php
//Wont work
function test(ObjName $obj = ''){
//.....
}
//Will work

function test(Array $obj = array()){


//.....
}
?>
Even if you have Daniel's implementation of type hinting, a string typehint will still not work if you give it an empty string
default too.

marcus at ignorethis netweblogic dot com 14-Jul-2008 06:18


Love the typehint object Daniel. Great effort!
However, it still throws catchable fatal errors, which is not what I want, so I added one line to handleTypehint() so it throws
an Exception.
<?php
public static function handleTypehint($ErrLevel, $ErrMessage) {
if ($ErrLevel == E_RECOVERABLE_ERROR) {
if (preg_match ( TYPEHINT_PCRE, $ErrMessage, $ErrMatches )) {
list ( $ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType ) = $ErrMatches;
if (isset ( self::$Typehints [$ThHint] )) {
$ThBacktrace = debug_backtrace ();
$ThArgValue = NULL;
if (self::getTypehintedArgument ( $ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue )) {
if (call_user_func ( self::$Typehints [$ThHint], $ThArgValue )) {
return TRUE;
}
}
}
throw new Exception($ErrMessage);
}
}
return FALSE;
}
?>

madness 11-Jul-2008 03:09


I must admit that Daniel's implementation is quite awesome (after all we'd be omonyms if I was english, omen nomen ;-) ), for
everyone that already has a function/class to handle errors, this is a quick method to integrate the TypeHint class:
<?php
public static function handleError($errno, $errstr, $errfile, $errline){
// Implements just-in-time classes for broad type hinting
if (TypeHint::handleTypehint($errno, $errstr)){
return true;
}

// do your usual stuff here
/*
* ...
*/
}
?>
The initializeHandler method and the Typehint::initializeHandler(); call are rendered useless in this case. Enjoy.

Daniel dot L dot Wood at Gmail dot Com 26-May-2008 11:00


People often ask about scalar/basic typehints. Here is a drop in class that I use in my MVC framework that will enable
typehints through the use of a custom error handler.
Note: You should include this code above all other code in your include headers and if you are the using set_error_handler()
function you should be aware that this uses it as well. You may need to chain your set_error_handlers()
Why?
1) Because people are sick of using the is_* functions to validate parameters.
2) Reduction of redundant coding for defensive coders.
3) Functions/Methods are self defining/documenting as to required input.
Also..
Follow the discussion for typehints in PHP 6.0 on the PHP Internals boards.
<?php
define('TYPEHINT_PCRE' ,'/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+)
given/');
class Typehint
{
private static $Typehints = array(
'boolean' => 'is_bool',
'integer' => 'is_int',
'float' => 'is_float',
'string' => 'is_string',
'resrouce' => 'is_resource'
);
private function __Constrct() {}
public static function initializeHandler()
{
set_error_handler('Typehint::handleTypehint');
return TRUE;
}
private static function getTypehintedArgument($ThBackTrace, $ThFunction, $ThArgIndex, &$ThArgValue)
{
foreach ($ThBackTrace as $ThTrace)
{
// Match the function; Note we could do more defensive error checking.
if (isset($ThTrace['function']) && $ThTrace['function'] == $ThFunction)
{
$ThArgValue = $ThTrace['args'][$ThArgIndex - 1];
return TRUE;
}
}
return FALSE;

}
public static function handleTypehint($ErrLevel, $ErrMessage)
{
if ($ErrLevel == E_RECOVERABLE_ERROR)
{
if (preg_match(TYPEHINT_PCRE, $ErrMessage, $ErrMatches))
{
list($ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType) = $ErrMatches;
if (isset(self::$Typehints[$ThHint]))
{
$ThBacktrace = debug_backtrace();
$ThArgValue = NULL;
if (self::getTypehintedArgument($ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue))
{
if (call_user_func(self::$Typehints[$ThHint], $ThArgValue))
{
return TRUE;
}
}
}
}
}
return FALSE;
}
}
Typehint::initializeHandler();
?>
An are some examples of the class in use:
<?php
function teststring(string $string) { echo $string; }
function testinteger(integer $integer) { echo $integer; }
function testfloat(float $float) { echo $float; }
// This will work for class methods as well.
?>
You get the picture..

Darby 28-Dec-2007 07:50


Correction to previous note:
"Failing to satisfy the type hint results in a catchable fatal error."

This only seems to be the case for PHP >= 5.2.0.

jesdisciple @t gmail -dot- com 06-Nov-2007 07:50


The manual's sample code says:
<?php
//...
// Fatal Error: Argument 1 must not be null
$myclass->test(null);
//...
?>
And this is true, unless a default value of NULL is given; in fact, this is the only way to give a default value for object
arguments (as a default value must be a constant expression):
<?php
$mine = new MyClass();
$mine->test(NULL);
class MyClass{
public function __construct(OtherClass $arg = NULL){
if(is_null($arg)){
//Apply default value here.
}
}
public function test(array $arr = NULL){
print_r($arr);
}
}
class OtherClass{

}
?>

Jazz 16-Oct-2007 09:20


To Nikivich and Edorian:
There are many times when you would use an equals() method other than to find out if the two objects are the same object.
Think of all the primitive wrapper classes in Java, for example -- if you create two new Integer()'s with identical values,
equals() returns true, even though they are two different objects. There would be no reason to allow someone to perform an
equals() between an Integer and, say, a GregorianCalendar -- it just doesn't make sense. In Java you would attempt this and
probably get a ClassCastException, but in PHP no such facility exists, so the best way to prevent this would be through type
hinting.
The point Nicholas was making is that you can't specify a stricter type hint on an inherited method, and despite your
arguments, that would be a truly useful thing to be able to do.
(True overloading would be a better way, IMHO, but *shrug*)

ldebuyst->brutele.be 28-Feb-2007 06:52


In reply to Nikivich and Edorian:
Although it isn't quite clear from his post, I believe that the point nicholas is trying to make is that, if you typehint an
abstract function, you MUST use that same typehint for all classes extending the abstract class.
As his example shows, if you typehint (Object $object), then you must use the exact same typehint in the extending class.
Using the typehint (Table $table) or (Chair $chair) will give fatal errors, even if Table and Chair are subclasses of Object.

In other words, type hinting allows for descendants, as caliban at darklock dot com has shown, except when you're subclassing.
See http://bugs.php.net/bug.php?id=36601 for a bit more info. Flagged as wontfix, though, so something to keep in mind.

Nikivich 23-Feb-2007 07:28


In reply to Nicolas
I don't think you exactly understand the inheritance principles
If you want to do the equals thing in a decent OO way, you would do something like this:
class Object {
public equals(Object &o) {
return this == &o; //perform default equals check, one could arguably say that === is the correct default, but
doesnt matter for the example
}
}
class Chair extends Object {
}
class Table extends Object {
}
$chair = new Chair();
$table = new Table();
$chair->equals($table); //will print false (zero)
This is actually a correct implementation of an equals method. Since you want to take a chair for example and just call
equals() on it WITH ANY OBJECT, you should only hint Object, not an implementation, since the whole point of the equals method
is to find out whether it is actually the same object :-) I want to be able to pass a table (which implements Object too, so
is perfectly allowed as a parameter to equals).
Hope this clears it up a bit for you... :-)

Edorian 07-Feb-2007 10:12


In response to nicholas at nicholaswilliams dot info:
Of course this doesn't work. Not in Php nor in Java.
You can't put a Chair into Table just because there both implementing "Object"
It wouldn't make any sense to say "i'm expecting an argument that implements the same object that i'm implementing" with type
hinting.
You say: "I'm expection an Object of that Class or a Object of a Subclass of that Class " like you do in every OO languange.

nicholas at nicholaswilliams dot info 13-Nov-2006 12:53


Please note that the following will not work:
<?php
abstract class Object
{
public abstract function toString( );
public abstract function equals( Object &$o );

}
class Chair extends Object
{
public function toString( )
{
return 'This is a chair.';
}

public function equals( Chair &$o )


{
return TRUE;
}
}
class Table extends Object
{
public function toString( )
{
return 'This is a table.';
}

public function equals( Table &$o )


{
return TRUE;
}
}
$chair = new Chair();
$table = new Table();
echo $chair->equals( $table );
?>
The expected output is "Fatal error: Argument 1 passed to Chair::equals() must be an instance of Chair, called in [filename] on
line 38 and defined in [filename] on line 16" but instead you get "Fatal error: Declaration of Chair::equals() must be
compatible with that of Object::equals() in [filename] on line 20".
This is unlike other OO languages (secifically Java) which not only allow but expect this type of code. It is in the nature of
abstraction. However, you can get similar results using the following code instead:
<?php
abstract class Object
{
public abstract function toString( );
public abstract function equals( self &$o );
}
class Chair extends Object
{
public function toString( )
{
return 'This is a chair.';
}

public function equals( self &$o )


{
return TRUE;

}
}
class Table extends Object
{
public function toString( )
{
return 'This is a table.';
}

public function equals( self &$o )


{
return TRUE;
}
}
$chair = new Chair();
$table = new Table();
echo $chair->equals( $table );
?>
This code gives the expected result "Fatal error: Argument 1 passed to Chair::equals() must be an instance of Chair, called in
[filename] on line 38 and defined in [filename] on line 16". This is the proper behavior but isn't the most intuitive approach
for those of us used to OO programming.
Hope this helps someone :-).
Nicholas

02-Sep-2006 08:59
The type hinting system can also be used for interfaces. Example:
<?php
interface fooface
{
public function foo ();
}
class fooclass implements fooface
{
public function foo ()
{
echo ('foo<br>');
}
}
class barclass implements fooface
{
public function foo ()
{
echo ('bar<br>');
}
}
class bazclass implements fooface
{
public function foo ()
{

echo ('baz<br>');
}
}
class quuxclass
{
public function foo ()
{
echo ('quux<br>');
}
}
function callfoo (fooface $myClass)
{
$myClass -> foo ();
}
$myfoo = new fooclass;
$mybar = new barclass;
$mybaz = new bazclass;
$myquux = new quuxclass;
callfoo ($myfoo);
callfoo ($mybar);
callfoo ($mybaz);
callfoo ($myquux); // Fails because the quuxclass doesn't implement the fooface interface
?>
Using this syntax you can allow a function to work with different classes as long as they all implement the same interfaces.
An example might be an online shop that implements a plugin system for payment. If the creator of the script provides a
payment module interface then functions can check if it has been implemented in a given payment class. This means that the
details of the class are unimportant, so it doesn't matter if it interfaces with PayPal, HSBC, ProTX or any other payment
system you care to name, but if it doesn't properly provide all the functionality a payment module requires a fatal error is
generated.
Unfortunately, it doesn't seem possible to use type hinting with new. In java you could do a "fooface myfoo = new fooclass"
which would fail if you tried it with quuxclass instead, but as far as I can tell you can't do a similar test on create with
PHP.

mlovett at morpace dot com 06-Jul-2005 03:54


Type hinting works with interfaces too. In other words, you can specify the name of an interface for a function parameter, and
the object passed in must implement that interface, or else type hinting throws an exception.

caliban at darklock dot com 23-Feb-2005 07:34


In case you're worried, type hinting does allow descendants. Extending the documentation example:
<?php
// Example class
class MyClass
{
public function test(OtherClass $otherclass)
{
if(is_callable(array($otherclass,$otherclass->var)))
{
$otherclass->{$otherclass->var}();
}

else
{
echo $otherclass->var;
}
}
}
// Another example class
class OtherClass
{
public $var = 'Hello World';
}
// Yet another example class
class DerivedClass extends OtherClass
{
function __construct()
{
$this->var="Planet";
}
public function Planet()
{
echo "Hello ".$this->var;
}
}
$myclass = new MyClass;
$otherclass = new OtherClass;
$derivedclass = new DerivedClass;
// Works - prints "Hello World"
$myclass->test($otherclass);
// Works - calls DerivedClass::Planet()
// which prints "Hello Planet"
$myclass->test($derivedclass);
?>

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Late Static Bindings


As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called
class in a context of static inheritance.
More precisely, late static bindings work by storing the class named in the last "non-forwarding call". In case of
static method calls, this is the class explicitly named (usually the one on the left of the :: operator); in case of
non static method calls, it is the class of the object. A "forwarding call" is a static one that is introduced by
self::, parent::, static::, or, if going up in the class hierarchy, forward_static_call(). The function
get_called_class() can be used to retrieve a string with the name of the called class and static:: introduces its
scope.
This feature was named "late static bindings" with an internal perspective in mind. "Late binding" comes from
the fact that static:: will not be resolved using the class where the method is defined but it will rather be
computed using runtime information. It was also called a "static binding" as it can be used for (but is not limited
to) static method calls.

Limitations of self::
Static references to the current class like self:: or __CLASS__ are resolved using the class in which the
function belongs, as in where it was defined:
Example #1 self:: usage
<?php
classA{
publicstaticfunctionwho(){
echo__CLASS__;
}
publicstaticfunctiontest(){
self::who();
}
}
classBextendsA{
publicstaticfunctionwho(){
echo__CLASS__;
}
}
B::test();
?>

The above example will output:


A

Late Static Bindings' usage


Late static bindings tries to solve that limitation by introducing a keyword that references the class that was
initially called at runtime. Basically, a keyword that would allow you to reference B from test() in the previous
example. It was decided not to introduce a new keyword but rather use static that was already reserved.
Example #2 static:: simple usage
<?php
classA{

publicstaticfunctionwho(){
echo__CLASS__;
}
publicstaticfunctiontest(){
static::who();//HerecomesLateStaticBindings
}
}
classBextendsA{
publicstaticfunctionwho(){
echo__CLASS__;
}
}
B::test();
?>

The above example will output:


B

Note:
In non-static contexts, the called class will be the class of the object instance. Since $this-> will try to call
private methods from the same scope, using static:: may give different results. Another difference is that
static:: can only refer to static properties.
Example #3 static:: usage in a non-static context
<?php
classA{
privatefunctionfoo(){
echo"success!\n";
}
publicfunctiontest(){
$this->foo();
static::foo();
}
}
classBextendsA{
/*foo()willbecopiedtoB,henceitsscopewillstillbeAand
*thecallbesuccessful*/
}
classCextendsA{
privatefunctionfoo(){
/*originalmethodisreplaced;thescopeofthenewoneisC*/
}
}
$b=newB();
$b->test();
$c=newC();
$c->test();//fails
?>

The above example will output:


success!
success!
success!

Fatal error:

Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

Note:
Late static bindings' resolution will stop at a fully resolved static call with no fallback. On the other hand,
static calls using keywords like parent:: or self:: will forward the calling information.
Example #4 Forwarding and non-forwarding calls
<?php
classA{
publicstaticfunctionfoo(){
static::who();
}
publicstaticfunctionwho(){
echo__CLASS__."\n";
}
}
classBextendsA{
publicstaticfunctiontest(){
A::foo();
parent::foo();
self::foo();
}
publicstaticfunctionwho(){
echo__CLASS__."\n";
}
}
classCextendsB{
publicstaticfunctionwho(){
echo__CLASS__."\n";
}
}
C::test();
?>

The above example will output:


A
C
C

User Contributed Notes

Late Static Bindings

fchoquet at NOSPAM dot example dot com 25-Oct-2011 06:36


A tricky behaviour of LSB:
If you forget a "static" keywork in the method definition you can get very unexpected results.
<?php
class BaseClass {
public function callTest() { // static accidentally omitted
static::test();
}

protected static function test() {


echo 'BaseClass::test<br />';
}
}
class ExtendedClass extends BaseClass {
protected static function test() {
echo 'ExtendedClass::test<br />';
}
}
class UserClass {
public function useExtendedClass() {
ExtendedClass::callTest(); // Static call of the *acidentally* non static method
}
public function test() {
echo 'UserClass::test<br />';
}
}
BaseClass::callTest(); // BaseClass::test, as expected
ExtendedClass::callTest(); // ExtendedClass::test, as expected
$userClass = new UserClass();
$userClass->useExtendedClass(); // ExtendedClass::test is expected, but displays UserClass::test!!!
?>

brendel at krumedia dot de 21-Mar-2011 06:37


In my opinion late static binding is an anti pattern but there are some benefits though:
<?php
class MyClass extends ClassReference
{
}
?>
MyClass::getQualifiedName() returns the full class name including namespace information. This prevents you from passing class
names as plain strings and still lets you take advantage of code completion and type browsing.
MyClass::cast() ensures the type of an object to be of a certain class. This is a kind of type hinting.
<?php

abstract class ClassReference


{

final public static function getQualifiedName()


{
return get_called_class();
}

final public static function cast($object)


{
$className = get_called_class();
if (!is_object($var) || !($object instanceof $className))
{
throw new UnexpectedValueException("Cast failed. Argument is not of type " . $className . ".");
}
return $object;
}

}
?>

jrfish dot x at gmail dot com 09-Dec-2010 04:05


also works the same way with static variables and constants

jrfish dot x at gmail dot com 09-Dec-2010 04:01


consider this:
<?php
class A
{
// some stuff....
public static function getInstance()
{
return new self();
}
}
class B extends A
{
//stuff...
}
$obj = B::getInstance();
//versus
class A
{
// some stuff....
public static function getInstance()
{

return new static();


}
}
class B extends A
{
//stuff...
}
$obj = B::getInstance();
?>
also works the same way with static variables and constants

Anonymous 24-Nov-2010 09:22


THIS WORKED GREAT FOR ME:
<?php
abstract class ParentClass
{
static function parent_method()
{
$child_class_str = self::get_child_class();
eval("\$r = ".$child_class_str."::abstract_static();");
return $r;
}// CHILD MUST OVERRIDE TO PUT ITSELF INTO TRACE
protected abstract static function abstract_static();
private static function get_child_class()
{
$backtrace = debug_backtrace();
$num = count($backtrace);
for($i = 0; $i < $num; $i++)
{
if($backtrace[$i]["class"] !== __CLASS__)
return $backtrace[$i]["class"];
}
return null;
}
}
class ChildClass extends ParentClass
{
static function parent_method(){ return parent::parent_method(); }
protected static function abstract_static()
{
return __METHOD__."()";
}// From ParentClass
}
print "The call was: ". ChildClass::parent_method();
?>

jakub dot lopuszanski at nasza-klasa dot pl 08-Nov-2010 10:12

Suprisingly consts are also lazy bound even though you use self instead of static:
<?php
class A{
const X=1;
const Y=self::X;
}
class B extends A{
const X=1.0;
}
var_dump(B::Y); // float(1.0)
?>

tfn dot yldrm at hotmail dot com 26-Oct-2010 12:30


example for static binding on 5.2 and real enumaration
<?php
/**
* Static Binding On PHP 5.2
* @author Tufan Baris YILDIRIM
* @since 26.10.2010
*/
abstract class EnumBase
{
protected $num = 0;
public $toString;
public $toInt;
public function __construct($enumKeyOrVal)
{
unset($this->toString,$this->toInt);
$enums = $this->enums();
if(
empty($enumKeyOrVal)
||
!(isset($enums[$this->num = $enumKeyOrVal])
||
($this->num = array_search($enumKeyOrVal,$enums)) !== false)
)
$this->num = 0;
/**
* 5.3 Version
*/
/*
* if(
empty($enumKeyOrVal)
||
!(isset(static::$enums[$this->num = $enumKeyOrVal])
||
($this->num = array_search($enumKeyOrVal,static::$enums)) !== false)
)
$this->num = 0;
*/
}
#5.3 e geilirse gerek kalmaz.

public function vars()


{
return get_class_vars(get_class($this));
}
public function enums()
{
$vars = $this->vars();
return $vars['enums'];
}
public function __get($property)
{
if(method_exists($this,'__'.$property))
return $this->{'__'.$property}();
else
return $this->__toString();
}
public function __toInt()
{
return $this->num;
}
public function __toString()
{
$enums = $this->enums();
if(isset($enums[$this->num]))
{
return $enums[$this->num];
}
else
{
return $enums[0];
}
/**
* 5.3 Version
*/
/*
if(isset(static::$enums[$this->num]))
{
return static::$enums[$this->num];
}
else
{
return static::$enums[0];
}
*/
}
}
class Positions extends EnumBase
{
public static $enums = array(
0 => 'Bilinmiyor',
1 => 'Kale',

2 => 'Defans',
3 => 'Orta Saha',
4 => 'Forvet'
);
}

$a = new Positions('Orta Saha');
$b = new Positions(4);
$c = (string)$a; // Orta Saha
$d = (string)$b; // Forvet
?>

fabiolimasouto at gmail dot com 15-Oct-2010 05:10


<?php
// tricky implementation of singleton
// creates a function handle to work with the child singleton
// so you can get the object doing: ClassName() instead of ClassName::getInstance()
// or get some property rightaway: ClassName('nameOfPublicProperty');
// enjoy!!
Abstract class SingletonBase
{
protected function __clone(){}
public function getInstance()
{
static $instance = null;
if($instance==null)
{
$instance = new static;
if(!function_exists($name=get_called_class()))
{
$strCode = "function {$name}(\$attribute=null){
static \$obj = null;
!\$obj AND \$obj = {$name}::getInstance();
return \$attribute ? \$obj->\$attribute : \$obj;
}";
// creates the getInstance handle function
eval($strCode);
}
}
return $instance;
}
}
// EXAMPLE
class MySingletonClass extends SingletonBase
{
var $varTest = "somevalue";
}
$obj = MySingletonClass::getInstance();
echo $obj->varTest; // somevalue
echo MySingletonClass('varTest'); // somevalue
$obj = MySingletonClass();
echo $obj->varTest; // somevalue

?>

steven dot karas+nospam at gmail dot com 27-Sep-2010 02:38


This function can be used as a workaround for late static binding in PHP >= 5.1.0. There was another similar version of this
function elsewhere, but used eval.
<?php
function & static_var($class, $name)
{
if (is_object($class))
{
$class = get_class($class);
}
elseif ( ! is_string($class))
{
throw new Exception('Must be given an object or a class name', NULL);
}

$class = new ReflectionClass($class);


return $class->getStaticPropertyValue($name);
}
?>

adam dot prall at thinkingman dot com 11-Jun-2010 09:51


Just a quick reminder to always check your syntax. While I love LSB, I thought it wasn't working:
static::$sKey = not set
until I realized that Id completely forgotten to make it a variable variable:
$sKey = 'testStaticClassVarNameThatExistsInThisClassesScope';
static::$$sKey = is set
of course this applies anywhere in PHP, but because of the (current) newness late static bindings, Ive seen lots of code with
this particular snafu in it from others.

James 29-Apr-2010 03:59


If you're still stuck on a pre-5.3 codebase then you can fake a singleton superclass like this. It ain't pretty, though. To
do it you pass the type info down the stack manually and then abuse call_user_func to pass the value back to the originating
class so that you can access it's static properties.
<?php
abstract class Singleton {
protected function __construct() {}
protected function __clone() {}
public function instance($class) {
$member = 'instance';
$instance = self::getStaticMember($class, $member);
if (!$instance instanceof $class) {
$instance = new $class();
self::setStaticMember($class, $member, $instance);

}
return $instance;
}

protected function setStaticMember($class, $member, $value) { call_user_func(array($class, __FUNCTION__), $member, $value);


}
protected function getStaticMember($class, $member) { return call_user_func(array($class, __FUNCTION__), $member); }
}
class MySingleton extends Singleton {
protected static $instance = null;
public function instance() { return parent::instance(__CLASS__); }
protected function setStaticMember($member, $value) { self::$$member = $value; }
protected function getStaticMember($member) { return self::$$member; }
}
?>

joost dot t dot hart at planet dot nl 21-Aug-2009 06:34


PHP5.3 unavailable, yet in the need for 'static', I did the following.
Any objections? Personally I hate using the the eval() statement...
<?php
class mother
{
function setStatic( $prop, $val ) {
// After this, self:: refers to mother, yet next $class refers to...
//
$class = get_class( $this );
eval( "$class::\$$prop = \$$val;" );
}
}
class child extends mother
{
protected static $sProp;
function writer( $value ) {
parent::setStatic( 'sProp', $value );
}
function reader()
{
return self::$sProp;
}
}
$c = new child();
$c->writer( 3 );
echo $c->reader(); // 3
?>

tom 03-Jul-2009 06:28

Something you may find useful for passive code-testing:


<?php
class BaseClass {
function __get($id) {
throw new Exception("Trying to access undefined property '$id'.");
}
function __set($id) {
throw new Exception("Trying to access undefined property '$id'.");
}
}
class MyClass extends BaseClass {
// my implementation
}
?>
Using these magic function as described above will help you to find classes that try to access an undefined (and undocumented)
class-member. In most cases: this is an error based on misspelled member names.

kenneth at kennethjorgensen dot com 30-Mar-2009 02:19


Simple basic class which uses to get_called_class() to create singleton instances. A previous post by php at mikebird dot co
dot uk explain how to do this, but the extended static variables require you to define them in child classes before they work.
<?php
abstract class Singleton {
private static $instances = array();

public function __construct() {


$class = get_called_class();
if (array_key_exists($class, self::$instances))
trigger_error("Tried to construct a second instance of class \"$class\"", E_USER_WARNING);
}

public static function getInstance() {


$class = get_called_class();
if (array_key_exists($class, self::$instances) === false)
self::$instances[$class] = new $class();
return self::$instances[$class];
}
}
class A extends Singleton {
}
class B extends Singleton {
}
$a1 = A::getInstance();
$a2 = A::getInstance();
$b1 = B::getInstance();
$b2 = B::getInstance();
if (get_class($a1) == "A" &&
get_class($a2) == "A" &&
get_class($b1) == "B" &&
get_class($b2) == "B" &&

$a1 === $a2 &&


$b1 === $b2)
echo "All good\n";
else
echo "FAIL!\n";
?>
You probably noticed the use of self:: rather than static::, this is because we want the static variable to be private, and
using static:: will not allow us to do that.

lazybones_senior 01-Oct-2008 12:30


WHOA... KEEP IT SIMPLE!
Remember, when you write a class definition, you are creating a new "type" of object. And when you extend those classes, you
are creating a heirarchy. To get to the point... all the class defs below work together to provide a solid organization of
data.
<?php
abstract class Animal {
protected $type, $name;
public function __construct($aType, $aName) {
$this->type = $aType;
$this->name = $aName;
}
public function __toString() {
return "Animal [type=$this->type, name=$this->name]";
}
}
class Dog extends Animal {
public function __construct($aName) {
parent::__construct("Dog", $aName);
}
}
class Cat extends Animal {
public function __construct($aName) {
parent::__construct("Cat", $aName);
}
}
echo 'My dog: ' . (new Dog('Sam')) . '<br>';
echo 'My cat: ' . (new Cat('Fluffy')) . '<br>';
echo 'Your dog: ' . (new Dog('Walter')) . '<br>';
echo 'Yout cat: ' . (new Cat('Ginger'));
?>
My dog: Animal[type=Dog, name=Sam]
My cat: Animal[type=Cat, name=Fluffy]
Your dog: Animal[type=Dog, name=Walter]
Yout cat: Animal[type=Cat, name=Ginger]
... and notice the property called $type, is the same as using __CLASS__ in most of the previous posts, but without the

complexities of the PHP language.

gern_ at hotmail dot com 18-Sep-2008 07:51


get_called_class for PHP < 5.3
<?php
/**
* Return called class name
*
* @author Michael Grenier
* @param int $i_level optional
* @return string
*/
function get_called_class ($i_level = 1)
{
$a_debug = debug_backtrace();
$a_called = array();
$a_called_function = $a_debug[$i_level]['function'];
for ($i = 1, $n = sizeof($a_debug); $i < $n; $i++)
{
if (in_array($a_debug[$i]['function'], array('eval')) ||
strpos($a_debug[$i]['function'], 'eval()') !== false)
continue;
if (in_array($a_debug[$i]['function'], array('__call', '__callStatic')))
$a_called_function = $a_debug[$i]['args'][0];
if ($a_debug[$i]['function'] == $a_called_function)
$a_called = $a_debug[$i];
}
if (isset($a_called['object']) && isset($a_called['class']))
return (string)$a_called['class'];
$i_line = (int)$a_called['line'] - 1;
$a_lines = explode("\n", file_get_contents($a_called['file']));
preg_match("#([a-zA-Z0-9_]+){$a_called['type']}
{$a_called['function']}( )*\(#", $a_lines[$i_line], $a_match);
unset($a_debug, $a_called, $a_called_function, $i_line, $a_lines);
if (sizeof($a_match) > 0)
$s_class = (string)trim($a_match[1]);
else
$s_class = (string)$a_called['class'];
if ($s_class == 'self')
return get_called_class($i_level + 2);
return $s_class;
}
?>

kx 14-Sep-2008 09:39
At least as of PHP 5.3.0a2 there's a function get_called_class(), which returns the class on which the static method is called.
<?php
class a {
static public function test() {
print get_called_class();
}
}

class b extends a {
}
a::test(); // "a"
b::test(); // "b"
?>

iamscrumpyjack 07-Sep-2008 09:01


I have been dying to see this issue resolved. I'm very much looking forward to the production release of PHP 5.3...
In my case I have been trying to do the following:
class A {
function __construct() {
echo "I was called by " . static::__CLASS__;
}
}
class B extends A {
function Foo() {
echo "I am class " . __CLASS__;
}
}
$b = new B; // Should echo "I was called by B"
$b->Foo(); // Should echo "I am class B"
At the moment I do the following workaround:
class A {
function __construct($child) {
echo "I was called by " . $child;
}
}
class B extends A {
function __construct() {
parent::__construct(__CLASS__);
}
function Foo() {
echo "I am class " . __CLASS__;
}
}
$b = new B; // Echos "I was called by B"
$b->Foo(); // Echo "I am class B"
As you can see, my current workaround has some overhead and is not as water-tight as the late static binding method.

sebastien at info-conseil dot fr 17-Jul-2008 07:26


Here is a small workaround I made for the static inheritance issue. It's not perfect, but it works.
<?php

// BaseClass class will be extended by any class needing static inheritance workaroud
class BaseClass {
// Temporarily stores class name for Entry::getStatic() and Entry::setNextStatic()
protected static $nextStatic = false;

// Returns the real name of the class calling the method, not the one in which it was declared.
protected static function getStatic() {
// If already stored
if (self::$nextStatic) {
// Clean and return
$class = self::$nextStatic;
self::$nextStatic = false;
return $class;
}

// Init
$backTrace = debug_backtrace();
$class = false;

// Walk through
for ($i=0; $i<count($backTrace); $i++) {
// If a class is defined
if (isset($backTrace[$i]['class'])) {
// Check if it is not a basic class
if (!in_array($backTrace[$i]['class'], array('BaseClass', 'GenericClass'))) {
return $backTrace[$i]['class'];
} else {
$class = $backTrace[$i]['class'];
}
} else {
// Returns last known class
return $class;
}
}

// Default
return $class;
}

// If a static method is called within global env, the previous method won't work, so we need to tell BaseClass which
public static function setNextStatic($class) {
// Save value
self::$nextStatic = $class;
}
}
// Generic class declaring various static methods
class GenericClass extends BaseClass {
public static $name = 'Generic';

public function getName() {


$static = get_class_vars(get_class($this));
return $static['name'];
}

public static function basicClassName() {


return self::$name;
}

public static function staticClassName() {

// Get real name


$staticName = self::getStatic();

// Return final class name
$static = get_class_vars($staticName);
return $static['name'];
}
}
// Final class
class SomeClass extends GenericClass {
public static $name = 'Some';

public static function returnClassNameWith($string) {


return $string.' : '.self::staticClassName();
}
}
// Instance call
// Will print 'Some'
$a = new SomeClass();
echo 'Name of $a : '.$a->getName().'<br />';
// Static calls
// Will print 'Generic'
echo 'Basic call to SomeClass::$name : '.SomeClass::basicClassName().'<br />';
// Will print 'Generic'
echo 'Global call to SomeClass::$name : '.SomeClass::staticClassName().'<br />';
// Will print 'Some'
BaseClass::setNextStatic('SomeClass');
echo 'Global call to SomeClass::$name with pre-set : '.SomeClass::staticClassName().'<br />';
// Will print 'Some'
echo 'Internal call to SomeClass::$name : '.SomeClass::returnClassNameWith('This is a ').'<br />';
?>
There are two issues with this workaround :
- if you call a static method from global env, you need to declare the name of the class BEFORE calling the method, otherwise
the workaround won't work (see 3rd and 4th examples). But I assume good programming makes few calls to static methods from
global scope, so this shouldn't be long to fix if you use it.
- the workaround fails to access to private or protected static vars, as it uses get_class_vars(). If you find any better
solution, let us know.
With Php 5.3.0, upgrading will be easy : just delete the methods from the basic class, and search/replace any call to
getStatic() and setNextStatic() by static:: - or one could use a selector on PHP_VERSION value to include either the BaseClass
file with workaround or a BaseClass file using static::

Anonymous 12-Jul-2008 12:49


Trying to recreate an inheritable static part for an object through a singleton pattern.
<?php
/**
* "Inheritable static" for PHP < 5.3

* << Library/Inheritable.php >>


*/
abstract class Inheritable_Static extends Singleton
{
}
abstract class Inheritable
{
public static function getStatic($className)
{
// Use an abstract Singleton
return Singleton::getInstance($className . '_Static') ;
}

public function goStatic()


{
return self::getStatic(get_class($this)) ;
}
}
/**
* Abstract
* << Library/SayIt/Abstract.php >>
*/
abstract class SayIt_Abstract_Static extends Inheritable_Static
{
public $format ;
}
abstract class SayIt_Abstract extends Inheritable
{
protected $_name ;

public function __construct($name)


{
$this->_name = $name ;
}

final public function sayIt()


{
echo sprintf($this->goStatic()->format, $this->_name) . "\n" ;
}

}
/**
* Concrete
* << Library/SayIt/Hello.php >>
*/
class SayIt_Hello_Static extends SayIt_Abstract_Static
{
}
class SayIt_Hello extends SayIt_Abstract
{
public static function getStatic() { return parent::getStatic(__CLASS__) ; }
}

/**
* Test
*/
SayIt_Hello::getStatic()->format = 'Hello %s' ;
$w = new SayIt_Hello('World') ;
$j = new SayIt_Hello('Joe') ;
echo $w->sayIt() ; // Hello World
echo $j->sayIt() ; // Hello Joe

Andrea Giammarchi 21-Jun-2008 01:06


About static parameters, these work as expected.
<?php
class A {
protected static $__CLASS__ = __CLASS__;
public static function constructor(){
return static::$__CLASS__;
}
}
class B extends A {
protected static $__CLASS__ = __CLASS__;
}
echo B::constructor(); // B
?>

martinpauly [at] google mail [dot] com 18-Jun-2008 05:54


will this work for variables as well?
it would be great, if the following worked:
<?php
class A {
protected static $table = "table";
public static function connect(){
//do some stuff here
echo static::$table;
return static::getInstance(); //function getInstance() now can return classes A or B depending on the context it was
called
}
...
}
class B extends A {
protected static $table = "subtable";
...
}
$table = B::connect(); //hopefully the output will be: subtable
?>

deadimp at gmail dot com 05-Jun-2008 10:39


I think this will be pretty helpful too.
My question is, can just 'static' by itself resolve to the late static class?
I ask this because it could help in making new instances of the derived class, from a base class, by calling a derived class's
static method instead of having to create a new instance of the derived class - or explicitly defining a 'getClass' method for
each derived class.
Example:
<?php
//There isn't really any purpose for this example I posted
//Just a random implementation
class Base {
static function useful() {
//Create a list of instances of the derived class
$list=array();
for ($i=0;$i<10;$i++) $list[]=new static(); //Here's the point in question
return $list;
}
}
class Derived extends Base {
static function somethingElse() {
//...
$list=static::useful();
}
}
?>
I'm not sure what kind of lexical / whatever-it's-called problems this would make with parsing. I don't think it could really
collide with any contexts where you would use static otherwise - variable / method declaration.
Even more so, is there a way to get the class's name to which the keywords 'self', 'parent', or 'static' refer?
Example:
<?php
class Base {
static function stuff() {
echo "Self: ".get_class(self);
echo "Parent: ".get_class(parent);
echo "Derived: ".get_class(static);
}
}
class Derived extends Base {
static function stuff() {
static::stuff();
}
}
?>
I don't think there should be a massive bloat in the PHP core to support all of this, but it would be nice to take advantage
of the dynamic nature of PHP.
And yet another side note:
If you're in the instance-level scope in a method of a base, and you want to get a top-level static, here's an ugly workaround
(from Thacmus /lib/core.php - see SVN repo):
<?php
//Get reference [?] to static from class
//$class - Class name OR object (uses get_class())
//$var - Not gonna say
function& get_static($class,$var) { //'static_get'?
if (!is_string($class)) $class=get_class($class);
if (!@property_exists($class,$var)) {
trigger_error("Static property does not exist: $class::\$$var");

//debug_callstack(); //This is just a wrapper for debug_backtrace() for HTML


return null;
}
//Store a reference so that the base data can be referred to
//The code [[ return eval('return &'.$class.'::$'.$var.';') ]] does not work - can not return references...
//To establish the reference, use [[ $ref=&get_static(...) ]]
eval('$temp=&'.$class.'::$'.$var.';'); //using
return $temp;
}
?>

tyler AT canfone [dot] COM 04-Jun-2008 10:48


@ php at mikebird
You can pass arguments to your constructor through your getInstance method, assuming you are running php5.
public static function getInstance($params = null) {
if (self::$objInstance == null) {
$strClass = static::getClass();
self::$objInstance = new $strClass($params);
}
return self::$objInstance;
}
This would pass the params to your constructor. Love for php.

sergei at 2440media dot com 28-May-2008 01:22


Finally we can implement some ActiveRecord methods:
<?php
class Model
{
public static function find()
{
echo static::$name;
}
}
class Product extends Model
{
protected static $name = 'Product';
}
Product::find();
?>
Output: 'Product'

php at mikebird dot co dot uk 23-Apr-2008 08:39


This should make life easier and neater if you have a project with a lot of singleton classes e.g.
<?php

class Singleton {

public static $objInstance;

public static function &getInstance() {


if (self::$objInstance == null) {
$strClass = static::getClass();
self::$objInstance = new $strClass;
}
return self::$objInstance;
}

public static function getClass() {
return __CLASS__;
}

}
class Foo extends Singleton {

public $intBar;

public function __construct() {
$this->intBar = 1;
}

public static function getClass() {
return __CLASS__;
}

}

$objFooTwo = Foo::getInstance();
$objFooTwo->intBar = 2;

$objFooOne = Foo::getInstance();

if ($objFooOne->intBar == $objFooTwo->intBar) {
echo 'it is a singleton';
} else {
echo 'it is not a singleton';
}
?>
The above will output 'it is a singleton'. The obvious downfall to this method is not being able to give arguments to the
constructor.

max at mastershrimp dot com 10-Apr-2008 03:24


If you are using PHP < 5.3.0 you might be interested in the following workaround for late static binding:
http://de2.php.net/manual/de/function.get-class.php#77698

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Objects and references


One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by
default". This is not completely true. This section rectifies that general thought using some examples.
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an
object variable doesn't contain the object itself as value anymore. It only contains an object identifier which
allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to
another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the
same object.
Example #1 References and Objects
<?php
classA{
public$foo=1;
}
$a=newA;
$b=$a;//$aand$barecopiesofthesameidentifier
//($a)=($b)=<id>
$b->foo=2;
echo$a->foo."\n";

$c=newA;
$d=&$c;//$cand$darereferences
//($c,$d)=<id>
$d->foo=2;
echo$c->foo."\n";

$e=newA;
functionfoo($obj){
//($obj)=($e)=<id>
$obj->foo=2;
}
foo($e);
echo$e->foo."\n";
?>

The above example will output:


2
2
2

User Contributed Notes

Objects and references

kristof at viewranger dot com 16-Jun-2012 02:07

I hope this clarifies references a bit more:


<?php
class A {
public $foo = 1;
}
$a = new A;
$b = $a;
$a->foo = 2;
$a = NULL;
echo $b->foo."\n"; // 2
$c = new A;
$d = &$c;
$c->foo = 2;
$c = NULL;
echo $d->foo."\n"; // Notice: Trying to get property of non-object...
?>

Anonymous 23-Nov-2011 07:57


this example could help:
<?php
class A {
public $testA = 1;
}
class B {
public $testB = "class B";
}
$a = new A;
$b = $a;
$b->testA = 2;
$c = new B;
$a = $c;
$a->testB = "Changed Class B";
echo "<br/> object a: "; var_dump($a);
echo "<br/> object b: "; var_dump($b);
echo "<br/> object c: "; var_dump($c);
// by reference
$aa = new A;
$bb = &$aa;
$bb->testA = 2;
$cc = new B;
$aa = $cc;
$aa->testB = "Changed Class B";
echo "<br/> object aa: "; var_dump($aa);
echo "<br/> object bb: "; var_dump($bb);

echo "<br/> object cc: "; var_dump($cc);


?>

Rob Marscher 03-Feb-2011 09:33


Here's an example I created that helped me understand the difference between passing objects by reference and by value in php
5.
<?php
class A {
public $foo = 'empty';
}
class B {
public $foo = 'empty';
public $bar = 'hello';
}
function normalAssignment($obj) {
$obj->foo = 'changed';
$obj = new B;
}
function referenceAssignment(&$obj) {
$obj->foo = 'changed';
$obj = new B;
}
$a = new A;
normalAssignment($a);
echo get_class($a), "\n";
echo "foo = {$a->foo}\n";
referenceAssignment($a);
echo get_class($a), "\n";
echo "foo = {$a->foo}\n";
echo "bar = {$a->bar}\n";
/*
prints:
A
foo = changed
B
foo = empty
bar = hello
*/
?>

Anonymous 16-Jan-2011 08:51


There seems to be some confusion here. The distinction between pointers and references is not particularly helpful.
The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code,
for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)
First principle:
A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't
delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)

2nd principle, and source of the most confusion:


Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed
by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is
done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be
accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.
3rd principle:
"&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you
decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly
separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often
the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference"
that were clearer in C and C++.
Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original
unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object
will the originals change.
Example:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}

?>

Hayley Watson 29-Mar-2010 07:21


Using &$this can result in some weird and counter-intuitive behaviour - it starts lying to you.
<?php
class Bar
{
public $prop = 42;
}
class Foo
{
public $prop = 17;
function boom()
{
$bar = &$this;
echo "\$bar is an alias of \$this, a Foo.\n";
echo '$this is a ', get_class($this), '; $bar is a ', get_class($bar), "\n";
echo "Are they the same object? ", ($bar === $this ? "Yes\n" : "No\n");
echo "Are they equal? ", ($bar === $this ? "Yes\n" : "No\n");
echo '$this says its prop value is ';
echo $this->prop;
echo ' and $bar says it is ';
echo $bar->prop;
echo "\n";
echo "\n";
$bar = new Bar;
echo "\$bar has been made into a new Bar.\n";
echo '$this is a ', get_class($this), '; $bar is a ', get_class($bar), "\n";
echo "Are they the same object? ", ($bar === $this ? "Yes\n" : "No\n");
echo "Are they equal? ", ($bar === $this ? "Yes\n" : "No\n");
echo '$this says its prop value is ';
echo $this->prop;
echo ' and $bar says it is ';
echo $bar->prop;
echo "\n";
}
}
$t = new Foo;
$t->boom();
?>
In the above $this claims to be a Bar (in fact it claims to be the very same object that $bar is), while still having all the
properties and methods of a Foo.
Fortunately it doesn't persist beyond the method where you committed the faux pas.
<?php
echo get_class($t), "\t", $t->prop;
?>

miklcct at gmail dot com 07-Jan-2010 01:34


Notes on reference:
A reference is not a pointer. However, an object handle IS a pointer. Example:
<?php
class Foo {
private static $used;
private $id;
public function __construct() {
$id = $used++;
}
public function __clone() {
$id = $used++;
}
}
$a = new Foo; // $a is a pointer pointing to Foo object 0
$b = $a; // $b is a pointer pointing to Foo object 0, however, $b is a copy of $a
$c = &$a; // $c and $a are now references of a pointer pointing to Foo object 0
$a = new Foo; // $a and $c are now references of a pointer pointing to Foo object 1, $b is still a pointer pointing to Foo
object 0
unset($a); // A reference with reference count 1 is automatically converted back to a value. Now $c is a pointer to Foo object
1
$a = &$b; // $a and $b are now references of a pointer pointing to Foo object 0
$a = NULL; // $a and $b now become a reference to NULL. Foo object 0 can be garbage collected now
unset($b); // $b no longer exists and $a is now NULL
$a = clone $c; // $a is now a pointer to Foo object 2, $c remains a pointer to Foo object 1
unset($c); // Foo object 1 can be garbage collected now.
$c = $a; // $c and $a are pointers pointing to Foo object 2
unset($a); // Foo object 2 is still pointed by $c
$a = &$c; // Foo object 2 has 1 pointers pointing to it only, that pointer has 2 references: $a and $c;
const ABC = TRUE;
if(ABC) {
$a = NULL; // Foo object 2 can be garbage collected now because $a and $c are now a reference to the same NULL value
} else {
unset($a); // Foo object 2 is still pointed to $c
}

mjung at poczta dot onet dot pl 15-Aug-2009 10:25


Ultimate explanation to object references:
NOTE: wording 'points to' could be easily replaced with 'refers ' and is used loosly.
<?php
$a1 = new A(1); // $a1 == handle1-1 to A(1)
$a2 = $a1; // $a2 == handle1-2 to A(1) - assigned by value (copy)
$a3 = &$a1; // $a3 points to $a1 (handle1-1)
$a3 = null; // makes $a1==null, $a3 (still) points to $a1, $a2 == handle1-2 (same object instance A(1))
$a2 = null; // makes $a2 == null
$a1 = new A(2); //makes $a1 == handle2-1 to new object and $a3 (still) points to $a1 => handle2-1 (new object), so value of
$a1 and $a3 is the new object and $a2 == null
//By reference:
$a4 = &new A(4); //$a4 points to handle4-1 to A(4)
$a5 = $a4; // $a5 == handle4-2 to A(4) (copy)
$a6 = &$a4; //$a6 points to (handle4-1), not to $a4 (reference to reference references the referenced object handle4-1 not
the reference itself)
$a4 = &new A(40); // $a4 points to handle40-1, $a5 == handle4-2 and $a6 still points to handle4-1 to A(4)
$a6 = null; // sets handle4-1 to null; $a5 == handle4-2 = A(4); $a4 points to handle40-1; $a6 points to null
$a6 =&$a4; // $a6 points to handle40-1

$a7 = &$a6; //$a7 points to handle40-1


$a8 = &$a7; //$a8 points to handle40-1
$a5 = $a7; //$a5 == handle40-2 (copy)
$a6 = null; //makes handle40-1 null, all variables pointing to (hanlde40-1 ==null) are null, except ($a5 == handle40-2 =
A(40))
?>
Hope this helps.

Aaron Bond 19-Jun-2009 06:08


I've bumped into a behavior that helped clarify the difference between objects and identifiers for me.
When we hand off an object variable, we get an identifier to that object's value. This means that if I were to mutate the
object from a passed variable, ALL variables originating from that instance of the object will change.
HOWEVER, if I set that object variable to new instance, it replaces the identifier itself with a new identifier and leaves the
old instance in tact.
Take the following example:
<?php
class A {
public $foo = 1;
}
class B {
public function foo(A $bar)
{
$bar->foo = 42;
}

public function bar(A $bar)


{
$bar = new A;
}
}
$f = new A;
$g = new B;
echo $f->foo . "\n";
$g->foo($f);
echo $f->foo . "\n";
$g->bar($f);
echo $f->foo . "\n";
?>
If object variables were always references, we'd expect the following output:
1
42
1
However, we get:
1
42
42

The reason for this is simple. In the bar function of the B class, we replace the identifier you passed in, which identified
the same instance of the A class as your $f variable, with a brand new A class identifier. Creating a new instance of A
doesn't mutate $f because $f wasn't passed as a reference.
To get the reference behavior, one would have to enter the following for class B:
<?php
class B {
public function foo(A $bar)
{
$bar->foo = 42;
}

public function bar(A &$bar)


{
$bar = new A;
}
}
?>
The foo function doesn't require a reference, because it is MUTATING an object instance that $bar identifies. But bar will be
REPLACING the object instance. If only an identifier is passed, the variable identifier will be overwritten but the object
instance will be left in place.

Ivan Bertona 15-Oct-2008 08:45


A point that in my opinion is not stressed enough in the manual page is that in PHP5, passing an object as an argument of a
function call with no use of the & operator means passing BY VALUE an unique identifier for that object (intended as instance
of a class), which will be stored in another variable that has function scope.
This behaviour is the same used in Java, where indeed there is no notion of passing arguments by reference. On the other hand,
in PHP you can pass a value by reference (in PHP we refer to references as "aliases"), and this poses a threat if you are not
aware of what you are really doing. Please consider these two classes:
<?php
class A
{
function __toString() {
return "Class A";
}
}

class B
{
function __toString() {
return "Class B";
}
}
?>
In the first test case we make two objects out of the classes A and B, then swap the variables using a temp one and the normal
assignment operator (=).
<?php
$a = new A();
$b = new B();

$temp = $a;
$a = $b;

$b = $temp;

print('$a: ' . $a . "\n");


print('$b: ' . $b . "\n");
?>
As expected the script will output:
$a: Class B
$b: Class A
Now consider the following snippet. It is similar to the former but the assignment $a = &$b makes $a an ALIAS of $b.
<?php
$a = new A();
$b = new B();

$temp = $a;
$a = &$b;
$b = $temp;

print('$a: ' . $a . "\n");


print('$b: ' . $b . "\n");
?>
This script will output:
$a: Class A
$b: Class A
That is, modifying $b reflects the same assignment on $a... The two variables end pointing to the same object, and the other
one is lost. To sum up is a good practice NOT using aliasing when handling PHP5 objects, unless your are really really sure of
what you are doing.

lazybones_senior 30-Sep-2008 06:57


WHOA... KEEP IT SIMPLE!
In regards to secure_admin's note: You've used OOP to simplify PHP's ability to create and use object references. Now use PHP's
static keyword to simplify your OOP.
<?php
class DataModelControl {
protected static $data = 256; // default value;
protected $name;
public function __construct($dmcName) {
$this->name = $dmcName;
}
public static function setData($dmcData) {
if(is_numeric($dmcData)) {
self::$data = $dmcData;
}
}
public function __toString() {
return "DataModelControl [name=$this->name, data=" . self::$data . "]";

}
}
# create several instances of DataModelControl...
$dmc1 = new DataModelControl('dmc1');
$dmc2 = new DataModelControl('dmc2');
$dmc3 = new DataModelControl('dmc3');
echo $dmc1 . '<br>';
echo $dmc2 . '<br>';
echo $dmc3 . '<br><br>';
# To change data, use any DataModelControl object...
$dmc2->setData(512);
# Or, call setData() directly from the class...
DataModelControl::setData(1024);
echo $dmc1 . '<br>';
echo $dmc2 . '<br>';
echo $dmc3 . '<br><br>';
?>
DataModelControl [name=dmc1, data=256]
DataModelControl [name=dmc2, data=256]
DataModelControl [name=dmc3, data=256]
DataModelControl [name=dmc1, data=1024]
DataModelControl [name=dmc2, data=1024]
DataModelControl [name=dmc3, data=1024]
... even better! Now, PHP creates one copy of $data, that is shared amongst all DataModelControl objects.

secure_admin 30-Sep-2008 04:38


USE OOP to ACCESS OBJECT REFERENCES
The PHP language itself offers a slew of nifty operators that can copy, clone, and alias objects and references in many ways.
But that kind of syntax looks rather fearsome. Here, I use OOP to get the same results, but with cleaner and more practical
code. Below, one DataModel object is instantiated so that many instances of DataControl can use and alter it. Regardless of how
PHP works, the OOP styled setup keeps all DataControl instances "on the same page" because they are all looking at the "same
model" - which this code clearly shows.
<?php
class DataModel {
protected $name, $data;
public function __construct($dmName, $dmData) {
$this->name = $dmName;
$this->setData($dmData);
}
public function setData($dmData) {
if(is_numeric($dmData)) {
$this->data = $dmData;
}
}
public function __toString() {
return "DataModel [name=$this->name, data=$this->data]";
}

}
class DataControl {
protected $name, $model;
public function __construct($dcName, $dcModel) {
$this->name = $dcName;
$this->model = $dcModel;
}
public function setData($dmData) {
$this->model->setData($dmData);
}
public function __toString() {
return "DataController [name=$this->name, model=" . $this->model->__toString() . "]";
}
}
# create one instance of DataModel...
$model = new DataModel('dm1', 128);
echo $model . '<br><br>';
# create several instances of DataControl, passing $model to each one...
$dc1 = new DataControl('dc1', $model);
$dc2 = new DataControl('dc2', $model);
$dc3 = new DataControl('dc3', $model);
echo $dc1 . '<br>';
echo $dc2 . '<br>';
echo $dc3 . '<br><br>';
# To change data, use any $dataControl->setData()...
$dc3->setData(512);
echo $dc1 . '<br>';
echo $dc2 . '<br>';
echo $dc3 . '<br><br>';
?>
* * * output * * *
DataModel [name=dm1, data=128]
DataController [name=dc1, model=DataModel [name=dm1, data=128]]
DataController [name=dc2, model=DataModel [name=dm1, data=128]]
DataController [name=dc3, model=DataModel [name=dm1, data=128]]
DataController [name=dc1, model=DataModel [name=dm1, data=512]]
DataController [name=dc2, model=DataModel [name=dm1, data=512]]
DataController [name=dc3, model=DataModel [name=dm1, data=512]]

wbcarts at juno dot com 30-Sep-2008 01:23


A BIT DILUTED... but it's alright!
In the PHP example above, the function foo($obj), will actually create a $foo property to "any object" passed to it - which
brings some confusion to me:
$obj = new stdClass();
foo($obj); // tags on a $foo property to the object
// why is this method here?

Furthermore, in OOP, it is not a good idea for "global functions" to operate on an object's properties... and it is not a good
idea for your class objects to let them. To illustrate the point, the example should be:
<?php
class A {
protected $foo = 1;
public function getFoo() {
return $this->foo;
}
public function setFoo($val) {
if($val > 0 && $val < 10) {
$this->foo = $val;
}
}
public function __toString() {
return "A [foo=$this->foo]";
}
}
$a = new A();
$b = $a; // $a and $b are copies of the same identifier
// ($a) = ($b) = <id>
$b->setFoo(2);
echo $a->getFoo() . '<br>';
$c = new A();
$d = &$c; // $c and $d are references
// ($c,$d) = <id>
$d->setFoo(2);
echo $c . '<br>';
$e = new A();
$e->setFoo(16); // will be ignored
echo $e;
?>
- - 2
A [foo=2]
A [foo=1]
- - Because the global function foo() has been deleted, class A is more defined, robust and will handle all foo operations... and
only for objects of type A. I can now take it for granted and see clearly that your are talking about "A" objects and their
references. But it still reminds me too much of cloning and object comparisons, which to me borders on machine-like programming
and not object-oriented programming, which is a totally different way to think.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

Object Serialization
Serializing objects - objects in sessions
serialize() returns a string containing a byte-stream representation of any value that can be stored in PHP.
unserialize() can use this string to recreate the original variable values. Using serialize to save an object will
save all variables in an object. The methods in an object will not be saved, only the name of the class.
In order to be able to unserialize() an object, the class of that object needs to be defined. That is, if you have
an object of class A and serialize this, you'll get a string that refers to class A and contains all values of
variables contained in it. If you want to be able to unserialize this in another file, an object of class A, the
definition of class A must be present in that file first. This can be done for example by storing the class
definition of class A in an include file and including this file or making use of the spl_autoload_register()
function.
<?php
//classa.inc:

classA{
public$one=1;

publicfunctionshow_one(){
echo$this->one;
}
}

//page1.php:
include("classa.inc");

$a=newA;
$s=serialize($a);
//store$ssomewherewherepage2.phpcanfindit.
file_put_contents('store',$s);
//page2.php:

//thisisneededfortheunserializetoworkproperly.
include("classa.inc");
$s=file_get_contents('store');
$a=unserialize($s);
//nowusethefunctionshow_one()ofthe$aobject.
$a->show_one();
?>

If an application is using sessions and uses session_register() to register objects, these objects are serialized
automatically at the end of each PHP page, and are unserialized automatically on each of the following pages.
This means that these objects can show up on any of the application's pages once they become part of the
session. However, the session_register() is removed since PHP 5.4.0.
It is strongly recommended that if an application serializes objects, for use later in the application, that the
application includes the class definition for that object throughout the application. Not doing so might result in
an object being unserialized without a class definition, which will result in PHP giving the object a class of
__PHP_Incomplete_Class_Name, which has no methods and would render the object useless.

So if in the example above $a became part of a session by running session_register("a"), you should include
the file classa.inc on all of your pages, not only page1.php and page2.php.

User Contributed Notes

Object Serialization

wbcarts at juno dot com 20-Dec-2009 12:39


PHP OBJECT SERIALIZATION
I use a database to store info rather than storing PHP Objects themselves. However, I find that having a PHP Object acting as
an interface to my db is way useful. For example, suppose I have a TABLE called 'user' that looks like this.
CREATE TABLE user {
user_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_first VARCHAR(24) NOT NULL,
user_last VARCHAR(24) NOT NULL,
PRIMARY KEY (user_id)
);
Then I would create a PHP Class definition like so:
<?php
require('includes/db_connect.php');
class User
{
protected $user_id;
protected $user_first;
protected $user_last;
public function __construct($id, $first, $last)
{
$this->user_id = $id;
$this->user_first = $first;
$this->user_last = $last;
}
# FUNCTIONS TO RETRIEVE INFO - DESERIALIZE.
public static function db_user_by_id($dbc, $id)
{
$query = "SELECT * FROM user WHERE user_id=$id LIMIT 1";
return User::db_select($dbc, $query);
}
public static function db_user_by_name($dbc, $first, $last)
{
$query = "SELECT * FROM user WHERE user_first='$first' AND user_last='$last' LIMIT 1";
return User::db_select($dbc, $query);
}
protected static function db_select($dbc, $query);
{
$result = mysqli_query($dbc, $query);
if(mysqli_num_rows($result) > 0)
{
$row = mysqli_fetch_array($result, MYSQLI_NUM);

return new User($row[0], $row[1], $row[2]);


}
}
# FUNCTIONS TO SAVE INFO - SERIALIZE.
public function insert($dbc)
{
$query = "INSERT INTO user VALUES (NULL, '$this->user_first', '$this->user_last')";
$result = mysqli_query($dbc, $query);
}
public function update($dbc)
{
$query = "UPDATE user SET user_first='$this->user_first', user_last='$this->user_last' WHERE user_id=$this->id LIMIT 1";
$result = mysqli_query($dbc, $query);
}
# GETTER and SETTER FUNCTIONS - DO NOT ALLOW SETTING OF ID
public function getId() {return $this->user_id;)
public function getFirst() {return $this->user_first;)
public function getLast() {return $this->user_last;)
public function setFirst($first) {$this->user_first = $first;}
public function setLast($last) {$this->user_last = $last;}
# CUSTOM FUNCTIONS
public function getFullName() {return $this->user_first . ' ' . $this->user_last;}
public function getLastFirst() {return $this->user_last . ', ' . $this->user_first;}
}
?>
Using PHP Objects for SERIALIZATION and DESERIALIZATION is now super-easy, for example:
<?php
require('User.php');
// INSERT a new user.
$user = new User(0, 'Frank', 'American');
$user->insert($dbc); // done!
// UPDATE an existing user.
$user = User::db_user_by_id($dbc, 223);
$user->setFirst('Johnny');
$user->update($dbc); // done!
mysqli_close($dbc);
?>

php at lanar dot com dot au 18-Oct-2009 04:47


Note that static members of an object are not serialized.

Copyright 2001-2012 The PHP Group


All rights reserved.

[edit] Last updated: Sat, 16 Jun 2012

OOP Changelog
Changes to the PHP 5 OOP model are logged here. Descriptions and other notes regarding these features are
documented within the OOP 5 documentation.
Version

Description

5.4.0

Changed: If an abstract class defines a signature for the constructor it will now be enforced.

5.3.3

Changed: Methods with the same name as the last element of a namespaced class name will no
longer be treated as constructor. This change doesn't affect non-namespaced classes.

5.3.0

Changed: Classes that implement interfaces with methods that have default values in the prototype
are no longer required to match the interface's default value.

5.3.0

Changed: It's now possible to reference the class using a variable (e.g., echo
$classname::constant;). The variable's value can not be a keyword (e.g., self, parent or static).

5.3.0

Changed: An E_WARNING level error is issued if the magic overloading methods are declared static. It
also enforces the public visibility requirement.

5.3.0

Changed: Prior to 5.3.0, exceptions thrown in the __autoload() function could not be caught in the
catch block, and would result in a fatal error. Exceptions now thrown in the __autoload function can
be caught in the catch block, with one proviso. If throwing a custom exception, then the custom
exception class must be available. The __autoload function may be used recursively to autoload the
custom exception class.

5.3.0

Added: The __callStatic method.

5.3.0

Added: heredoc and nowdoc support for class const and property definitions. Note: heredoc values
must follow the same rules as double-quoted strings, (e.g., no variables within).

5.3.0

Added: Late Static Bindings.

5.3.0

Added: The __invoke() method.

5.2.0

Changed: The __toString() method was only called when it was directly combined with echo or
print. But now, 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 a __toString
method to string emits a E_RECOVERABLE_ERROR level error.

5.1.3

Changed: In previous versions of PHP 5, the use of var was considered deprecated and would issue
an E_STRICT level error. It's no longer deprecated, therefore does not emit the error.

5.1.0

Changed: The __set_state() static method is now called for classes exported by var_export().

5.1.0

Added: The __isset() and __unset() methods.

User Contributed Notes

OOP Changelog

There are no user contributed notes for this page.

Copyright 2001-2012 The PHP Group


All rights reserved.

You might also like