OOPS Concepts in PHP
OOPS Concepts in PHP
OOPS Concepts in PHP
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
// method declaration
public function displayVar() {
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).
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this is not defined.\n";
}
}
}
class B
{
function bar()
{
// Note: the next line will issue a warning if E_STRICT is en
abled.
A::foo();
}
}
$a = new A();
$a->foo();
New
To create an instance of a class, a new object must be created and assigned to a variable. An object will
always be assigned when creating a new object unless the object has a constructor defined that throws
an exception on error. Classes should be defined before instantiation (and in some cases this is a
requirement).
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.
<?php
$assigned = $instance;
$reference =& $instance;
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
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::
<?php
class ExtendClass extends SimpleClass
{
// Redefine the parent method
function displayVar()
{
echo "Extending class\n";
parent::displayVar();
}
}
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).
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.
Its 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 := const constant = 'constant value';
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
$classname = "MyClass";
echo $classname::constant . "\n"; // As of PHP 5.3.0
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().
?php
function __autoload($class_name) {
require_once $class_name . '.php';
}
<?php
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will
search for the old-style constructor function, by the name of the class. Effectively, it means that the
only case that would have compatibility issues is if the class had a method named __construct() which
was used for different semantics.
Destructor
void __destruct ( void )
PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++.
The destructor method will be called as soon as all references to a particular object are removed or
when the object is explicitly destroyed or in any order in shutdown sequence.
<?php
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "Destroying " . $this->name . "\n";
}
}
Like constructors, parent destructors will not be called implicitly by the engine. In order to run a parent
destructor, one would have to explicitly call parent::__destruct() in the destructor body.
Note: Destructors called during the script shutdown have HTTP headers already sent. The
working directory in the script shutdown phase can be different with some SAPIs (e.g.
Apache).
Note: Attempting to throw an exception from a destructor (called in the time of script
termination) causes a fatal error.
Visibility
The visibility of a property or method can be defined by prefixing the declaration with the keywords
public, protected or private. 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 without an
explicit visibility keyword, the property will be defined as public.
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.
<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not
private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
?>
Method Visibility
Class methods may be defined as public, private, or protected. Methods declared without any
explicit visibility keyword are defined as public.
<?php
/**
* Define MyClass
*/
class MyClass
{
// Declare a public constructor
public function __construct() { }
// This is public
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// This is public
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // Fatal Error
}
}
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
class foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
?>
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!
<?php
class MyClass {
const CONST_VALUE = 'A constant value';
}
$classname = 'MyClass';
echo $classname::CONST_VALUE; // As of PHP 5.3.0
echo MyClass::CONST_VALUE;
?>
<?php
class OtherClass extends MyClass
{
public static $my_static = 'static var';
$classname = 'OtherClass';
echo $classname::doubleColon(); // As of PHP 5.3.0
OtherClass::doubleColon();
?>
When an extending class overrides the parents definition of a method, PHP will not call the parent's
method. It's up to the extended class on whether or not the parent's method is called. This also applies
to Constructors and Destructors, Overloading, and Magic method definitions.
Static Keyword
Declaring class 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).
<?php
class Foo
{
public static $my_static = 'foo';
PHP 5 introduces abstract classes and methods. It is not allowed to create an instance of a class that has
been defined as abstract. Any class that contains at least one abstract method must also be abstract.
Methods defined as abstract simply declare the method's signature they cannot define the
implementation.
When inheriting from an abstract class, all methods marked abstract in the parent's class declaration
must be defined by the child; additionally, these methods must be defined with the same (or a less
restricted) visibility. For example, if the abstract method is defined as protected, the function
implementation must be defined as either protected or public, but not private.
<?php
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Common method
public function printOut() {
print $this->getValue() . "\n";
}
}
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 extend 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
Its possible for interfaces to have constants. Interface constants works exactly like class constants. They
cannot be overridden by a class/interface that inherits it.
Examples
<?php
interface a
{
public function foo();
}
interface b extends a
{
public function baz(Baz $baz);
}
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
void __set ( string $name , mixed $value )
mixed __get ( string $name )
bool __isset ( string $name )
void __unset ( string $name )
__set() is run when writing data to inaccessible 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 can not be 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 assignemnts together
like this:
$a = $obj->b = 8;
<?php
class PropertyTest {
/** Location for overloaded data. */
private $data = array();
/** Overloading only used on this when accessed outside the clas
s. */
private $hidden = 2;
$trace = debug_backtrace();
trigger_error(
'Undefined property via __get(): ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
echo "<pre>\n";
$obj = new PropertyTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
function iterateVisible() {
echo "MyClass::iterateVisible:\n";
foreach($this as $key => $value) {
print "$key => $value\n";
}
}
}
$class->iterateVisible();
?>
Patterns
Patterns are ways to describe best practices and good designs. They show a flexible solution to
common programming problems.
Factory
The Factory pattern allows for the instantiation of objects at runtime. It is called a Factory Pattern since
it is responsible for "manufacturing" an object. A Parameterized Factory receives the name of the class
to instantiate as argument.
<?php
class Example
{
// The parameterized factory method
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception ('Driver not found');
}
}
}
?>
Singleton
The Singleton pattern applies to situations in which there needs to be a single instance of a class. The
most common example of this is a database connection. Implementing this pattern allows a
programmer to make this single instance easily accessible by many other objects.
<?php
class Example
{
// Hold an instance of the class
private static $instance;
return self::$instance;
}
// Example method
public function bark()
{
echo 'Woof!';
}
?>
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.
__invoke
The __invoke method is called when a script tries to call an object as a function.
__set_state
This static method is called for classes exported by var_export() since PHP 5.1.0.
The only parameter of this method is an array containing exported properties in the form
array('property' => value, ...).
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.
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
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.
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.
<?php
class SubObject
{
static $instances = 0;
public $instance;
class MyCloneable
{
public $object1;
public $object2;
function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone $this->object1;
}
}
print("Original Object:\n");
print_r($obj);
print("Cloned Object:\n");
print_r($obj2);
?>
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.
<?php
function bool2str($bool)
{
if ($bool === false) {
return 'FALSE';
} else {
return 'TRUE';
}
}
class Flag
{
public $flag;
class OtherFlag
{
public $flag;
$o = new Flag();
$p = new Flag();
$q = $o;
$r = new OtherFlag();
/**
* Another test function
*
* First parameter must be an array
*/
public function test_array(array $input_array) {
print_r($input_array);
}
}
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:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
B::test();
?>
Edge cases
There are lots of different ways to trigger a method call in PHP, like callbacks or magic methods. As
late static bindings base their resolution on runtime information, it might give unexpected results in so-
called edge cases.
<?php
class A {
class B extends A {
$b = new B;
$b->foo;
?>
Objects and references
One of the key-points of PHP5 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
PHP5, 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.
<?php
class A {
public $foo = 1;
}
$a = new A;
$b = $a; // $a and $b are copies of the same identifier
// ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";
$c = new A;
$d = &$c; // $c and $d are references
// ($c,$d) = <id>
$d->foo = 2;
echo $c->foo."\n";
$e = new A;
function foo($obj) {
// ($obj) = ($e) = <id>
$obj->foo = 2;
}
foo($e);
echo $e->foo."\n";
?>
Object Serialization
class A {
public $one = 1;
// page1.php:
include("classa.inc");
$a = new A;
$s = serialize($a);
// store $s somewhere where page2.php can find it.
file_put_contents('store', $s);
// page2.php:
$s = file_get_contents('store');
$a = unserialize($s);