Sunteți pe pagina 1din 45

Oops Consepts in php

How to Create a Class

Definition of a Class

A class is user defined data type that contains attributes or data members;
and methods which work on the data members. (You will learn more about
data members and methods in following tutorials. This tutorial focuses only on
learning how to create a Class in PHP5)
To create a class, you need to use the keyword class followed by the name of
the class. The name of the class should be meaningful to exist within the
system (See note on naming a class towards the end of the article). The body
of the class is placed between two curly brackets within which you declare
class data members/variables and class methods.
Following is a prototype of a PHP5 class structure
class <class-name> {

<class body :- Data Members &amp; Methods>;

On the basis of the above prototype, look below an example of PHP5 class
Example of a Class:
class Customer {
private $first_name, $last_name;

public function setData($first_name, $last_name) {


$this->first_name = $first_name;
$this->last_name = $last_name;
}

public function printData() {


echo $this->first_name . " : " . $this->last_name;
}
}

In the above program, Customer is the name of the class and


$first_name/$last_name are attributes or data members. setData()
and printData() are methods of a class. We will discuss more about
attributes and members in the upcoming articles on PHP5 OOPS
Tutorials series.

Note:
You can read more about private, public and protected in this tutorial on Access
Specifiers
Naming Conventions
Naming Convention for Class:
As a general Object Oriented Programming practice, it is better to name the
class as the name of the real world entity rather than giving it a fictitious name.
For example, to represent a customer in your OOAD model; you should name
the class as Customer instead of Person or something else.
Naming Conventions for Methods:
The same rule applies for class methods. The name of the method should tell
you what action or functionality it will perform. E.g. getData() tells you that it
will accept some data as input and printData() tells you that it will printData().
So ask yourself what you would name a method which stores data in the
database. If you said storeDataInDB() you were right.
Look at the manner in which the method storeDataInDB() has been named. The
first character of the first word of the method is lower case i.e. ‘s‘tore. For rest
of the words in the function viz Data/In/DB have been named as first character
Uppercase and the remaining characters of the words as lower case i.e. ‘D’ata
‘I’n ‘D’B. Therefore it becomes storeDataInDB()
Naming Convention for Attributes:
Attributes of a class should be named on the basis of the data that they hold.
You should always give meaningful names to your attributes. For attributes you
should split the words with an underscore (_) i.e. $first_name, $last_name, etc.

How to Create PHP Class Object

In the earlier PHP5 OOPS tutorial you learnt how to create a class in PHP5.
In this tutorial you will learn how to create an object of a PHP5 class. But
before we begin, lets understand what is an object.
Definition of an Object
An object is a living instance of a class. This means that an object is created
from the definition of the class and is loaded in memory. A good analogy to
understand this is to compare objects with humans - and understand that all of
us (you and I) are objects. If God wants to send a human to earth, what is easy
for Him to do? Create and define properties and attributes of each human
separately or create a one time template and generate objects out if it.
Therefore, this onetime template is a Class and you, I & everyone in this world
is an object - that is a living instance of class Human.
Creating Objects in PHP5 Class
To create an object of a PHP5 class we use the keyword new. Below is the
syntax style of how to create objects in PHP5:
$obj_name = new ClassName();

€In the above syntax style, $obj_name is a variable in PHP. ‘new’ is


the keyword which is responsible for creating a new instance of
ClassName.

Look at the example below:


class Customer {
private $first_name, $last_name;

public function getData($first_name, $last_name) {


$this->first_name = $first_name;
$this->last_name = $last_name;
}
public function printData() {
echo $this->first_name . " : " . $this->last_name;
}
}

$c1 = new Customer();


$c2 = new Customer();

In the above example $c1 and $c2 are two objects of the Customer
Class. Both these objects are allocated different blocks in the memory.
Look at the diagram below:

Therefore, an object is a living instance of a class. Each object / living instance


has its own memory space that can hold independent data values.
In the next tutorial you will learn about Attributes of a Class in PHP5.

Defining Attrubutes of a PHP5 Class:


Definition of an class attribute
An attribute is also know as data members and is used to hold data of a class.
The data that it holds are specific to the nature of the class in which it has been
defined. For example, a Customer class would hold data related to a customer,
an Order class would hold data related a an order.

Defining an attribute is as easy as declaring a variable within the body of the


class. At the time of declaring a data member/variable within the body of the
class, it is also possible to assign a default value to the attribute or data
member.
Attributes can either be public, private or protected - the default being
public. These are called Access Specifiers. You will learn more about access
specifiers in PHP5 OOPS tutorials ahead.
Example Code:
class Customer {
private $first_name, $last_name;
private $outstanding_amount = 0; //example of default value

public function getData($first_name, $last_name) {


$this->first_name = $first_name;
$this->last_name = $last_name;
}

public function printData() {


echo $this->first_name . " : " . $this->last_name;
}
}

$c1 = new Customer();

In the above example $first_name, $last_name and


$outstanding_amount are data members or attributes of the class
Customer. Of these attributes, $outstanding_amount has a default
value of zero assigned to it. This means that when an object of the
Customer class has been created, $first_name and $last_name will be
blank whereas; $outstanding_amount will be initialized with default
value of zero.

Let’s take a problem statement and define a PHP5 Class for it.
Problem Statement:
Define a class to encapsulate Student. The data required to be captured is
Student’s first name, last name, date of birth, address and telephone number.
Solution:
class Student {
public $first_name;
public $last_name;
public $date_of_birth;
public $address;
public $telephone;
}

In the above example $first_name, $last_name, $date_of_birth,


$address and $telephone are all data members of class Student.
These data members define the data that one Student Object will
store. Therefore, you can create two objects of a Student class having
different data as follows:

//creating an object $s1 of Student class and assigning data


$s1 = new Student();
$s1->first_name = "Sunil";
$s1->last_name = "Bhatia";
$s1->date_of_birth = "01/01/1900";
$s1->address = "India";
$s1->telephone = "9999999999";

//creating an object $s2 of Student class and assigning data


$s2 = new Student();
$s2->first_name = "Vishal";
$s2->last_name = "Thakur";
$s2->date_of_birth = "01/01/1910";
$s2->address = "USA";
$s2->telephone = "8888888888";
In the above example, we create two objects of the Student class $s1
and $s2. Both these objects have their own memory space within
which they store their respective data. Because each data member is
‘public‘ you can directly access the data members of the Student
Class using the arrow operator (reference operator) i.e. $s1-
>first_name = “Sunil”; You will learn more about public, private and
protected in the PHP5 tutorials ahead on Access Specifiers.

The diagram below explains the above example:

Objects as Attributes
In addition to declaring attributes as intrinsic data types (int, string, etc), you
can also declare data members as objects of another class. This is called
aggregation in Object Oriented Analysis and Design (OOAD). Lets look at an
example below:
class Customer {
private $first_name, $last_name;
private $outstanding_amount = 0; //example of default value

public function getData($first_name, $last_name) {


$this->first_name = $first_name;
$this->last_name = $last_name;
}

public function printData() {


echo $this->first_name . " : " . $this->last_name;
}
}

class Order {
private $order_id;
private $customer;

public setCust(Customer $c) {


$this->customer = $c;
}
}

$c1 = new Customer();


$o1 = new Order();

$o1->setCust($c1); //storing $c1 object in $o1 order object

In the above example setCust() method accepts a Customer type of


parameter which is stored internally in the $customer data member.
The advantage of the above method is that it allows you to change the
customer object independently of the order object. Imagine having to add 3 - 4
new data members to the Customer object. You only have to modify the
Customer object without having the need to modify the Order Object.
In the next tutorial you will learn about PHP5 Class Method.

Definition of an class method

A class method/functions is the behavior/functionality of a class i.e. they


provide the necessary code for the class in which it is defined. Examples could
be a saveCustomer() method in the class Customer or a printDocument() in the
Document class.
Methods act (perform operations) on the data members of the class and can be
declared as private or public. A class method is exactly similar to PHP
functions, it’s just that class functions are declared inside classes and accessed
using the -> (arrow operator / dereferencing operator).

Methods can also be declared as either public, protected or private.


Lets look at an example to understand PHP5 Class methods better:
Example Code:
class Customer {
private $name;
public functionsetName($name) {
$this->name = $name;
}
}

$c1 = new Customer();


$c1->setName("Sunil Bhatia");

In the above example setName() is the class method of the Customer


class. The setName() class method is responsible for accepting the
name of the customer and storing it in the internal data member i.e.
$name.

The reason why you require methods is so that you can perform necessary
validations on the data passed. Let’s re-look at the above example with
necessary validation code.
class Customer {
private $name;
public function setName($name) {
if(trim($name) != "") {
$this->name = $name;
return true;
}
else {
return false;
}
}
}

$c1 = new Customer();


$c1->setName("Sunil Bhatia");

In the above example the setName() method accepts a customer’s


name and validates to check if $name is blank. If $name is blank the
setName() function returns false; otherwise it stores the $name in the
$this->name of the class and returns true.

Notes on Accessor and Mutator methods


Although we will learn about Access Specifiers in the subsequent tutorials;
let’s try to understand the meaning and need for accessor and mutator
methods.

Accessor Methods:
Accessor methods are also know as getter methods. The reason why we need
an accessor method is to be able to read the value of a property/attribute in a
class object. In real OOAD practice most of the data members that you define
would either be private or protected (more on this will be covered in the tutorial
on Access specifiers), therefore to access data of such data members that have
been defined as either private or protected will require an implementation of
accessor or getter methods.
Note: To make a property or data member as non-read only; you
should not provide a getter or accessor method.

Mutator Methods:
Mutator methods are opposite to accessor methods. Mutator methods provides
a mechanism to store data in data members that have either been declared as
private or protected. The reason why you should provide a mutator method is
to provide necessary validation on the data that is to be stored in the data
member of the class.
Note: To make a property or data member as read only; you should
not provide a setter or mutator method.

Lets look at an example of accessor and mutator methods below:


class Customer {
private $name;

//mutator method
public function setName($name) {
if(trim($name) != "") {
$this->name = $name;
return true;
}
else {
return false;
}
}
//accessor method
public getName() {
return $this->name;
}
}

$c1 = new Customer();


$c1->setName("Sunil Bhatia");
echo $c1->getName();

Output:
Sunil Bhatia
In the above example the setName() method accepts a customer’s
name and validates to check if $name is blank. If $name is blank the
setName() function returns false; otherwise it stores the $name in the
$this->name of the class and returns true. The getName() returns the
name stored in the $name data member of the $c1 object.

In the next tutorial you will learn about PHP5 Constructor.

PHP Constructor and Distructor:

Definition of a Constructor
A constructor is a special function of a class that is automatically executed
whenever an object of a class gets instantiated.
What does this all mean?
Lets revisit that definition in more simple terms. A constructor is a special
function - this means that a constructor is a function; but its special. But, why is
it special? It’s special because it is automatically executed or called when an
object of a class is created.
Why do we need a Constructor?
It is needed as it provides an opportunity for doing necessary setup operations
like initializing class variables, opening database connections or socket
connections, etc. In simple terms, it is needed to setup the object before it can
be used.
PHP5 Constructor
In PHP5 a constructor is defined by implementing the __construct() method.
This naming style has been introduced in PHP5. In PHP4, the name of the
constructor was the same name as that of the class. So, for example if you had
a class Customer, you would have to implement a function Customer().
PHP5 to be backward complaint also supports the PHP4 rule. When an object is
created, PHP5 searches for __construct() first. If __construct() is not defined it
then searches for a method with the same that of the class. However, if you
define both; PHP5 will first search for __construct() method and execute it if
available, otherwise it will execute the same class name function.
Let’s look at how to define a PHP5 Constructor
class Customer {
public function __construct() {
//code
}
}

Let’s look at a real example:


class Customer {
private $first_name;
private $last_name;
private $outstanding_amount;

public function __construct() {


$first_name = "";
$last_name = "";
$outstanding_amount = 0;
}

public function setData($first_name, $last_name, $outstanding_amount) {


$this->first_name = $first_name;
$this->last_name = $last_name;
$this->outstanding_amount = $outstanding_amount;
}

public function printData() {


echo "Name : " . $first_name . " " . $this->last_name . "\n";
echo "Outstanding Amount : " . $this->outstanding_amount . "\n";
}

$c1 = new Customer();


$c1->setData("Sunil","Bhatia",0);

In the above example on line number 26, we create a new object of


the Customer class. the ‘new’ operator is responsible for creating the
Customer class. At this point PHP5 searches the Customer class to see
if a constructor has been defined. Therefore, it calls the constructor
method i.e. __construct() defined starting from line no 7. The
__construct() method sets the $first_name and $last_name to blank
and sets the $outstanding_amount to zero.

Parameterized Constructor or Argument Constructor


A parameterized or argument constructor is a constructor which accepts values
in the form of arguments in the constructor. Unlike other programming
languages where overloaded argument constructors is possible, in PHP5 you
cannot overload constructors.
Example:
class Customer {
private $first_name;
private $last_name;
private $outstanding_amount;

public function __construct($first_name, $last_name, $outstanding_amount) {


$this->setData($first_name, $last_name, $outstanding_amount);
}

public function setData($first_name, $last_name, $outstanding_amount) {


$this->first_name = $first_name;
$this->last_name = $last_name;
$this->outstanding_amount = $outstanding_amount;
}

public function printData() {


echo "Name : " . $first_name . " " . $this->last_name . "\n";
echo "Outstanding Amount : " . $this->outstanding_amount . "\n";
}

$c1 = new Customer("Sunil","Bhatia",0);

In the above example on line number 24, we create a new object $c1
and pass values “Sunil”, “Bhatia” and zero to the constructor defined
on line number starting 7. The constructor now takes 3 arguments
and stores them in the internal private variable $first_name,
$last_name and $outstanding_amount respectively.

In the next tutorial you will learn about PHP5 Destructor

Definition of a Destructor
A destructor is a special function of a class that is automatically executed
whenever an object of a class is destroyed.
What does this all mean?
Let’s revisit that definition in more simple terms. A destructor is a special
function - this means that a destructor is a function; but its special. But, why is
it special? It’s special because it is automatically executed or called when an
object of a class is destroyed. An object of a class is destroyed when
1. it goes out of scope,
2. when you specifically set it to null,
3. when you unset it or when the program execution is over.

Why do we need a Destructor?


It is needed as it provides an opportunity for doing necessary cleanup
operations like unsetting internal class objects, closing database connections or
socket connections, etc. In simple terms, it is needed to cleanup the object
before it is destroyed. You should also read more about Garbage Collection to
understand how clean up happens.
PHP5 Destructor
A PHP5 destructor is defined by implementing the __destruct() method. In PHP4
however, the concept of a destructor did not exist.
Important Note:
A destructor cannot take any arguments.

Let’s look at how to define a PHP5 Destructor


class Customer {
public function __destructor() {
//code
}
}
Let’s look at a real example:
1 class Customer {
2
3 private $first_name;
4 private $last_name;
5 private $outstanding_amount;
6
7 public function __construct() {
8 $first_name = "";
9 $last_name = "";
10 $outstanding_amount = 0;
11 }
12
13 public function setData($first_name, $last_name, $outstanding_amount) {
14 $this->first_name = $first_name;
15 $this->last_name = $last_name;
16 $this->outstanding_amount = $outstanding_amount;
17 }
18
19 public function printData() {
20 echo "Name : " . $first_name . " " . $last_name . "\n";
21 echo "Outstanding Amount : " . $outstanding_amount . "\n";
22 }
23
24 }
25
26 class Order {
27 private $order_id;
28 private $customer;
29
30 public function __construct($order_id, $customer) {
31 $this->order_id = $order_id;
32 $this->customer = $customer;
33 }
34
35 public function __destruct() {
36 unset($this->order_id);
37 unset($this->customer);
38 }
39 }
40
41 $order_id = "L0001";
42 $c1 = new Customer();
43 $c1->setData("Sunil","Bhatia",0);
44
45 $o = new Order($order_id, $c1);

In the above example on line number 45, we <a>create a new


object</a> of the Order class. The argument constructor of the Order
class takes two parameters i.e. $order_id and $customer object. After
the program completes its execution, the object goes out of scope
because the program stops execution after line 45 and hence the
destructor is automatically called.

In the next PHP5 tutorial you will learn about Access Specifier
PHP Class Access Specifier:

In the earlier tutorials we have witnessed keywords like public, private and
protected. These are nothing but access specifiers. So, lets understand what
access specifiers are.
Definition of Access Specifiers
Access specifiers specify the level of access that the outside world (i.e. other
class objects, external functions and global level code) have on the class
methods and class data members. Access specifiers can either be public,
private or protected.
Why do we need Access specifiers
Access specifiers are used as a key component of Encapsulation and Data
Hiding. By using either of the access specifiers mentioned above i.e. public,
private or protected you can hide or show the internals of your class to the
outside world.
Explanation of each access specifier
1. Private
2. Protected
3. Public

1. Private
A private access specifier is used to hide the data member or member function
to the outside world. This means that only the class that defines such data
member and member functions have access them. Look at the example below:
class Customer {
private $name;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}
}

$c = new Customer();
$c->setName("Sunil Bhatia");
echo $c->name; //error, $name cannot be accessed from outside the class
//$name can only be accessed from within the class

echo $c->getName(); //this works, as the methods of the class have access
//to the private data members or methods

In the above example, echo $c->name will give you an error as


$name in class Customer has been declared private and hence only
be accessed by its member functions internally. Therefore, the
following line echo $c->getName() will display the name.
2. Public
A public access specifier provides the least protection to the internal data
members and member functions. A public access specifier allows the outside
world to access/modify the data members directly unlike the private access
specifier. Look at the example below:
class Customer {
public $name;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}
}

$c = new Customer();
$c->setName("Sunil Bhatia");
echo $c->name; // this will work as it is public.
$c->name = "New Name" ; // this does not give an error.

In the above example, echo $c->name will work as it has been


declared as public and hence can be accessed by class member
functions and the rest of the script.

3. Protected
A protected access specifier is mainly used with inheritance. A data member or
member function declared as protected will be accessed by its class and its
base class but not from the outside world (i.e. rest of the script). We can also
say that a protected data member is public for the class that declares it and it’s
child class; but is private for the rest of the program (outside world). Look at
the example below:

class Customer {
protected $name;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}
}

class DiscountCustomer extends Customer {

private $discount;

public function setData($name, $discount) {


$this->name = $name; //this is storing $name to the Customer
//class $name variable. This works
// as it is a protected variable

$this->discount = $discount;
}
}
$dc = new DiscountCustomer();
$dc->setData("Sunil Bhatia",10);
echo $dc->name; // this does not work as $name is protected and hence
// only available in Customer and DiscountCustomer class

In the above example, echo $dc->name will not work work $name has
been defined as a protected variable and hence it is only available in
Customer and DiscountCustomer class.

You will learn more about inheritance later in this tutorial series. You should
revisit this tutorial and read more on the protected section again when you
understand inheritance better.
Important Note of Access Specifier in PHP5
In PHP5, access specifiers are public by default. This means that if you don’t
specify an access specifier for a data member or method then the default
‘public’ is applicable
----------------------------------------------------------------------------------
------------------------------
$this Variable Explained

$this variable is a pointer to the object making the function call. $this variable
is not avialable in static methods. We will learn more about static methods in
the next series of tutorials.
Example:
class Customer {

private $name;

public setName($name) {
$this->name = $name;
}

$c1 = new Customer();


$c2 = new Customer();

$c1->setName(“Sunil”);
$c2->setName(“Vishal”);

In the above example, $c1 and $c2 are two separate Customer
objects. Each object has its own memory to store names. But if you
see the function setName() is common. During run time, how can it
make a difference as to which memory location to use to store the
function values. Therefore, it uses the $this variable. As mentioned
earlier, $this variable is a pointer to the object making a function call.
Therefore when we execute $c1->setName(”Sunil”), $this in the
setName() function is a pointer or a reference to the $c1 variable.

Instance of operator explained:


PHP5 introduces a new operator by the name of instanceOf. instanceOf is used
to check if two objects passed as operands belong to the same class. This
check can also happen when an object is compared with a class name.
In PHP4 a similar functionality existed with a method is_a(), which has been
replaced by the instanceOf operator in PHP5.

Lets look at an example below:


class Person {
...
}

$p1 = new Person();


$p2 = new Person();

if($p1 instanceof $p2)


echo "True";
else
echo "False";

In the above example, we are comparing to check if $p1 and $p2


belong to the same class i.e. Person. In this case $p1 and $p2 both
belong to the same class Person and hence the output is True. Please
note that line number 8 can also be written as if($p2 instanceof $p1)
and will yield the same output.

You can also use instanceOf operator to compare an object with the name of
the class, look at the example below:
class Person {
...
}

$p1 = new Person();

if($p1 instanceof Person)


echo "True";
else
echo "False";

In the above example, on line number 7 $p1 object is being compared


to check if its a Person type of object. In this case $p1 is a Person type
of object and hence the output is True.

Behaviour of instanceOf operator in inheritance


class Customer extends Person {
...
}

$p1 = new Person();


$c1 = new Customer();

if($c1 instanceof $p1)


echo "True";
else
echo "False";
In the above example, on line number 8 $c1 child class object is being
compared with $p1 which is a parent class object. This is possible
because Customer class is a child of the Person Class, just that the
Customer class is a specialized form of the Person class and therefore
this becomes possible. However the reverse is not possible, we
cannot compare if($p1 instanceof $c1) and will result in an error.

Defining PHP5 Class constants:

In PHP4 the only constants that we would declare were global constants. In
PHP5 it is possible to define a class level constant. These constants are specific
to the class and hence don’t clutter the global level constant space.

To declare a constant in a class, PHP5 provides developers with a new keyword


i.e. const; look at the example below:
class Customer {
const TYPES = "Anything";
}

echo "Types are : " . Customer::TYPES;

In the above example, const is a keyword and TYPES is the name of


the constant. Outside the class definition we echo the value of the
constant by using the scope resolution operator (::) like this
Customer::TYPES. Observe that we don’t need to create an object of
the class to make use of the constant.

The next logical question is if we can create an object of the Customer class
and using the scope resolution operator access the constant. The answer is no;
reason - because a constant belongs to the class definition scope and not to an
object.
Example of accessing Constants within a function
class Customer {
const TYPES = "Anything";

public function showConstant() {


echo "Echo from showConstant() : " . Customer::TYPES;
}

$c = new Customer();
$c->showConstant();

Output:
Echo from showConstant() : Anything
Some observations on Constants
1. Variables defined as constants cannot be changed.
2. Only a string or numeric value can be assigned to a constant.
3. Arrays, Objects & Expressions cannot be assigned to a constant.
4. A class constant can only be accessed via the scope resolution operator
(::) executed on the class name.
5. A class constant cannot have <a>access specifiers</a> assigned to it
(private, public & protected)
Static data members and methods:

In this tutorial you will learn all about static data members and methods
• Meaning of static data members
• Meaning of static methods
• Defining static data members in PHP5
• Defining static methods in PHP5
• Accessing static data members in PHP5
• Accessing static methods in PHP5
• Rules to keep in mind for static methods

Meaning of static data members


A data member that is commonly available to all objects of a class is called a
static member. Unlike regular data members, static members share the
memory space between all objects of the same class.

Meaning of static methods


A static method is a class method that can be called without creating an
instance of a class. Such methods are useful when creating utility classes.

Defining static data members in PHP5


To define a static member in PHP5 you need to prefix the class member name
with the keyword ’static’. Look at the example below.

class Customer {

private $first_name; // regular member


static public $instance_count; //static data member

In the above example $instance_count is declared as a static data


member

Defining static methods in PHP5


To define a static data methods in PHP5 you need to prefix the class method
name with the keyword ’static’. Look at the example below.

class Customer {

public function getFirstName() {


//body of method
}

static public function getInstanceCount() {


//body of method
}
}

In the above example getInstanceCount is declared as a static


method

Accessing static data members in PHP5


A static member data can be accessed using the name of the class along with
the scope resolution operator (::) i.e. you don’t need to create an instance of
that class
Look at the example below:

class Customer {

static public $instance_count = 0; //static data member

public function __construct() {


Customer::$instance_count++;
}

public function __destruct() {


Customer::$instance_count--;
}

public function getFirstName() {


//body of method
}

static public function getInstanceCount() {


//body of method
}
}

$c1 = new Customer();


$c2 = new Customer();

echo Customer::$instance_count;

Output:
2
In the above example, $instance_count is a static data member. Every
time a new object is created the constructor is executed and the
$instance_count variable is incremented by one. To echo the value
contained in $instance_count variable, we use the :: (scope
resolution) operator.
Accessing static method in PHP5
A static method can be accessed using the name of the class along with the
scope resolution operator (::) i.e. you don’t need to create an instance of that
class. However, you can also access it with an instance variable.
Look at the example below:

class Customer {

static public $instance_count = 0; //static data member

public function __construct() {


Customer::$instance_count++;
}

public function __destruct() {


Customer::$instance_count--;
}

public function getFirstName() {


//body of method
}

static public function getInstanceCount() {


return Customer::$instance_count;
}
}

$c1 = new Customer();


$c2 = new Customer();

echo Customer::getInstanceCount(); //this is using the scope resolution operator


echo $c1->getInstanceCount(); //this is using the instance variable

Output:
2
2

Rules to keep in mind for static methods


• A static method can only access static data members
• A static method does not have access to the $this variable
Please feel free to write back for any clarification.

Final Class And Methods:

In this PHP tutorial we will understand the following:


• Meaning of Final Class
• Meaning of Final Method
• When to declare a class as final
• When to declare a method as final
Meaning of Final Class
A final class is a class that cannot be extended. To declare a class as final, you
need to prefix the ‘class’ keyword with ‘final’. Example below.

final class BaseClass {


public function myMethod() {
echo "BaseClass method called";
}
}

//this will cause Compile error


class DerivedClass extends BaseClass {
public function myMethod() {
echo "DerivedClass method called";
}
}

$c = new DerivedClass();
$c->myMethod();

In the above example, BaseClass is declared as final and hence


cannot be extended (inherited). DerivedClass tries to extend from
BaseClass and hence the compiler will throw a compile error.

Meaning of Final Method


A final method is a method that cannot be overridden. To declare a method as
final, you need to prefix the function name with the ‘final’ keyword. Example
below:

class BaseClass {
final public function myMethod() {
echo "BaseClass method called";
}
}

class DerivedClass extends BaseClass {


//this will cause Compile error
public function myMethod() {
echo "DerivedClass method called";
}
}

$c = new DerivedClass();
$c->myMethod();

In the above example, DerivedClass extends from BaseClass.


BaseClass has the method myMethod() declared as final and this
cannot be overridden. In this case the compiler causes a compile
error.
When to declare a class as final
You should declare a class as final when you think that you implementation of
that class should not change in the derived class. You should do this mainly for
Utility classes where you don’t want the behavior/implementation of your class
to change.

When to declare a method as final


You should declare a class method as final when you think that the method you
develop contains necessary functionality to support your application and any
modification or change to the functionality can cause unexpected errors/bugs.
Please feel free to write back for any clarification.
Subscribe to my free newsletter:

Handling Exception in PHP5:


In this tutorial we will cover the following:
• What is an exception?
• The use of a try…catch block
• Anatomy of PHP5 Exception class
• Extending the Exception class
• A note on unhanded exceptions

What is an exception?
An exception is a logical/system error that occurs during the normal execution
of a script. The exception could either be raised by the system or the program
itself it the exception cannot be handled and the caller script/function needs to
be informed about the same.

The use of a try…catch block


PHP5 introduces the try…catch block to trap exceptions. Look at the example
below.

try {
check();
}
catch(Exception $e) {
echo "Message : " . $e->getMessage();
echo "Code : " . $e->getCode();
}

function check() {
if(some error condition) {
throw new Exception("Error String",Error Code);
}
}

In the above example, the method check() is called between the try
{} block. The try{} block is the area where you will place your code
that could raise an exception. Below the try{} block is the catch() {}
block. The catch block expects the Exception type of object as a
parameter. Within the catch() {} block you will place your logic to
either fix the issue or log the error.

In the function check(), we raise an Exception using the ‘throw’


keyword. The statement following ‘throw’ is the syntax of creating a
new object of Exception type. The exception class accepts two
parameters. The left parameter is a string that is the error message
and the right parameter is the integer error code that you wish to
assign to that error.

Anatomy of PHP5 Exception class

class Exception {
protected $message;
protected $code;
protected $file;
protected $line;

private $string;
private $trace;

public function __construct($message = null, $code = 0);


public function __toString();

final public function getCode();


final public function getMessage();
final public function getFile();
final public function getLine();
final public function getTrace();
final public function getTraceAsString();
final private __clone();
}

In the above example, except for __construct and __toString(), no


other method can be overridden as all other methods are ‘final’.

Related Reading:

• PHP5 Tutorial - Creating a PHP5 Constructor __construct()


• PHP5 Tutorial - Defining Attributes of a PHP5 Class
• PHP5 Tutorial OOPS - PHP5 Class Access Specifiers - public,
private and protected
• PHP 5 Tutorial - Final Class and Methods
• PHP5 Tutorial - Magic Methods - __toString() method

Extending the Exception class


You can also extend the exception class as follows:

class CustomerException extends Exception {


public function __construct($message = null, $code = 0) {

$t_message = "Exception raised in CustomerException ";


$t_message .= "with message : " . $message;

parent::__construct($t_message, $code);

function testException() {

throw new CustomerException("CustomerException has been raised",101);

try {
testException();
}
catch(CustomerException $e) {
echo "Error Message : " $e->getMessage();
echo "Error Code : " $e->getCode();
}

Output:
Error Message : CustomerException has been raised
Error Code : 101

PHP5 Inheritance & Polymorphism

Inheritance:
In the tutorial we will understand what is Inheritance in general and how to
inherit classes in PHP5.
Definition of Inheritance:
Inheritance is the mechanism of deriving a new class from an existing class. It
allows a sub-class / child class to share/inherit the attributes and behaviors of a
base-class or parent class. These inherited attributes and behaviors are usually
modified by means of extension.

PHP5 Inheritance
To inherit in PHP5, you should use the keyword ‘extends’ in the class definition.
In PHP5 only single inheritance is allowed. Look at the example below:
class Person {
private $name;
private $address;

public function getName() {


return $this->name;
}
}
class Customer extends Person {
private $customer_id;
private $record_date;

public getCustomerId() {
return $this->customer_id;
}

public getCustomerName() {
return $this->getName();// getName() is in Person
}
}

In the above example, class Customer extends from the Person class.
This means that Customer class is the child class and the Person base
class. The child class Customer extends the method getName() and
calls it in the getCustomerName() method of the Customer class.

Inheritance and Access Specifiers


You can refer to the Access specifiers tutorial to understand what it means.
Let’s understand the use of Access Specifiers with context to Inheritance.
Access specifiers specify the level of access that the outside world (other
objects and functions) have on the data members / member functions of the
class. Please note that all data members and member functions are public by
default.
Lets look at how three access specifiers viz. private, public and protected
behave in Inheritance:
1. private
A private access specifier is used to hide data and member functions. A
method or data member declared as private can only be accessed by the class
itself and neither the outside program nor the derived class can have access to
it. Lets look at an example below:
class Customer {
private $name;
public $age;

public function __construct($name, $age) {


$this->name = $name;
$this->age = $age;
}
}

$c = new Customer("Sunil","28");
echo "Name : " . $c->name; //causes an error

In the above example, the statement;

echo “Name : ” . $c->name;

causes an error as we are trying to access $name that has been


declared as a private member variable. We can however access the
$age data member without any limitation as its public. We will learn
more about public later in this tutorial.
The reason why data members are declared private is to avoid the outside
programs to either accidently modify the values without necessary validation. If
you make a data member private you should provide accessor/mutator
methods to access. Read more about accessor/mutator methods here (You will
have to scroll a bit down and reach to “Notes on Accessor and Mutator
methods”)
Note: When you define a method as private that method can only be called
from within that class and not from outside that is the global level script.
2. public
A public access specifier allows the data members and methods to be access
from anywhere in the script. Lets look at an example below:
class Customer {
private $name;
public $age;

public function __construct($name, $age) {


$this->name = $name;
$this->age = $age;
}
}

$c = new Customer("Sunil","28");
echo "Age : " . $c->age; //prints 28

In the above example, the statement;

echo “Age : ” . $c->;age;

prints 28 on the screen as $age is a public variable and hence can be


accessed from anywhere in the script. Please note that if you declare
any data member or method without a access specifier it is
considered as ‘public’.

3. protected
A protected access specifier allows the derived class to access the data
member or member functions of the base class, whereas disallows global
access to other objects and functions.
class Person {
protected $name;
}

class Customer extends Person {


function setName($name) {
//this works as $name is protected in Person
$this->name = $name;
}
}

$c1 = new Customer();


$c1->setName("Sunil");
$c1->name = "Sunil"; //this causes error as $name is protected and not public

In the above example, the statement;


$this->name = $name;

in the setName() function is referring to the $name data member of


the Person class. This access is only possible because the $name
variable has been declared as protected. Had this been private; the
above statement would have raised an error. Further, in the
statement towards the end;

$c1->name = “Sunil”;

raises an error as $name in the Person class has been declared as


protected and not public.

PHP5 Inheritance - Method Overriding


Lets learn how to override methods in PHP5, but before we understand how to
override methods in PHP5; lets define method overriding.
Definition of Method Overriding:
Method overriding is when the function of base class is re-defined with the
same name, function signature and access specifier (either public or protected)
of the derived class.
The reason to override method is to provide additional functionality over and
above what has been defined in the base class. Imagine that you have a class
by the name of Bird from which you derive two child classes viz. Eagle and
Swift. The Bird class has methods defined to eat, fly, etc, but each of the
specialized classes viz Eagle and Swift will have its own style of flying and
hence would need to override the flying functionality.
Lets look at an example with Bird:
class Bird {
public function fly() {
echo "Fly method of Bird Class called";
}
}

class Eagle extends Bird {


public function fly() {
echo "Fly method of the Eagle Class called";
}
}

class Swift extends Bird {


public function fly() {
echo "Fly method of the Swift Class called";
}
}

$e = new Eagle();
$s = new Swift();

$e->fly();
echo "\n";
$s->fly();

Output:
Fly method of the Eagle Class called
Fly method of the Swift Class called
In the above example, we create two objects of class Eagle and Swift.
Each of these classes have overridden the method fly() and have
provided their own implementation of the fly() method that has been
extended from the Bird class. The manner in which they have been
extended the Bird class fly() method is not called as both these
classes have provided a new functionality for the fly() method.

Another example of function overriding in Inheritance


class Person {
function calculateAge($dob) {
echo "calculateAge called of Person Class\n";
}

class Customer extends Person {


function calculateAge($dob) {
echo "calculateAge called of Customer Class\n";
}
}

$c1 = new Customer();


$p1 = new Person();

$c1->calculateAge("something");
$p1->calculateAge("something More");

Output:
calculateAge called of Customer Class
calculateAge called of Person Class
PHP5 Inheritance - Invoking parent methods
When you override a method of the base class, it’s functionality is completely
hidden unless it has been explicitly invoked from the child class. To invoke a
parent class method you should use the keyword parent followed by the scope
resolution operator followed by the name of the method as mentioned below:
parent::function_name();

Look at the example below:


class Person {
public function showData() {
echo "This is Person's showData()\n";
}
}

class Customer extends Person{


public function showData() {
parent::showData();
echo "This is Customer's showData()\n";
}
}

$c = new Customer();
$c->showData();
Output:
This is Person’s showData()
This is Customer’s showData()
In the above example, look at the way in which the showData()
function in the Customer child class is invoking the the Person parent
class’s showData() function. When the program executes the
showData() method if the Customer class is called which inturn calls
the showData() function of the parent class. After the parent class’s
showData() function complets its execution the remaining code in
showData() function of the Customer class is executed.

PHP5 Inheritance - Invoking parent Constructor and Destructor


We can get the parent PHP5 constructor and PHP5 Destructor to be invoked in
the same way as invoking the parent method, refer to the example below:
class Person{
public function __construct() {
echo "This is Person's __construct()\n";
}

public function __destruct() {


echo "This is Person's __destruct()\n";
}
}

class Customer extends Person{


public function __construct() {
parent::__construct();
echo "This is Customer's __construct()\n";
}

public function __destruct() {


parent::__destruct();
echo "This is Customer's __destruct()\n";
}
}

$c = new Customer();

Output:
This is Person’s __construct()
This is Customer’s __construct()
This is Person’s __destruct()
This is Customer’s __destruct()

PHP Abstract Class And Interface:

In this post, we learn what is an abstract class and an interface.


• What is an Abstract Class?
• Private methods cannot be Abstract
• What is an Interface?
• Defining an Interface
• Abstract Class v/s Interface
What is an Abstract Class?
An abstract class is a class with or without data members that provides some
functionality and leaves the remaining functionality for its child class to
implement. The child class must provide the functionality not provided by the
abstract class or else the child class also becomes abstract.
Objects of an abstract and interface class cannot be created i.e. only objects of
concrete class can be created
To define a class as Abstract, the keyword abstract is to be used e.g. abstract
class ClassName { }
Example of Abstract Class

abstract class Furniture {


private $height, width, length;

public function setData($h, $w, $l) {


$this->height = $h;
$this->width = $w;
$this->length = $l;
}

//this function is declared as abstract and hence the function


//body will have to be provided in the child class
public abstract function getPrice();

class BookShelf extends Furniture {

private $price;

public setData($h, $w, $l, $p) {


parent::setData($h, $w, $l);
$this->price = $p;
}

//this is the function body of the parent abstract method


public function getPrice() {
return $this->price;
}
}

In the above example, the method getPrice() in class Furniture has


been declared as Abstract. This means that its the responsibility of
the child class to provide the functionality of getPrice(). The BookShelf
class is a child of the Furniture class and hence provides the function
body for getPrice().

Private methods cannot be abstract


If a method is defined as abstract then it cannot be declared as private (it can
only be public or protected). This is because a private method cannot be
inherited.
abstract class BaseClass {

private abstract function myFun();

class DerivedClass extends BaseClass {


public function myFun() {
//logic here
}
}

$d = new DerivedClass(); //will cause error

What is an Interface?
An interface is a contract between unrelated objects to perform a common
function. An interface enables you to specify that an object is capable of
performing a certain function, but it does not necessarily tell you how the
object does so, this means that it leaves for classes implementing an interface
to define its behaviour.
To extend from an Interface, keyword implements is used.
We can have a class extend from more than one Interface.

interface Storable {
function getContentsAsText();
}

class Document implements Storable {


public function getContentsAsText() {
return "This is Text of the Document\n";
}
}

class Indexer {
public function readAndIndex(Storable $s) {
$textData = $s->getContentsAsText();
//do necessary logic to index
echo $textData;
}
}

$p = new Document();

$i = new Indexer();
$i->readAndIndex($p);

In the above example, Document and the Indexer class are two
independant classes. The Indexer class is designed to index the
contents of any text. Using the Storable interface above, we declare a
method getContentsAsText() in the Document class. Because the
Indexer class is only concerned with the TEXT, hence we can call
getContentsAsText() method on the object of Document. This way any
class if it implements the method getContentsAsText() can get
indexed

Difference between Abstract Class and Interface


Abstract Classes
1. An abstract class can provide some functionality and leave the rest for
derived class
2. The derived class may or may not override the concrete functions defined
in base class
3. The child class extended from an abstract class should logically be
related
Interface
1. An interface cannot contain any functionality. It only contains definitions
of the methods
2. The derived class must provide code for all the methods defined in the
interface
3. Completely different and non-related classes can be logically be grouped
together using an interface
Subscribe below for article updates

Polymorphism:

In this tutorial we will learn the following:


• Meaning of Polymorphism
• Why method polymorphism cannot be achieved in PHP
• PHP 5 Object Polymorphism

Meaning of Polymorphism
Polymorphism is derived from two Greek words. Poly (meaning many) and
morph (meaning forms). Polymorphism means many forms. In C you have two
methods with the same name that have different function signatures and
hence by passing the correct function signature you can invoke the correct
method.
This is how polymorphism is achieved in languages like C where in a function
sum(int, int) differs from sum(float, float). Therefore the method sum() has
many forms depending on the parameters being passed to it.
The meaning with Object Oriented languages changes. With Object Oriented
language polymorphism happens:
When the decision to invoke a function call is made by inspecting the object at
runtime it is called Polymorphism
Why method polymorphism cannot be achieved
The reason why polymorphism for methods is not possible in PHP is because
you can have a method that accepts two parameters and call it by passing
three parameters. This is because PHP is not strict and contains methods like
func_num_args() and func_get_arg() to find the number of arguments passed
and get a particular parameter.
Because PHP is not type strict and allows variable arguments, this is why
method polymorphism is not possible.

PHP 5 Polymorphism
Since PHP 5 introduces the concept of Type Hinting, polymorphism is possible
with class methods. The basis of polymorphism is Inheritance and overridden
methods.
Lets look at an example:

class BaseClass {
public function myMethod() {
echo "BaseClass method called";
}
}

class DerivedClass extends BaseClass {


public function myMethod() {
echo "DerivedClass method called";
}
}

function processClass(BaseClass $c) {


$c->myMethod();
}

$c = new DerivedClass();
processClass($c);

In the above example, object $c of class DerievedClass is executed


and passed to the processClass() method. The parameter accepted in
processClass() is that of BassClass. Within the processClass() the
method myMethod() is being called. Since the method is being called
on the class variable of BaseClass, it would not be wrong to assume
that myMethod() of class BaseClass will be called. But, as per the
definition “When the decision to invoke a function call is made by
inspecting the object at runtime it is called Polymorphism”,
myMethod() will be called on object DerievedClass. The reason why
this happens is because the object of DerievedClass is being passed
and hence the method myMethod() of DerievedClass will be called.

Please feel free to write back for any clarification.


PHP 5 Magic Methods-_toString()
PHP5 provides a magic method by the name of __toString() (double underscore
followed by toString()) which is useful for debugging purposes.
The __toString() method is automatically called when an object in PHP5 is
converted into a string for the purpose of display or concatenation.

Following is the example of the __toString() method:


<?php

class Customer {
private $firstName, $lastName, $email;

public function __construct($firstName, $lastName, $email) {


$this->firstName = $firstName;
$this->lastName = $lastName;
$this->email = $email;
}

public function __toString() {


return “Debug message from Customer Class : First Name = ” . $this-
>firstName . “, Last Name = ” . $this->lastName . “, Email = ” . $this-
>email;
}
}

$c = new Customer(”Sunil”,”Bhatia”,”email@domain.com”);

echo “Customer Object is >>” . $c;

?>

Output:
Customer Object is >> Debug message from Customer Class : First
Name = Sunil, Last Name = Bhatia, Email = email@domain.com

See how in this example $c Customer Object got converted into a string type
when used with the dot (.) concatenation operator. In the background the
magic method __toString() is automatically called when such a conversion
happens.
Security Tip:
Be careful not to include sensitive data as part of the output as you could
compromise security by leaking secure information. Many applications are
written to write object states in a log file, therefore you should ensure that
sensitive information like Credit Card information, etc is not made available
through the magic method __toString()
Subscribe to my newsletter and be informed as a new PHP5 tutorial is posted
online:

PHP _get() and _set():

This article talks about the use of __get() (double underscore - get()) and
__set() (double underscore - set()) PHP5 OOPS magic methods.
By default PHP is a Loosely typed language and therefore it is not necessary to
declare variables before using them. This also holds true for using class
members. Look at an example below.
<?php

class Customer {
public $name;
}

$c = new Customer();
$c->name = “Sunil”; // $name is set because its public

$c->email = “email@domain.com”; //assigning email@domain.com to


the $email variable.

?>

Ideally in a strict language this would have been an error. But, with PHP this
works perfectly well as you can assign values to an undefined variable.
Because of the above limitation, PHP engine provides two magic methods
__get() and __set(). __get() is used when value from an undefined variable is
to be read and __set() is used when a value is to be assigned to a undefined
variable of a class.
__set() allows you to provide functionality to validate data being stored. See
example below:
<?php

class Customer {
public $name;
private $data = array();

public function __set($dt, $vl) {


$this->data[$dt] = $vl;
}

public function __get($dt) {


return $this->data[$dt];
}
}

$c = new Customer();
$c->name = “Sunil”; // $name is set because its public

$c->email = “email@domain.com”; //assigning email@domain.com to


the $email variable.

echo $c->email;
?>

In the above example when email@domain.com is assigned to the undefined


variable $email, the magic method __set() is called. To this __set() method the
name of the variable is passed into $dt variable of __set() method and the
value i.e. email@domain.com is passed to $vl variable of the __set() method.

The next step is to store these values into the $data array so that you could
retrieve it later.
The __get() method works in the similar fashion. When you echo $c->email,
__get() method is called and the name email is passed in the $dt of the __get()
method.
Tip:
It is possible to stop this behavior of PHP to assign values to undefined issues.
The solution is that you raise an exception from within __set() method. Look at
the code below:
<?

class Customer {

private $name;

public function __set($dt, $vl) {


throw new Exception(”Cannot assign values to undefined
variables”,1);
}

$c = new Customer();
$c->email = “email@domain.com”; //this will cause an exception to
be raised

?>

_isset() and _unset():

In my previous PHP5 OOPS tutorial on PHP5 Tutorial - Magic Methods -


__get() and __set(), we learnt how and when to use these magic methods.
This PHP5 OOPS tutorial will teach you how and when to use the magic
methods __isset() and __unset().

These methods are automatically called internally when isset() and unset() is
called on undeclared data members. The magic method __isset() method
receives an argument - the value of which is the name of the variable that the
program wants to test if the variable is set or not.
The magic method __unset() method receives an argument - the value of
which is the name of the variable that the program wants to unset.
Look at the example below:
class Customer {
private $data = array();

public function __set($dt, $vl) {


$this->data[$dt] = $vl;
}

public function __get($dt) {


return $this->data[$dt];
}

public function __isset($dt) {


return isset($this->data[$dt]);
}

public function __unset($dt) {


return unset($this->data[dt]);
}
}

$c = new Customer();
$c->name = “Sunil Bhatia”;

echo isset($c->name).”\n”;
echo unset($c->name);

In the example above the script creates a new Customer Object. The
program assigns a string value to an undeclared variable i.e. $c-
>name. The undeclared variable is handled by the magic method
__set(). Read this post on PHP5 Magic Methods __set() if you need
more understanding how the magic method __set() works.

The program ties to check if the undeclared variable i.e., $c->name


has been set or not using the PHP method isset(). Since $c->name is
an undeclared variable the PHP5 magic method __isset() is invoked
that takes the name of the undeclared variable i.e. ‘name’ and checks
if the internal array $data[’name’] is set or not.

Similarly, when the program calls unset() on the undeclared variable i.e. $c-
>name, the PHP5 magic method __unset() is invoked that takes the name of
the undeclared variable i.e. ‘name’ and unsets the internal array
$data[’name’].

_call() Method:

This tutorial will teach you how and when to use the magic method __call().
The magic method __call() is to undeclared methods what __get() and __set()
are to undeclared data member.
These methods are automatically called internally when the program tires to
execute a method that has not been defined within the class at the time of
development.
The magic method __call() takes two arguments. The first argument is the
name of the undeclared method invoked by the program and the second is an
array that contains a list of parameters passed to the undeclared array.

Look at the example below:


class Customer {

public function __call($name, $args) {


var_dump($name);
echo "\n";
var_dump($args);
echo "\n";
}
}

$c = new Customer();
$c->setName("Sunil","Bhatia");

Output:
string(7) “setName”
array(2) {
[0]=>
string(5) “Sunil”
[1]=>
string(6) “Bhatia”
}

In the example above, an object of the Customer class is created and


an undeclared method viz. $c->setName is called. The magic method
__call() is internally executed which accepts two parameters. The first
parameter ‘$name’ contains the name of the method i.e. ’setName’
and the second parameter ‘$args’ contains the arguments passed to
the ’setName’ method i.e ‘Sunil’ & ‘Bhatia’.

Using this method, you can provide code to handle calls to undeclared method.
To disallow programs to call an undeclared method, you should raise an
exception from within __call() magic method.
Look at the example below:
class Customer {

public function __call($name, $args) {


throw new Exception("Undeclared method execution not allowed",10);
}
}

$c = new Customer();
$c->setName("Sunil","Bhatia");
Output:
Fatal error: Uncaught exception ‘Exception’ with message ‘Undeclared method
execution not allowed’ in D:sunilbwebsiteprogsmagic_call.php:6
Stack trace:
#0 [internal function]: Customer->__call(’setName’, Array)
#1 D:sunilbwebsiteprogsmagic_call.php(11): Customer->setName(’Sunil’,
‘Bhatia’)
#2 {main}
thrown in D:sunilbwebsiteprogsmagic_call.php on line 6
In the above program, when the script calls an undeclared variable $c-
>setName(), the magic method __call() is executed. On executing the magic
method __call(), an exception is raised and the execution of the program
stops there (unless we use the try..catch statements)

_autoload():

This tutorial will teach you how and when to use the magic method
__autoload().
The magic method __autoload() function is a convenience that allows you to
use classes without having to explicitly write code to include them.
The magic method __autoload() is not included in your class definition as this
is to be called once in a script. The best place to put the autoload() file is in
your configuration file which is loaded in all your other scripts.

Many people debate that the magic method __autoload() causes a


performance overhead. Well, that is not the case. There is no performance
penalty to pay. In fact, there may be performance improvements if not all
classes are used all the time. This is explained below.
Using the magic method __autoload has the beneficial side effect of requiring
strict naming conventions for files that hold class definitions.
Look at the example below:
include “customer.php”;
include “orders.php”;

$c = new Customer();

In the example displayed above, an instance of class Customer is


created. Therefore, we only need the customers.php file. The file
orders.php is not needed. This means that we should only have
included the customer.php file. But, what if during execution on the
basis of a condition, an instance of class Orders would have to be
created. Therefore you need to include both the files i.e.
customer.php and orders.php

But this causes performance issues. Each time the above script is executed,
orders.php is included. To avoid this performance hit, we would have to do
additional programming to ensure that the file orders.php is loaded only when
needed.
This is the reason why magic method __autoload() should be used. Look at
the example below:
function __autoload($class) {
require $class . '.php'; //is substituted as require Customer.php (with capital 'C')
}

$c = new Customer();

In the above program, we don’t explicitly include customer.php and


orders.php file. When an instance of the customer class is to be
created, the PHP engine checks to see if the file Customer.php is
loaded. It does not raise an warning on finding that Customer.php has
not been loaded, it in turn calls the magic method __autoload(). The
__autoload() magic method accepts a parameter which is the name of
the class that needs to be loaded.

Therefore, on the line when an instance of the customer class is created i.e.
object $c, magic method __autoload() is called with the parameter $class
containing value ‘Customer’. Within the __autoload() method we call the
‘require’ method. The require method tries to load $class.’php’ file i.e.
Customer.php. Therefore, as stated earlier, the __autoload() method has its
beneficial side effect of requiring strict file naming convention.
The __autoload() method is called only once for each new class that needs to
be loaded. Subsequent instantiation of the Customer class object will not call
the __autoload() method again. Therefore, this offers performance
improvements in your scripts because, unless the class is needed - files are not
loaded. Therefore, the PHP engine does not have to parse and compile an
unnecessary file.
Please feel free to leave behind any comments or questions that you might
have.
_sleep() and _wakeup()
The magic method __sleep() and __wakeup() is called when an object is
serialized. The magic method __sleep() and __wakeup() provides a method to
clean up and restore objects before being serialized.
Working with the magic method __sleep()
__sleep() magic method is called when the object of a class is about to be
serialized. This magic method __sleep() does not accept any parameter and
returns an array. The array should contain a list of class members that should
be serialized. This means that if you don’t wish to serialize a particular class
member, you should not include it in the array. Look at the example below:

class Customer {
private $name;
private $credit_card_number;
public function setName($name) {
$this->name = $name;
}

public function getName() {


return $this->name;
}

public function setCC($cc) {


$this->credit_card_number = $cc;
}

public function getCC() {


return $this->credit_card_number;
}

public function __sleep() {


return array("name"); //because of this, only name is serialized
}

$c = new Customer();
$c->setName("Sunil");
$c->setCC("1234567890123456");

$data = serialize($c)."\n";
echo $data."\n";

Output:
O:8:”Customer”:1:{s:14:” Customer name”;s:5:”Sunil”;}
In the above example, you can see that the serialized string data only
contains the name of the Customer Object. This is because the
__sleep() magic method returned an array containing only the
‘name’ data member.

Working with the magic method __wakeup()


__wakeup() magic method is the opposite of the __sleep() method. It is called
when the object of a class is about to be unserialized. This magic method
__wakeup() does not accept any parameter nor returns anything. The
__wakeup() method is responsible for setup operations after an object has been
unserialized. Look at the example below:
class Customer {
private $name;
private $credit_card_number;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}

public function setCC($cc) {


$this->credit_card_number = $cc;
}

public function getCC() {


return $this->credit_card_number;
}

public function __sleep() {


return array("name");
}

public function __wakeup() {


if($this->name == "Sunil") {
//you would ideally fetch CC data from Database
$this->credit_card_number = "1234567890123456";
}
}
}

$c = new Customer();
$c->setName("Sunil");
$c->setCC("1234567890123456");

$data = serialize($c)."\n";
var_dump(unserialize($data));

Output:
object(Customer)#2 (2) {
[”name:private”]=>
string(5) “Sunil”
[”credit_card_number:private”]=>
string(16) “1234567890123456″
}
In the above example, you can see that after the $c object has been
serialized and the output stored in $data variable, we use the $data
variable and pass it to the unserialize(). Before the object is
unserizlied and object created, the __wakeup() method is called. In
the __wakeup() method you should ideally make a database call to
fetch data of the missing member variable.

Please feel free to leave behind any comments or questions that you might
have.

_clone method():

Before I begin to explain the use of a __clone() method, lets try and understand
what does object cloning mean.
To clone an object means to create a duplicate of an object. With regular
variables $a = $b means that a new variable $a gets created that contains the
value of $b. This means that 2 variables get created.
With objects $obj2 = $obj1 does not mean that a new object i.e. $obj2 gets
created. When we execute $obj2 = $obj1, the reference of $obj1 is assigned to
$obj2. This means that $obj1 and $obj2 point to the same memory space. Look
at the diagram below.
Lets look at an example where only references are assigned to another object:
class Customer {
private $name;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}
}

$c1 = new Customer();


$c1->setName("Sunil");

$c2 = $c1; //only reference or memory assigned to $c2

$c2->setName("Vishal");

echo $c1->getName()."\n";
echo $c2->getName()."\n";

Output:
Vishal
Vishal
In the above example, $c2 has the reference of $c1; therefore, when
you set a new name in the $c2 object - $c1 object changes as well.
Therefore, when an object is assigned as a reference; changes made
to one object are also reflected in the other.

Therefore, to create a new $obj2 object we must clone an object to create a


new one. To clone an PHP5 Object a special keyword i.e. clone is used.
Example below:
$obj2 = clone $obj1;

After the above line is executed $obj2 with a new memory space is created
with the data members having the same value as that of $obj1. This is also
referred to as shallow copy.

The above technique works with a class having data members that
are of intrinsic type i.e. int, boolean, string, float, etc.. However, this
technique will not work with a class that has a data member which is
an object of another class. In such a scenario, the cloned object
continues to share the reference of the data member object of the
class that was cloned.

So, how do we resolve this issue? Doing a regular shallow copy won’t help us.
To allow aggregated objects (i.e. data members that are objects of another
class) to also get cloned properly we need to use the concept of ‘deep copy‘
as opposed to ‘shallow copy‘. To implement a ‘deep copy‘ you should
implement the magic method __clone().
You could also provide the implementation of __clone() magic method even
when you don’t have an aggregated object. You would want to do this for
providing necessary clean up operations, conversions or validations.
Lets explore a very simple example of cloning intrinsic data types:
class Customer {
private $name;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}

public function __clone() {


$c = new Customer();
$c->setName($this->name);
return $c;
}

$c1 = new Customer();


$c1->setName("Sunil");

$c2 = clone $c1; //new object $c2 created

$c2->setName("Vishal");

echo $c1->getName()."\n";
echo $c2->getName()."\n";

Output:
Sunil
Vishal
In the above example, observe the line where the statement $c2 =
clone $c1 is executed. This is internally represented as $c2 =
$c1.__clone(). However, you cannot explicitly call the __clone()
method on an object as the __clone() is automatically called. Now that
$c1 and $c2 are two individual objects, changes made to one object is
not reflected in the other.
Cloning aggregate objects (i.e. data members that are objects of
another class)
To clone a class having aggregated objects, you should perform ‘deep copy‘.
Please refer to the example below:
class Order {
private $order_id;
private $customer;

public function setOrderId($order_id) {


$this->order_id = $order_id;
}

public function getOrderId() {


return $this->order_id;
}

public function setCustomer(Customer $customer) {


$this->customer = clone $customer;
}

public function getCustomer() {


return $this->customer;
}

public function __clone() {

$o = new Order();
$o->setOrderId($this->order_id);

//force a copy of the same object to itself, otherwise


//it takes the same instance. Seems like a bug to me
$this->customer = clone $this->customer;
$o->setCustomer($this->customer);
return $o;
}

class Customer {
private $name;

public function setName($name) {


$this->name = $name;
}

public function getName() {


return $this->name;
}

public function __clone() {


$c = new Customer();
$c->setName($this->name);
return $c;
}

$c = new Customer();
$c->setName("Sunil");
$o1 = new Order();
$o1->setOrderId("OD0001");
$o1->setCustomer($c);

$o2 = clone $o1;

$o2->getCustomer()->setName("Vishal");

var_dump($c);
var_dump($o1);
var_dump($o2);

Output:
object(Customer)#1 (1) {
[”name:private”]=>
string(5) “Sunil”
}
object(Order)#2 (2) {
[”order_id:private”]=>
string(6) “OD0001″
[”customer:private”]=>
object(Customer)#3 (1) {
[”name:private”]=>
string(5) “Sunil”
}
}
object(Order)#4 (2) {
[”order_id:private”]=>
string(6) “OD0001″
[”customer:private”]=>
object(Customer)#6 (1) {
[”name:private”]=>
string(6) “Vishal”
}
}
In the above example both $o1 and $o2 have their own set of
customer objects, therefore changes made to one object is not
reflected in another. This example implements the concepts of ‘deep
copy‘.

A special note on $this->customer = clone $this->customer; For some


reason it is necessary to do this for proper working of aggregated
cloning.

I hope this tutorial was helpful. Please feel free to leave behind any comments
or questions that you might have.

S-ar putea să vă placă și