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

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.

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

Attributes can either be public, private or protected - the default being public. These are called Access Specifiers.

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();

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.

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: Example:
class Customer { private $name; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } }

Public A public access specifier provides the least protection to the internal data members and member functions. 2. // this will work as it is public. A public access specifier allows the outside world to access/modify the data members directly unlike the private access specifier. } } $c = new Customer(). We can also say that a protected data member is public for the class . Look at the example below: Example: class Customer { public $name. $c->setName("Sunil Bhatia"). echo $c->name. $name cannot be accessed from outside the class //$name can only be accessed from within the class echo $c->getName(). //this works. //error. $c->name = "New Name" . $c->setName("Sunil Bhatia"). public function setName($name) { $this->name = $name. echo $c->name. Therefore.e. as the methods of the class have access //to the private data members or methods In the above example. 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. Protected A protected access specifier is mainly used with inheritance. the following line echo $c->getName() will display the name. // this does not give an error. 3. 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. rest of the script). 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.$c = new Customer(). } public function getName() { return $this->name. In the above example.

echo $dc->name. Look at the example below: class Customer { protected $name.10). This means that if you don’t specify an access specifier for a data member or method then the default ‘public’ is applicable Definition of an class method A class method/functions is the behavior/functionality of a class i.e. } } class DiscountCustomer extends Customer { private $discount. access specifiers are public by default. they provide the necessary code for the class in which it is defined. } public function getName() { return $this->name. public function setData($name. } } $dc = new DiscountCustomer(). //this is storing $name to the Customer //class $name variable. $dc->setData("Sunil Bhatia". but is private for the rest of the program (outside world).that declares it and it’s child class. Examples could be a saveCustomer() method in the class Customer or a printDocument() in the Document class. Important Note of Access Specifier in PHP5 In PHP5. $discount) { $this->name = $name. public function setName($name) { $this->name = $name. // this does not work as $name is protected and hence // only available in Customer and DiscountCustomer class In the above example. . This works // as it is a protected variable $this->discount = $discount. 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.

In the above example the setName() method accepts a customer’s name and validates to check if $name is blank. . public function setName($name) { if(trim($name) != "") { $this->name = $name. Example Code: class Customer { private $name.e. return true. $name. public functionsetName($name) { $this->name = $name. In the above example setName() is the class method of the Customer class. $c1->setName("Sunil Bhatia"). The setName() class method is responsible for accepting the name of the customer and storing it in the internal data member i. Methods can also be declared as either public. If $name is blank the setName() function returns false. protected or private.Methods act (perform operations) on the data members of the class and can be declared as private or public. } else { return false. it’s just that class functions are declared inside classes and accessed using the -> (arrow operator / dereferencing operator). $c1->setName("Sunil Bhatia"). A class method is exactly similar to PHP functions. } } } $c1 = new Customer(). } } $c1 = new Customer(). class Customer { private $name. otherwise it stores the $name in the $this->name of the class and returns true.

the name of the constructor was the same name as that of the class. opening database connections or socket connections. If __construct() is not defined it then searches for a method with the same that of the class. } . if you define both. PHP5 to be backward complaint also supports the PHP4 rule.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. This naming style has been introduced in PHP5. public function __construct() { $first_name = "". It’s special because it is automatically executed or called when an object of a class is created. otherwise it will execute the same class name function. $outstanding_amount = 0. it is needed to setup the object before it can be used. In PHP4. When an object is created. class Customer { public function __construct() { //code } } Example class Customer { private $first_name. $last_name = "". etc. private $last_name. PHP5 will first search for __construct() method and execute it if available. private $outstanding_amount. In PHP5 a constructor is defined by implementing the __construct() method. However. In simple terms. PHP5 searches for __construct() first. Why do we need a Constructor? It is needed as it provides an opportunity for doing necessary setup operations like initializing class variables.

$c1->setData("Sunil". $this->outstanding_amount = $outstanding_amount. Therefore. $last_name. } 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. $this->outstanding_amount . public function __construct($first_name. in PHP5 you cannot overload constructors. private $outstanding_amount. The __construct() method sets the $first_name and $last_name to blank and sets the $outstanding_amount to zero. $first_name .0)."Bhatia". } { public function setData($first_name. $last_name. } public function printData() { . " " . } $c1 = new Customer(). $last_name. $last_name. $this->outstanding_amount = $outstanding_amount. $this->last_name . $outstanding_amount) $this->first_name = $first_name. At this point PHP5 searches the Customer class to see if a constructor has been defined. private $last_name. "\n". In the above example on line number 26. $this->last_name = $last_name. "\n". the ‘new’ operator is responsible for creating the Customer class. } public function printData() { echo "Name : " . $outstanding_amount) { $this->setData($first_name. Example: class Customer { private $first_name.e. __construct() defined starting from line no 7. $outstanding_amount) $this->first_name = $first_name. $outstanding_amount). we create a new object of the Customer class. it calls the constructor method i. $this->last_name = $last_name.{ public function setData($first_name. echo "Outstanding Amount : " .

$this->last_name . In PHP4 however. $first_name .0). public function __construct() { $first_name = "". } $c1 = new Customer("Sunil". when you specifically set it to null. we create a new object $c1 and pass values “Sunil”. 3. " " . . The constructor now takes 3 arguments and stores them in the internal private variable $first_name. when you unset it or when the program execution is over. "\n". "\n". $this->outstanding_amount . 2. } An object of a class is destroyed Means 1. class Customer { public function __destructor() { //code } } Example: class Customer { private $first_name.echo "Name : " . Important Note: A destructor cannot take any arguments."Bhatia". the concept of a destructor did not exist. $last_name and $outstanding_amount respectively. it goes out of scope. private $outstanding_amount. 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. private $last_name. $last_name = "". echo "Outstanding Amount : " . A PHP5 destructor is defined by implementing the __destruct() method. In the above example on line number 24. “Bhatia” and zero to the constructor defined on line number starting 7.

"\n". public function setData($first_name. After the program completes its execution. unset($this->customer). $c1).} { $outstanding_amount = 0. private $customer.e. } } $order_id = "L0001". $last_name. 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).0). $first_name . $this->outstanding_amount = $outstanding_amount. } } class Order { private $order_id. $outstanding_amount . the object goes out of scope because the program stops execution after line 45 and hence the destructor is automatically called. $this->last_name = $last_name. Accessor Methods: Accessor methods are also know as getter methods. The argument constructor of the Order class takes two parameters i. In the above example on line number 45. The reason why we need an accessor method is to be able to read the value of a property/attribute in a class object. we create a new object of the Order class. $customer) { $this->order_id = $order_id. therefore to access data of such data members . } public function __destruct() { unset($this->order_id). $c1->setData("Sunil"."Bhatia". $o = new Order($order_id. $this->customer = $customer. "\n". $c1 = new Customer(). echo "Outstanding Amount : " . " " . $order_id and $customer object. } public function printData() { echo "Name : " . $outstanding_amount) $this->first_name = $first_name. public function __construct($order_id. $last_name .

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. If $name is blank the setName() function returns false. echo $c1->getName(). you should not provide a getter or accessor method. } } //accessor method public getName() { return $this->name. Mutator Methods: Mutator methods are opposite to accessor methods. //mutator method public function setName($name) { if(trim($name) != "") { $this->name = $name. otherwise it stores the $name in the $this->name of the class and returns true. return true. } else { return false. Output: Sunil Bhatia In the above example the setName() method accepts a customer’s name and validates to check if $name is blank. 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. $c1->setName("Sunil Bhatia"). Lets look at an example of accessor and mutator methods below: class Customer { private $name. Mutator methods provides a mechanism to store data in data members that have either been declared as private or protected. } } $c1 = new Customer(). Note: To make a property or data member as read only. . you should not provide a setter or mutator method. The getName() returns the name stored in the $name data member of the $c1 object.

In PHP4 a similar functionality existed with a method is_a().. } $p1 = new Person(). You can also use instanceOf operator to compare an object with the name of the class. look at the example below: class Person { . Person.. This check can also happen when an object is compared with a class name.. $p2 = new Person().PHP5 introduces a new operator by the name of instanceOf. else echo "False". In this case $p1 and $p2 both belong to the same class Person and hence the output is True. $c1 = new Customer(). which has been replaced by the instanceOf operator in PHP5. Behaviour of instanceOf operator in inheritance class Customer extends Person { . instanceOf is used to check if two objects passed as operands belong to the same class.. In the above example. if($p1 instanceof $p2) echo "True". we are comparing to check if $p1 and $p2 belong to the same class i. .. Please note that line number 8 can also be written as if($p2 instanceof $p1) and will yield the same output. } $p1 = new Person().e. on line number 7 $p1 object is being compared to check if its a Person type of object. if($p1 instanceof Person) echo "True". else echo "False". } $p1 = new Person(). In this case $p1 is a Person type of object and hence the output is True. class Person { .. In the above example.

In the above example. Customer::TYPES. The answer is no. The next logical question is if we can create an object of the Customer class and using the scope resolution operator access the constant. In the above example. just that the Customer class is a specialized form of the Person class and therefore this becomes possible. This is possible because Customer class is a child of the Person Class. Observe that we don’t need to create an object of the class to make use of the constant. } } $c = new Customer(). However the reverse is not possible. else echo "False". public function showConstant() { echo "Echo from showConstant() : " . Constants To declare a constant in a class. Output: Echo from showConstant() : Anything .e. PHP5 provides developers with a new keyword i. $c->showConstant().if($c1 instanceof $p1) echo "True". on line number 8 $c1 child class object is being compared with $p1 which is a parent class object.because a constant belongs to the class definition scope and not to an object. const. reason . look at the example below: class Customer { const TYPES = "Anything". Outside the class definition we echo the value of the constant by using the scope resolution operator (::) like this Customer::TYPES. we cannot compare if($p1 instanceof $c1) and will result in an error. Customer::TYPES. Example of accessing Constants within a function class Customer { const TYPES = "Anything". } echo "Types are : " . const is a keyword and TYPES is the name of the constant.

public & protected) Definition of Inheritance: Inheritance is the mechanism of deriving a new class from an existing class. A class constant can only be accessed via the scope resolution operator (::) executed on the class name. These inherited attributes and behaviors are usually modified by means of extension. Only a string or numeric value can be assigned to a constant. In PHP5 only single inheritance is allowed. This means that Customer class is the child class and the Person base class. private $record_date. you should use the keyword ‘extends’ in the class definition. A class constant cannot have <a>access specifiers</a> assigned to it (private. private $address. 5. Arrays. Objects & Expressions cannot be assigned to a constant. } } class Customer extends Person { private $customer_id. The child class Customer extends the method getName() and calls it in the getCustomerName() method of the Customer class. class Customer extends from the Person class.// getName() is in Person } } In the above example. public function getName() { return $this->name. Variables defined as constants cannot be changed. 4. public getCustomerId() { return $this->customer_id. PHP5 Inheritance To inherit in PHP5. } public getCustomerName() { return $this->getName().Some observations on Constants 1. Look at the example below: class Person { private $name. 2. 3. It allows a subclass / child class to share/inherit the attributes and behaviors of a base-class or parent class. .

$c->name. Lets look at an example below: class Customer { private $name. 2. 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. //causes an error In the above example. public function __construct($name. $age) { $this->name = $name. causes an error as we are trying to access $name that has been declared as a private member variable. Lets look at how three access specifiers viz. $this->age = $age. $c->name. echo "Name : " . public $age. echo “Name : ” . We can however access the $age data member without any limitation as its public. public A public access specifier allows the data members and methods to be access from anywhere in the script."28"). 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. Lets look at an example below: class Customer { private $name. Let’s understand the use of Access Specifiers with context to Inheritance.Inheritance and Access Specifiers You can refer to the Access specifiers tutorial to understand what it means. Please note that all data members and member functions are public by default. private. public and protected behave in Inheritance: 1. private A private access specifier is used to hide data and member functions. } } $c = new Customer("Sunil". $age) { . the statement. 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. public $age. public function __construct($name.

"28"). //this causes error as $name is protected and not public In the above example. $c1->setName("Sunil"). $this->name = $name. } class Customer extends Person { function setName($name) { //this works as $name is protected in Person $this->name = $name. $c1->name = “Sunil”. //prints 28 In the above example. in the setName() function is referring to the $name data member of the Person class. $c1->name = "Sunil".$this->name = $name. class Person { protected $name. the statement. This access is only possible because the $name variable has been declared as protected. $c->age. echo “Age : ” . Please note that if you declare any data member or method without a access specifier it is considered as ‘public’. . 3. raises an error as $name in the Person class has been declared as protected and not public. protected A protected access specifier allows the derived class to access the data member or member functions of the base class. } } $c1 = new Customer(). Had this been private.age. whereas disallows global access to other objects and functions. $c->. the above statement would have raised an error. $this->age = $age. Further. } } $c = new Customer("Sunil". in the statement towards the end. prints 28 on the screen as $age is a public variable and hence can be accessed from anywhere in the script. echo "Age : " . the statement.

lets define method overriding. Eagle and Swift. fly. . $e->fly(). Output: Fly method of the Eagle Class called Fly method of the Swift Class called In the above example. but before we understand how to override methods in PHP5. 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. $s = new Swift(). } } class Eagle extends Bird { public function fly() { echo "Fly method of the Eagle Class called". Definition of Method Overriding: Method overriding is when the function of base class is re-defined with the same name. 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. Lets look at an example with Bird: class Bird { public function fly() { echo "Fly method of Bird Class called". we create two objects of class Eagle and Swift. Imagine that you have a class by the name of Bird from which you derive two child classes viz. 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.Method Overriding Lets learn how to override methods in PHP5. echo "\n". } } $e = new Eagle(). function signature and access specifier (either public or protected) of the derived class. etc. The Bird class has methods defined to eat. The reason to override method is to provide additional functionality over and above what has been defined in the base class. $s->fly().PHP5 Inheritance . } } class Swift extends Bird { public function fly() { echo "Fly method of the Swift Class called".

. 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(). } } class Customer extends Person{ public function showData() { parent::showData(). Output: calculateAge called of Customer Class calculateAge called of Person Class PHP5 Inheritance . $p1 = new Person(). it’s functionality is completely hidden unless it has been explicitly invoked from the child class. } } $c = new Customer(). echo "This is Customer's showData()\n".Another example of function overriding in Inheritance class Person { function calculateAge($dob) { echo "calculateAge called of Person Class\n". $c1->calculateAge("something"). $c->showData(). } } $c1 = new Customer().Invoking parent methods When you override a method of the base class. $p1->calculateAge("something More"). } } class Customer extends Person { function calculateAge($dob) { echo "calculateAge called of Customer Class\n". Look at the example below: class Person { public function showData() { echo "This is Person's showData()\n".

echo "This is Customer's __construct()\n". 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.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. } public function __destruct() { echo "This is Person's __destruct()\n". Output: This is Person’s __construct() This is Customer’s __construct() This is Person’s __destruct() This is Customer’s __destruct() What is an exception? . look at the way in which the showData() function in the Customer child class is invoking the the Person parent class’s showData() function. refer to the example below: class Person{ public function __construct() { echo "This is Person's __construct()\n".Output: This is Person’s showData() This is Customer’s showData() In the above example. echo "This is Customer's __destruct()\n". PHP5 Inheritance . } } class Customer extends Person{ public function __construct() { parent::__construct(). } public function __destruct() { parent::__destruct(). } } $c = new Customer().

we raise an Exception using the ‘throw’ keyword. The exception class accepts two parameters. The use of a try…catch block PHP5 introduces the try…catch block to trap exceptions. 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. Below the try{} block is the catch() {} block. $code = 0). Within the catch() {} block you will place your logic to either fix the issue or log the error. $line. The try{} block is the area where you will place your code that could raise an exception. Look at the example below.Error Code). Anatomy of PHP5 Exception class class Exception { protected protected protected protected $message. $file. final public function getCode(). the method check() is called between the try {} block. private $trace.An exception is a logical/system error that occurs during the normal execution of a script. The catch block expects the Exception type of object as a parameter. $code. $e->getMessage(). } function check() { if(some error condition) { throw new Exception("Error String". } catch(Exception $e) { echo "Message : " . . 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. $e->getCode(). public function __construct($message = null. In the function check(). echo "Code : " . The statement following ‘throw’ is the syntax of creating a new object of Exception type. } } In the above example. private $string. try { check(). public function __toString().

} } function testException() { throw new CustomerException("CustomerException has been raised". echo "Error Code : " $e->getCode().= "with message : " . } Output: Error Message : CustomerException has been raised Error Code : 101 What is an Abstract Class? . public function getFile(). except for __construct and __toString(). In the above example. $t_message . private __clone(). $message. } catch(CustomerException $e) { echo "Error Message : " $e->getMessage(). } try { testException().101). $code). parent::__construct($t_message. public function getTrace().final final final final final final } public function getMessage(). Extending the Exception class You can also extend the exception class as follows: class CustomerException extends Exception { public function __construct($message = null. public function getTraceAsString(). no other method can be overridden as all other methods are ‘final’. public function getLine(). $code = 0) { $t_message = "Exception raised in CustomerException ".

$w. $l) { $this->height = $h. } } In the above example. $w. The child class must provide the functionality not provided by the abstract class or else the child class also becomes 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().g. the method getPrice() in class Furniture has been declared as Abstract. $this->width = $w. $l.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. } class BookShelf extends Furniture { private $price. } //this is the function body of the parent abstract method public function getPrice() { return $this->price. Private methods cannot be abstract . $l). length. $w. $this->length = $l. Objects of an abstract and interface class cannot be created i. abstract class ClassName {} Example of Abstract Class abstract class Furniture { private $height. } //this function is declared as abstract and hence the function //body will have to be provided in the child class public abstract function getPrice(). $p) { parent::setData($h. public setData($h.e. width. $this->price = $p. the keyword abstract is to be used e. public function setData($h. only objects of concrete class can be created To define a class as Abstract.

abstract class BaseClass { private abstract function myFun().If a method is defined as abstract then it cannot be declared as private (it can only be public or protected). $i = new Indexer(). interface Storable { function getContentsAsText(). } class Document implements Storable { public function getContentsAsText() { return "This is Text of the Document\n". $i->readAndIndex($p). but it does not necessarily tell you how the object does so. This is because a private method cannot be inherited. keyword implements is used. } class DerivedClass extends BaseClass { public function myFun() { //logic here } } $d = new DerivedClass(). To extend from an Interface. An interface enables you to specify that an object is capable of performing a certain function. } } $p = new Document(). this means that it leaves for classes implementing an interface to define its behaviour. } } class Indexer { public function readAndIndex(Storable $s) { $textData = $s->getContentsAsText(). //will cause error What is an Interface? An interface is a contract between unrelated objects to perform a common function. We can have a class extend from more than one Interface. //do necessary logic to index echo $textData. .

The Indexer class is designed to index the contents of any text. 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. we declare a method getContentsAsText() in the Document class.In the above example. Using the Storable interface above. This way any class if it implements the method getContentsAsText() can get indexed Difference between Abstract Class and Interface Abstract Classes 1. The derived class may or may not override the concrete functions defined in base class 3. The meaning with Object Oriented languages changes. 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. float). Polymorphism means many forms. This is how polymorphism is achieved in languages like C where in a function sum(int. Therefore the method sum() has many forms depending on the parameters being passed to it. An abstract class can provide some functionality and leave the rest for derived class 2. Document and the Indexer class are two independant classes. Completely different and non-related classes can be logically be grouped together using an interface Meaning of Polymorphism Polymorphism is derived from two Greek words. Poly (meaning many) and morph (meaning forms). The derived class must provide code for all the methods defined in the interface 3. An interface cannot contain any functionality. It only contains definitions of the methods 2. . The child class extended from an abstract class should logically be related Interface 1. Because the Indexer class is only concerned with the TEXT. hence we can call getContentsAsText() method on the object of Document. int) differs from sum(float.

But. 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. In the above example. The basis of polymorphism is Inheritance and overridden methods. it would not be wrong to assume that myMethod() of class BaseClass will be called. processClass($c). } $c = new DerivedClass(). The reason why this happens is because the object of DerievedClass is being passed and hence the method myMethod() of DerievedClass will be called. } } class DerivedClass extends BaseClass { public function myMethod() { echo "DerivedClass method called". Since the method is being called on the class variable of BaseClass. The parameter accepted in processClass() is that of BassClass. PHP 5 Polymorphism Since PHP 5 introduces the concept of Type Hinting. object $c of class DerievedClass is executed and passed to the processClass() method. Within the processClass() the method myMethod() is being called. this is why method polymorphism is not possible.Because PHP is not type strict and allows variable arguments. polymorphism is possible with class methods. 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. 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. } } function processClass(BaseClass $c) { $c->myMethod(). . Lets look at an example: class BaseClass { public function myMethod() { echo "BaseClass method called".

The reason why this happens is because the object of DerievedClass is being passed and hence the method myMethod() of DerievedClass will be called. as per the definition “When the decision to invoke a function call is made by inspecting the object at runtime it is called Polymorphism”. PHP magic methods . } } function processClass(BaseClass $c) { $c->myMethod().Because PHP is not type strict and allows variable arguments. it would not be wrong to assume that myMethod() of class BaseClass will be called. processClass($c). } } class DerivedClass extends BaseClass { public function myMethod() { echo "DerivedClass method called". The basis of polymorphism is Inheritance and overridden methods. In the above example. polymorphism is possible with class methods. object $c of class DerievedClass is executed and passed to the processClass() method. Lets look at an example: class BaseClass { public function myMethod() { echo "BaseClass method called". } $c = new DerivedClass(). this is why method polymorphism is not possible. But. Within the processClass() the method myMethod() is being called. The parameter accepted in processClass() is that of BassClass. PHP 5 Polymorphism Since PHP 5 introduces the concept of Type Hinting. myMethod() will be called on object DerievedClass. Since the method is being called on the class variable of BaseClass.

$lastName.PHP5 provides a magic method by the name of __toString() (double underscore followed by toString()) which is useful for debugging purposes. Last Name = ” . $this->email = $email.”Bhatia”. $email) { $this->firstName = $firstName. In the background the magic method __toString() is automatically called when such a conversion happens. “. “. $this->firstName . Security Tip: Be careful not to include sensitive data as part of the output as you could compromise security by leaking secure information.”email@domain. Last Name = Bhatia. } public function __toString() { return “Debug message from Customer Class : First Name = ” . $email. Email = ” . $lastName. 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. Many applications are written to write object states in a log file. public function __construct($firstName. $this->lastName = $lastName. therefore you should ensure that sensitive information like Credit Card information. etc is not made available through the magic method __toString() . $c. ?> Output: Customer Object is >> Debug message from Customer Class : First Name = Sunil. $this->email.com See how in this example $c Customer Object got converted into a string type when used with the dot (. } } $c = new Customer(”Sunil”.com”). Email = email@domain.) concatenation operator. $this->lastName . echo “Customer Object is >>” .

$vl) { $this->data[$dt] = $vl. This also holds true for using class members. public function __set($dt. __set() allows you to provide functionality to validate data being stored.com”. PHP engine provides two magic methods __get() and __set(). private $data = array(). Because of the above limitation. } $c = new Customer(). Look at an example below.com to the $email variable.By default PHP is a Loosely typed language and therefore it is not necessary to declare variables before using them. //assigning email@domain. with PHP this works perfectly well as you can assign values to an undefined variable. //assigning email@domain. <?php class Customer { public $name. . $c->name = “Sunil”.com to the $email variable. __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. } } $c = new Customer(). // $name is set because its public $c->email = “email@domain.com”. See example below: <?php class Customer { public $name. But. $c->name = “Sunil”. // $name is set because its public $c->email = “email@domain. ?> Ideally in a strict language this would have been an error. } public function __get($dt) { return $this->data[$dt].

the value of which is the name of the variable that the program wants to unset.echo $c->email. The magic method __unset() method receives an argument . } } $c = new Customer(). the magic method __set() is called. $vl) { throw new Exception(”Cannot assign values to undefined variables”.e. ?> In the above example when email@domain. email@domain. Look at the code below: <? class Customer { private $name. Tip: It is possible to stop this behavior of PHP to assign values to undefined issues.com”.the value of which is the name of the variable that the program wants to test if the variable is set or not. To this __set() method the name of the variable is passed into $dt variable of __set() method and the value i. . public function __set($dt. The next step is to store these values into the $data array so that you could retrieve it later. __get() method is called and the name email is passed in the $dt of the __get() method. The __get() method works in the similar fashion.1). //this will cause an exception to be raised ?> 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 .com is assigned to the undefined variable $email. $c->email = “email@domain. The solution is that you raise an exception from within __set() method.com is passed to $vl variable of the __set() method. When you echo $c->email.

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.e. ‘name’ and unsets the internal array $data[’name’]. The undeclared variable is handled by the magic method __set(). } public function __unset($dt) { return unset($this->data[dt]). } public function __isset($dt) { return isset($this->data[$dt]). $c->name = “Sunil Bhatia”. $vl) { $this->data[$dt] = $vl.e. Similarly. when the program calls unset() on the undeclared variable i.Look at the example below: class Customer { private $data = array().e. echo unset($c->name). The program ties to check if the undeclared variable i.”\n”.. . The magic method __call() is to undeclared methods what __get() and __set() are to undeclared data member. echo isset($c->name).e. In the example above the script creates a new Customer Object. public function __set($dt. Since $c->name is an undeclared variable the PHP5 magic method __isset() is invoked that takes the name of the undeclared variable i. } } $c = new Customer(). $c->name has been set or not using the PHP method isset(). ‘name’ and checks if the internal array $data[’name’] is set or not. } public function __get($dt) { return $this->data[$dt].e. The program assigns a string value to an undeclared variable i. the PHP5 magic method __unset() is invoked that takes the name of the undeclared variable i. $c->name. $c->name.

The magic method __call() takes two arguments. $c->setName is called.10). } } $c = new Customer(). echo "\n".e ‘Sunil’ & ‘Bhatia’. To disallow programs to call an undeclared method. } } . ’setName’ and the second parameter ‘$args’ contains the arguments passed to the ’setName’ method i. you can provide code to handle calls to undeclared method. Using this method. The magic method __call() is internally executed which accepts two parameters. Look at the example below: class Customer { public function __call($name. you should raise an exception from within __call() magic method. an object of the Customer class is created and an undeclared method viz. echo "\n". $c->setName("Sunil"."Bhatia"). Look at the example below: class Customer { public function __call($name. $args) { var_dump($name). The first parameter ‘$name’ contains the name of the method i. 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. $args) { throw new Exception("Undeclared method execution not allowed".e. var_dump($args). Output: string(7) “setName” array(2) { [0]=> string(5) “Sunil” [1]=> string(6) “Bhatia” } In the example above.

On executing the magic method __call(). that is not the case. when the script calls an undeclared variable $c->setName(). we only need the customers. $c = new Customer(). This is explained below. orders.. There is no performance penalty to pay. Each time the above script is executed. Well. The file orders. we would have to do additional programming to ensure that the file orders.php”. Therefore.php But this causes performance issues. what if during execution on the basis of a condition.php”. Look at the example below: include “customer. In the example displayed above.php on line 6 In the above program. there may be performance improvements if not all classes are used all the time. Output: Fatal error: Uncaught exception ‘Exception’ with message ‘Undeclared method execution not allowed’ in D:sunilbwebsiteprogsmagic_call. an instance of class Orders would have to be created. Using the magic method __autoload has the beneficial side effect of requiring strict naming conventions for files that hold class definitions. This is the reason why magic method __autoload() should be used. an exception is raised and the execution of the program stops there (unless we use the try. Therefore you need to include both the files i. $c->setName("Sunil". ‘Bhatia’) #2 {main} thrown in D:sunilbwebsiteprogsmagic_call. To avoid this performance hit.php file. This means that we should only have included the customer. an instance of class Customer is created.php and orders.e.php is loaded only when needed. Array) #1 D:sunilbwebsiteprogsmagic_call. But.catch statements) Many people debate that the magic method __autoload() causes a performance overhead.php file.php is included.php(11): Customer->setName(’Sunil’.php:6 Stack trace: #0 [internal function]: Customer->__call(’setName’. customer.php is not needed. Look at the example below: . include “orders. the magic method __call() is executed. In fact."Bhatia").$c = new Customer().

files are not loaded.e. The require method tries to load $class. When an instance of the customer class is to be created. the __autoload() method has its beneficial side effect of requiring strict file naming convention. The array should contain a list of class members that should be serialized. . } public function setCC($cc) { $this->credit_card_number = $cc. on the line when an instance of the customer class is created i. The __autoload() method is called only once for each new class that needs to be loaded.php file. '. it in turn calls the magic method __autoload(). It does not raise an warning on finding that Customer. Customer.e. Within the __autoload() method we call the ‘require’ method. Working with the magic method __sleep() __sleep() magic method is called when the object of a class is about to be serialized.php (with capital 'C') } $c = new Customer(). as stated earlier. magic method __autoload() is called with the parameter $class containing value ‘Customer’. } public function getName() { return $this->name.php is loaded.php. Subsequent instantiation of the Customer class object will not call the __autoload() method again. private $credit_card_number. Therefore.php and orders. this offers performance improvements in your scripts because. //is substituted as require Customer.’php’ file i. unless the class is needed .php'.function __autoload($class) { require $class . you should not include it in the array. Look at the example below: class Customer { private $name. This magic method __sleep() does not accept any parameter and returns an array. the PHP engine does not have to parse and compile an unnecessary file. the PHP engine checks to see if the file Customer. public function setName($name) { $this->name = $name. This means that if you don’t wish to serialize a particular class member. we don’t explicitly include customer. object $c.php has not been loaded. In the above program. The __autoload() magic method accepts a parameter which is the name of the class that needs to be loaded Therefore. Therefore. Therefore.

s:5:”Sunil”. $data = serialize($c). echo $data. //because of this. It is called when the object of a class is about to be unserialized. Look at the example below: class Customer { private $name. private $credit_card_number. The __wakeup() method is responsible for setup operations after an object has been unserialized. } public function getCC() { return $this->credit_card_number. public function setName($name) { $this->name = $name. $c->setName("Sunil"). This is because the __sleep() magic method returned an array containing only the ‘name’ data member.} public function getCC() { return $this->credit_card_number. only name is serialized } } $c = new Customer()."\n". } public function __sleep() { return array("name"). } public function setCC($cc) { $this->credit_card_number = $cc. Output: O:8:”Customer”:1:{s:14:” Customer name”. Working with the magic method __wakeup() __wakeup() magic method is the opposite of the __sleep() method. $c->setCC("1234567890123456"). } public function getName() { return $this->name. you can see that the serialized string data only contains the name of the Customer Object."\n".} In the above example. } . This magic method __wakeup() does not accept any parameter nor returns anything.

With objects $obj2 = $obj1 does not mean that a new object i. In the __wakeup() method you should ideally make a database call to fetch data of the missing member variable. To clone an object means to create a duplicate of an object. Look at the diagram below. $data = serialize($c). } } } $c = new Customer(). 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. When we execute $obj2 = $obj1."\n". the __wakeup() method is called. the reference of $obj1 is assigned to $obj2. var_dump(unserialize($data)). } public function __wakeup() { if($this->name == "Sunil") { //you would ideally fetch CC data from Database $this->credit_card_number = "1234567890123456". .e. With regular variables $a = $b means that a new variable $a gets created that contains the value of $b. Output: object(Customer)#2 (2) { [”name:private”]=> string(5) “Sunil” [”credit_card_number:private”]=> string(16) “1234567890123456″ } In the above example. This means that $obj1 and $obj2 point to the same memory space. $c->setCC("1234567890123456"). $obj2 gets created.public function __sleep() { return array("name"). $c->setName("Sunil"). This means that 2 variables get created.

e. To clone an PHP5 Object a special keyword i. therefore. when an object is assigned as a reference. 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. clone is used. echo $c2->getName(). $c1->setName("Sunil"). changes made to one object are also reflected in the other. public function setName($name) { $this->name = $name. This is also referred to as shallow copy. $c2 has the reference of $c1. echo $c1->getName().$c1 object changes as well. Therefore."\n". //only reference or memory assigned to $c2 $c2->setName("Vishal"). } public function getName() { return $this->name.Lets look at an example where only references are assigned to another object: class Customer { private $name. when you set a new name in the $c2 object . Therefore. Output: Vishal Vishal In the above example. Example below: $obj2 = clone $obj1. } } $c1 = new Customer()."\n". to create a new $obj2 object we must clone an object to create a new one. . $c2 = $c1.

To implement a ‘deep copy‘ you should implement the magic method __clone(). echo $c2->getName(). } public function getName() { return $this->name. boolean. etc.The above technique works with a class having data members that are of intrinsic type i. //new object $c2 created $c2->setName("Vishal"). Output: Sunil Vishal In the above example. echo $c1->getName(). this technique will not work with a class that has a data member which is an object of another class. You could also provide the implementation of __clone() magic method even when you don’t have an aggregated object. int. To allow aggregated objects (i. 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‘..e. You would want to do this for providing necessary clean up operations. observe the line where the statement $c2 = clone $c1 is executed. $c1->setName("Sunil"). the cloned object continues to share the reference of the data member object of the class that was cloned. you cannot explicitly call the __clone() . In such a scenario. However. So. } public function __clone() { $c = new Customer(). return $c. $c2 = clone $c1.e."\n". $c->setName($this->name). conversions or validations.__clone(). how do we resolve this issue? Doing a regular shallow copy won’t help us. This is internally represented as $c2 = $c1. However."\n". string. Lets explore a very simple example of cloning intrinsic data types: class Customer { private $name. public function setName($name) { $this->name = $name. float. } } $c1 = new Customer().

} public function __clone() { . you should perform ‘deep copy‘. public function setOrderId($order_id) { $this->order_id = $order_id. otherwise //it takes the same instance. $o->setOrderId($this->order_id). return $o.e. Please refer to the example below: class Order { private $order_id. changes made to one object is not reflected in the other. } public function getName() { return $this->name. } } class Customer { private $name. } public function getOrderId() { return $this->order_id. $o->setCustomer($this->customer). } public function getCustomer() { return $this->customer. Now that $c1 and $c2 are two individual objects. } public function __clone() { $o = new Order(). Cloning aggregate objects (i. private $customer. data members that are objects of another class) To clone a class having aggregated objects. public function setName($name) { $this->name = $name. //force a copy of the same object to itself. } public function setCustomer(Customer $customer) { $this->customer = clone $customer.method on an object as the __clone() is automatically called. Seems like a bug to me $this->customer = clone $this->customer.

$o1 = new Order(). therefore changes made to one object is not reflected in another. $o1->setCustomer($c). var_dump($o1). $c->setName("Sunil"). $c->setName($this->name). $c = new Customer(). return $c. var_dump($o2). var_dump($c). 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. . $o1->setOrderId("OD0001"). $o2->getCustomer()->setName("Vishal").} } $c = new Customer(). This example implements the concepts of ‘deep copy‘. $o2 = clone $o1.

For some reason it is necessary to do this for proper working of aggregated cloning.A special note on $this->customer = clone $this->customer. .

Sign up to vote on this title
UsefulNot useful