Object Oriented Concepts
Object-oriented programming is a popular programming paradigm where concepts are grouped into reusable objects that carry their own attributes and behaviors. An attribute can be described as a variable that is in the object, which is used to hold data pertaining to that object, while a behavior describes what an object can do. Let us consider the example of a User object; a user will have a name, an age, and an address, and these will be the attributes for a user. As the User object stores the address, we could have a behavior to allow and facilitate address retrieval; the behaviors are referred to as class methods. An object is a complex data structure that can have one or more types of attributes and one or more types of behaviors.
The attributes and behaviors are defined in a class, and an object is an instance of a class. Therefore, the instances carry the same attributes and behaviors of that class. Though there could be multiple objects of the same class, the data stored in each object would be stored in different memory locations.
OOP is not a new concept and has been around for a very long period. OOP allows us to group our code based on behaviors and attributes and also allows us to organize our code for better reusability. Basic object-oriented features such as objects and classes were introduced into PHP 3 in 1998. In 2000, PHP 4 was released with a better support for object-oriented features, but the implementation of objects was still an issue, as the object referencing was handled similar to value types. So, a whole object would be copied when an object had to be passed in as a parameter to a function. As the object had to be copied, recreated, and stored several times, this led to poor scalability for big applications, extra usage of memory, and unnecessary overhead on the resources. PHP 5, which was shipped in 2004, arrived with a far superior object model that was better at handling objects, thereby increasing the performance and scalability of the web applications. Now that we have a basic idea about OOP, let us dive into understanding classes and objects.
Before we go in detail, lets define important terms related to Object Oriented Programming.
Classes, Objects and Operations
Classes
Basic class definitions begin with the keyword class, followed by a class name, followed by a pair of curly braces which enclose the definitions of the properties and methods belonging to the class.
The class name can be any valid label, provided it is not a PHP reserved word. A valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: ^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$.
A class may contain its own constants, variables (called “properties”), and functions (called “methods”).
Defining PHP Classes
The general form for defining a new class in PHP is as follows:
<?php
class phpClass {
var $var1;
var $var2 = "constant string";
function myfunc ($arg1, $arg2) {
[..]
}
[..]
}
?>
Here is the description of each line:
Here is an example which defines a class of Books type:
<?php
class Books {
/* Member variables */
var $price;
var $title;
/* Member functions */
function setPrice($par){
$this->price = $par;
}
function getPrice(){
echo $this->price ."<br/>";
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title ." <br/>";
}
}
?>
The variable $this is a special variable and it refers to the same object ie. itself.
Another example of PHP Class is
<?php
class SimpleClass
{
// property declaration
public $var = 'a default value';
// method declaration
public function displayVar() {
echo $this->var;
}
}
?>
The pseudo-variable $this is available when a method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object). As of PHP 7.0.0 calling a non-static method statically from an incompatible context results in $this being undefined inside the method. Calling a non-static method statically from an incompatible context has been deprecated as of PHP 5.6.0. As of PHP 7.0.0 calling a non-static method statically has been generally deprecated (even if called from a compatible context). Before PHP 5.6.0 such calls already triggered a strict notice.
Objects
When talking about objects, you refer to variables belonging to these objects as properties (or attributes or fields), and functions are called methods.
These objects are essential when dealing with PHP, as almost everything is an object: for example, functions or arrays are objects, too! And this shows why we use objects: we can bundle our functions and data in one place, we can create objects easily using classes (object constructors), so we can create lots of instances (objects, which have been constructed via a class), which contain mostly the same data, except some little nuances.
Creating Objects in PHP
Once you defined your class, then you can create as many objects as you like of that class type. Following is an example of how to create object using new operator.
$physics = new Books;
$maths = new Books;
$chemistry = new Books;
Here we have created three objects and these objects are independent of each other and they will have their existence separately. Next, we will see how to access member function and process member variables.
Calling Member Functions
After creating your objects, you will be able to call member functions related to that object. One-member function will be able to process member variable of related object only.
Following example shows how to set title and prices for the three books by calling member functions.
$physics->setTitle( "Physics for High School" );
$chemistry->setTitle( "Advanced Chemistry" );
$maths->setTitle( "Algebra" );
$physics->setPrice( 10 );
$chemistry->setPrice( 15 );
$maths->setPrice( 7 );
Now you call another member function to get the values set by in above example:
$physics->getTitle();
$chemistry->getTitle();
$maths->getTitle();
$physics->getPrice();
$chemistry->getPrice();
$maths->getPrice();
This will produce the following result:
Physics for High School
Advanced Chemistry
Algebra
10
15
7
Operations
Operators are used to perform operations on variables and values.
PHP divides the operators in the following groups:
PHP Arithmetic Operators
The PHP arithmetic operators are used with numeric values to perform common arithmetical operations, such as addition, subtraction, multiplication etc.
OperatorNameExampleResult+Addition$x + $ySum of $x and $y–Subtraction$x – $yDifference of $x and $y*Multiplication$x * $yProduct of $x and $y/Division$x / $yQuotient of $x and $y%Modulus$x % $yRemainder of $x divided by $y**Exponentiation$x ** $yResult of raising $x to the $y’th power (Introduced in PHP 5.6)
PHP Assignment Operators
The PHP assignment operators are used with numeric values to write a value to a variable.
The basic assignment operator in PHP is “=”. It means that the left operand gets set to the value of the assignment expression on the right.
AssignmentSame as…Descriptionx = yx = yThe left operand gets set to the value of the expression on the rightx += yx = x + yAdditionx -= yx = x – ySubtractionx *= yx = x * yMultiplicationx /= yx = x / yDivisionx %= yx = x % yModulus
PHP Comparison Operators
The PHP comparison operators are used to compare two values (number or string):
OperatorNameExampleResult==Equal$x == $yReturns true if $x is equal to $y===Identical$x === $yReturns true if $x is equal to $y, and they are of the same type!=Not equal$x != $yReturns true if $x is not equal to $y<>Not equal$x <> $yReturns true if $x is not equal to $y!==Not identical$x !== $yReturns true if $x is not equal to $y, or they are not of the same type>Greater than$x > $yReturns true if $x is greater than $y<Less than$x < $yReturns true if $x is less than $y>=Greater than or equal to$x >= $yReturns true if $x is greater than or equal to $y<=Less than or equal to$x <= $yReturns true if $x is less than or equal to $y
PHP Increment / Decrement Operators
The PHP increment operators are used to increment a variable’s value.
The PHP decrement operators are used to decrement a variable’s value.
OperatorNameDescription++$xPre-incrementIncrements $x by one, then returns $x$x++Post-incrementReturns $x, then increments $x by one–$xPre-decrementDecrements $x by one, then returns $x$x–Post-decrementReturns $x, then decrements $x by one
PHP Logical Operators
The PHP logical operators are used to combine conditional statements.
OperatorNameExampleResultandAnd$x and $yTrue if both $x and $y are trueorOr$x or $yTrue if either $x or $y is truexorXor$x xor $yTrue if either $x or $y is true, but not both&&And$x && $yTrue if both $x and $y are true||Or$x || $yTrue if either $x or $y is true!Not!$xTrue if $x is not true
PHP String Operators
PHP has two operators that are specially designed for strings.
OperatorNameExampleResult.Concatenation$txt1 . $txt2Concatenation of $txt1 and $txt2.=Concatenation assignment$txt1 .= $txt2Appends $txt2 to $txt1
PHP Array Operators
The PHP array operators are used to compare arrays.
OperatorNameExampleResult+Union$x + $yUnion of $x and $y==Equality$x == $yReturns true if $x and $y have the same key/value pairs===Identity$x === $yReturns true if $x and $y have the same key/value pairs in the same order and of the same types!=Inequality$x != $yReturns true if $x is not equal to $y<>Inequality$x <> $yReturns true if $x is not equal to $y!==Non-identity$x !== $yReturns true if $x is not identical to $y
Class Attributes
A class is an element in object-oriented programming that aggregates attributes(fields) – which can be public accessible or not – and methods(functions) – which also can be public or private and usually writes/reads those attributes.
A class is a template for a real-world object to be used in a program. For example, a programmer can create a car class which emulates a car. This class can contain the properties of a car (color, model, year, etc.) and methods (functions) that specify what the car does (drive, reverse, stop, etc.).
An attribute is another term for a field. It’s typically a public constant or a public variable that can be accessed directly.
Creating a class
To create a class, use the?class?keyword, followed by the class name, followed by an opening brace and a closing brace. All the specifics and logisitcs of the class go between the braces.
Syntax:
class className{ }
An example is shown below:
class Book{ }
Creating variables for a class
Class variables are known as properties, because they store important information in regard to the class – hence, they are the classes properties. We will be referring to class variables as ‘variables’ or ‘properties’ interchangeably throughout this lesson.
An example is shown below:
class Book{ var $title; var $numPages; }
The above code uses the Book class and creates two variables for it. The first is $title – a variable which will store the title of the book. The second is $numPages : a variable which will store the number of pages in the book.
Creating functions for a class
Class functions are just like regular functions, except they are defined inside a class definition. Class functions are known as methods, and they can be used to either retrieve data or manipulate data. We will be referring to class functions as ‘functions’ or ‘methods’ interchangeably throughout this lesson.
An example is shown below:
class Book{
var $title;
var $numPages;
function setNumPages($numOfPages){
$numPages = $numOfPages;
}
function getNumPages(){
return $numPages;
}
function setTitle($Title){
$title = $Title;
}
function getTitle(){
return $title;
}
An explanation of each function from the above example:
Instantiating a class
So, you have created your class with its variables and functions, and now what to do with it? Now you can create objects based on how you designed your class. The process of creating an object is called instantiation. You can create an object by creating a variable which stores the object and using the new keyword and the name of the class to instantiate from.
Syntax:
$objectName = new nameOfClass();
An example is shown below:
$yellowPages = new Book();
Creating a class constructor
What if you wanted an object to automatically have a certain value when it is instantiated? For example, if you wanted all instances of the Book class to automatically have 200 pages? This is what class costructors are for. Class constructors are used to set objects to have certain values when they are initialized. The function used for this task is the __construct() function, and it goes inside the class definition.
Syntax:
function __construct($param1, $param2, etc.){ $this -> propertyName = $value; }
An example is shown below:
class Book{ $title; $numPages; function __construct(){ $this->$numPages = 200; } }
Did you notice a new keyword? The keyword this is a special keyword used when creating classes. The purpose of it is to refer to the current class. The code inside the __construct function from the example above could have been $Book->$numPages = 200; instead of $this->$numPages = 200;, and the result would have been the same. When creating classes, $this can be used synonomously with the name of the class (in this case the class being the Book class).
In the above example, the __construct() function specifies that all instances of the Book class will automatically have 200 pages.
Referencing the variables of a class with an object
You can reference the variables of a class with an object by referring to them by name.
Syntax:
$object->varName;
An example is shown below:
$yellowPages->numPages;
This example would reference the $numPages variable of the $yellowBook class. Notice how in the reference to the variable there is no $ symbol in front of the variable name. When referencing a class variable with the object name, you do NOT have to use the $ symbol.
Using the functions of a class with an object
Just as with the variables of a class, you can use the functions of a class with an object by referring to them by name.
Syntax:
$object->functionName();
An example is shown below:
$yellowPages->getNumPages();
This example would call the getNumPages() function of the Book class.
Access Modifier
PHP access modifiers are used to set access rights with?PHP?classes and their members that are the functions and variables defined within the class scope. In PHP, there are some keywords representing these access modifiers. These keywords will be added with PHP classes and its members.
PHP keywords as Access Control Modifiers
Now, let us have a look at the following list to know about the possible PHP keywords used as access modifiers.
Access modifiers Usage with PHP Classes, Class Members
Based on the possibility of applying the above list of PHP access modifiers, we can classify them. The following tabular column specifies which keyword could be applied wherein classes, functions or methods.
access modifierclassesfunctionsvariablepublicNot ApplicableApplicableApplicableprivateNot ApplicableApplicableApplicableprotectedNot ApplicableApplicableApplicableabstractApplicableApplicableNot ApplicablefinalApplicableApplicableNot Applicable
public Access Modifier
Before introducing access modifiers in PHP, all classes and its members are treated as public by default. Still, for PHP classes without specifying any access modifiers, then it will be treated as public.
If we specify public, private or protected for a PHP class, then it will cause the parse error. For example, if we define a class as,
public class {
...
...
}
Then, the following parse error will be displayed to the browser.
Parse error: syntax error, unexpected 'public' (T_PUBLIC) in.
Similarly, class functions without any access modifiers will be treated as public functions. But, it is good programming practice to specify those functions as public for better understanding.
Unlike PHP classes and functions, we need to specify access modifiers for PHP class variables explicitly. For example, the following code is invalid, which will cause PHP parse error.
class Toys {
$categories = array("puzzles","pull back","remote","soft");
...
}
And, the valid code for defining classes with public variables follows.
class Toys {
public $categories = array("puzzles","pull back","remote","soft");
...
}
private Access Modifier
We can state this keyword only for class variables and function, but not for the class itself, as like as public modifier. PHP class members defined as private cannot be accessed directly by using its instance. For example,
class Toys {
private $categories = array("puzzles","pull back","remote","soft");
public function getToysCategories() {
return $this->categories;
}
}
$objToys = new Toys();
print "<pre>";
print_r($objToys->categories); // invalid
print_r($objToys->getToysCategories());
print "</pre>";
In the above program, Toys class contains a private variable and a public function. Accessing this private variable by using Toys class instance with the line,
print_r($objToys->categories); // invalid
will cause PHP fatal error as,
Fatal error: Cannot access private property Toys::$categories in.
But we can access class private variables via any public function of that class. In the above program, we are getting the elements of $categories array variables via getToysCategories() function defined as public.
Note that, all members of a class can be accessed within the class scope by using $this variable.
protected Access Modifier
This keyword is used in a PHP program which is using PHP inheritance. And, it is used to prevent access to PHP classes and its members from anywhere, except from inside the class itself or from inside its subclasses.
With this keyword, PHP classes and its member’s functions cannot be access directly from outside the classes and their subclasses, with the references to their instance.
Consider the following PHP program.
<?php
class Toys {
protected $categories = array("puzzles","pull back","remote","soft");
protected $toys = array(array("name"=>"Mechanical Cars","category"=>"pull back"),
array("name"=>"Jigsaw","category"=>"puzzles"),
array("name"=>"HiTech Cars","category"=>"remote"),
array("name"=>"Teddy Bears","category"=>"soft"),
array("name"=>"Baby pillow","category"=>"soft"),
array("name"=>"Chinese Checker","category"=>"puzzles"),
array("name"=>"Electronic Toys","category"=>"remote"));
protected function getToys() {
for($i=0;$i<count($this->toys);$i++) {
$toys_list[] = $this->toys[$i]["name"];
}
return $toys_list;
}
protected function getToysByCategory($category) {
for($i=0;$i<count($this->toys);$i++) {
if($this->toys[$i]["category"]==$category)
$toys_list[] = $this->toys[$i]["name"];
}
return $toys_list;
}
}
class SoftToys extends Toys {
protected $category = "soft";
function getToys() {
return $this->getToysByCategory($this->category);
}
}
$objToys = new Toys();
$objSoftToys = new SoftToys();
print "<pre>";
/**Invalid
print_r($objToys->categories);
print_r($objSoftToys->categories);
print_r($objToys->getToys());*/
print_r($objSoftToys->getToys());
print "</pre>";
?>
In this program, we can see some of the statements are commented. These are invalid attempts to access protected members from outside Toys class.
We can access these members, as we have done with private member access by using the public function of a class.
abstract Access Modifier
We can define a PHP class or its function as abstract, but, abstractly is not applicable for class variables. For having at least one abstract function in a PHP class, then that class should be an abstract class.
We cannot access PHP abstract class members with its instance. Because PHP restricts instantiating the abstract class and cause the following error message while creating such instance.
Fatal error: Cannot instantiate abstract class.
But we can inherit an abstract class. Simply to say, PHP abstract classes are behaving like PHP interfaces. For an abstract class, we cannot contain any abstract function definition. Rather, we should just declare a function. For defining it, we should inherit this abstract class for a non-abstract subclass to have function definition.
Following code is an example of PHP abstract modifier.
abstract class Toys {
public $categories = array("puzzles","pull back","remote","soft");
public $toys = array(array("name"=>"Mechanical Cars","category"=>"pull back"),
array("name"=>"Jigsaw","category"=>"puzzles"),
array("name"=>"HiTech Cars","category"=>"remote"),
array("name"=>"Teddy Bears","category"=>"soft"),
array("name"=>"Baby pillow","category"=>"soft"),
array("name"=>"Chinese Checker","category"=>"puzzles"),
array("name"=>"Electronic Toys","category"=>"remote"));
abstract function getToys();
function getToysByCategory($category) {
for($i=0;$i<count($this->toys);$i++) {
if($this->toys[$i]["category"]==$category)
$toys_list[] = $this->toys[$i]["name"];
}
return $toys_list;
}
}
class SoftToys extends Toys {
protected $category = "soft";
function getToys() {
return $this->getToysByCategory($this->category);
}
}
$objSoftToys = new SoftToys();
print "<pre>";
print_r($objSoftToys->getToys());
print "</pre>";
final Access Modifier
With PHP final access modifier classes are prevented from inheriting them. If we attempt to derive subclasses from PHP final classes, then the following fatal error will occur to stop program execution.
Fatal error: Class SoftToys may not inherit from final class.
PHP final keyword should be used for PHP classes and functions, but not for class properties or variables. PHP functions with the final keyword will not be overridden.
Constructor & Destructor
Constructor Functions
Constructor Functions are special type of functions which are called automatically whenever an object is created. So, we take full advantage of this behavior, by initializing many things through constructor functions.
PHP provides a special function called __construct() to define a constructor. You can pass as many as arguments you like into the constructor function.
Following example will create one constructor for Books class and it will initialize price and title for the book at the time of object creation.
function __construct( $par1, $par2 ) {
$this->title = $par1;
$this->price = $par2;
}
Now we don’t need to call set function separately to set price and title. We can initialize these two-member variables at the time of object creation only. Check following example below ?
$physics = new Books( "Physics for High School", 10 );
$maths = new Books ( "Advanced Chemistry", 15 );
$chemistry = new Books ("Algebra", 7 );
/* Get those set values */
$physics->getTitle();
$chemistry->getTitle();
$maths->getTitle();
$physics->getPrice();
$chemistry->getPrice();
$maths->getPrice();
This will produce the following result:
Physics for High School
Advanced Chemistry
Algebra
10
15
7
Destructor
Like a constructor function you can define a destructor function using function __destruct(). You can release all the resources with-in a destructor.
Inheritance
Inheritance is a well-established programming principle, and PHP makes use of this principle in its object model. This principle will affect the way many classes and objects relate to one another.
For example, when you extend a class, the subclass inherits all of the public and protected methods from the parent class. Unless a class overrides those methods, they will retain their original functionality.
This is useful for defining and abstracting functionality and permits the implementation of additional functionality in similar objects without the need to reimplement all of the shared functionality.
PHP class definitions can optionally inherit from a parent class definition by using the extends clause. The syntax is as follows ?
class Child extends Parent {
<definition body>
}
The effect of inheritance is that the child class (or subclass or derived class) has the following characteristics ?
Following example inherit Books class and adds more functionality based on the requirement.
class Novel extends Books {
var $publisher;
function setPublisher($par){
$this->publisher = $par;
}
function getPublisher(){
echo $this->publisher. "<br />";
}
}
Now apart from inherited functions, class Novel keeps two additional member functions.
Another example of inheritance is:
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}
class Bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP(); // Output: 'PHP is great'
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP(); // Output: 'PHP is great'
?>
Static Method
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static cannot be accessed with an instantiated class object (though a static method can).
For compatibility with PHP 4, if no visibility declaration is used, then the property or method will be treated as if it was declared as public.
Static Methods
Because static methods are callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static.
An example of static method is:
<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
?>
Static Properties
Static properties cannot be accessed through the object using the arrow operator ->.
Like any other PHP static variable, static properties may only be initialized using a literal or constant before PHP 5.6; expressions are not allowed. In PHP 5.6 and later, the same rules apply as const expressions: some limited expressions are possible, provided they can be evaluated at compile time.
As of PHP 5.3.0, it’s possible to reference the class using a variable. The variable’s value cannot be a keyword (e.g. self, parent and static).
An example of static properties is:
<?php
class Foo
{
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
class Bar extends Foo
{
public function fooStatic() {
return parent::$my_static;
}
}
print Foo::$my_static . "\n";
$foo = new Foo();
print $foo->staticValue() . "\n";
print $foo->my_static . "\n"; // Undefined "Property" my_static
print $foo::$my_static . "\n";
$classname = 'Foo';
print $classname::$my_static . "\n"; // As of PHP 5.3.0
print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>
Type Hinting
Type hinting allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated: in PHP 5, this will be a recoverable fatal error, while PHP 7 will throw a TypeError exception.
To specify a type declaration, the type name should be added before the parameter name. The declaration can be made to accept NULL values if the default value of the parameter is set to NULL.
Type declarations were also known as type hints in PHP 5.
Valid types
The valid types are described in the table below:
TypeDescriptionMinimum PHP versionClass/interface nameThe parameter must be an instanceof the given class or interface name.PHP 5.0.0selfThe parameter must be an instanceof the same class as the one the method is defined on. This can only be used on class and instance methods.PHP 5.0.0arrayThe parameter must be an array.PHP 5.1.0callableThe parameter must be a valid callable.PHP 5.4.0boolThe parameter must be a boolean value.PHP 7.0.0floatThe parameter must be a floating point number.PHP 7.0.0intThe parameter must be an integer.PHP 7.0.0stringThe parameter must be a string.PHP 7.0.0iterableThe parameter must be either an array or an instanceof Traversable.PHP 7.1.0objectThe parameter must be an object.PHP 7.2.0
An example of basic class type hinting is shown below:
<?php
class C {}
class D extends C {}
// This doesn't extend C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
The above example will output:
C
D
Fatal error: Uncaught TypeError: Argument 1 passed to f() must be an instance of C, instance of E given, called in - on line 14 and defined in -:8
Stack trace:
#0 -(14): f(Object(E))
#1 {main}
thrown in - on line 8
Object Cloning
Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.
An object copy is created by using the clone keyword (which calls the object’s __clone() method if possible). An object’s __clone() method cannot be called directly.
$copy_of_object = clone $object;
When an object is cloned, PHP 5 will perform a shallow copy of all of the object’s properties. Any properties that are references to other variables will remain references.
void __clone ( void )
Once the cloning is complete, if a __clone() method is defined, then the newly created object’s __clone() method will be called, to allow any necessary properties that need to be changed.
An example of Cloning an object is
<?php
class SubObject
{
static $instances = 0;
public $instance;
public function __construct() {
$this->instance = ++self::$instances;
}
public function __clone() {
$this->instance = ++self::$instances;
}
}
class MyCloneable
{
public $object1;
public $object2;
function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone $this->object1;
}
}
$obj = new MyCloneable();
$obj->object1 = new SubObject();
$obj->object2 = new SubObject();
$obj2 = clone $obj;
print("Original Object:\n");
print_r($obj);
print("Cloned Object:\n");
print_r($obj2);
?>
The above example will output:
Original Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 1
)
[object2] => SubObject Object
(
[instance] => 2
)
)
Cloned Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 3
)
[object2] => SubObject Object
(
[instance] => 2
)
)
PHP 7.0.0 introduced the possibility to access a member of a freshly cloned object in a single expression:
An example of Access member of freshly cloned object
<?php
$dateTime = new DateTime();
echo (clone $dateTime)->format('Y');
?>
The above example will output something similar to:
2016
Abstract Class
PHP 5 introduces abstract classes and methods. Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method’s signature – they cannot define the implementation.
When inheriting from an abstract class, all methods marked abstract in the parent’s class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private. Furthermore, the signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. For example, if the child class defines an optional argument, where the abstract method’s signature does not, there is no conflict in the signature. This also applies to constructors as of PHP 5.4. Before 5.4 constructor signatures could differ.
An abstract class is one that cannot be instantiated, only inherited. You declare an abstract class with the keyword abstract, like this:
When inheriting from an abstract class, all methods marked abstract in the parent’s class declaration must be defined by the child; additionally, these methods must be defined with the same visibility.
abstract class MyAbstractClass {
abstract function myAbstractFunction() {
}
}
Note that function definitions inside an abstract class must also be preceded by the keyword abstract. It is not legal to have abstract function definitions inside a non-abstract class.
Another example of abstract class example is:
<?php
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Common method
public function printOut() {
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>
The above example will output:
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2
Final Keyword
PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final, then it cannot be extended.
Following example results in Fatal error: Cannot override final method BaseClass::moreTesting()
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called<br>";
}
final public function moreTesting() {
echo "BaseClass::moreTesting() called<br>";
}
}
class ChildClass extends BaseClass {
public function moreTesting() {
echo "ChildClass::moreTesting() called<br>";
}
}
?>
Another example is:
<?php
final class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
// Here it doesn't matter if you specify the function as final or not
final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
}
// Results in Fatal error: Class ChildClass may not inherit from final class (BaseClass)
?>
Implementing Interface
Interfaces are defined to provide a common function names to the implementers. Different implementors can implement those interfaces according to their requirements. You can say, interfaces are skeletons which are implemented by developers.
As of PHP5, it is possible to define an interface, like this:
interface Mail {
public function sendMail();
}
Then, if another class implemented that interface, like this:
class Report implements Mail {
// sendMail() Definition goes here
}
Object Interfaces
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are implemented.
Interfaces are defined in the same way as a class, but with the interface keyword replacing the class keyword and without any of the methods having their contents defined.
All methods declared in an interface must be public; this is the nature of an interface.
Understanding Advance and New Object-Oriented functionality
This topic is intended to cover some of the more advanced topics of object-oriented programming (OOP) in PHP and is intended to follow up on my previous article covering the basics of OOP in PHP. Specifically, this article will teach you all about:
Extending Classes
If you think about it, many things in this world have a main type and then a sub-type. For example, there are humans (main type) and then there are men (sub-type) and women (sub-type). As human beings, men and women share a lot of attributes. We all have arms and legs and a head. We all have faces, toes, and eyeballs, and the list goes on and on of all the things that are similar between men and women. They also do a lot of things that are the same. Most people brush their teeth the same way, work the same way, and eat the same way.
There ARE differences, though, and for the sake of a family-friendly (although incorrect) article, I’m just going to say that the main difference is that all women can have babies and all men cannot have babies.
Protected Scope
In the previous article on the basics of OOP in PHP, I covered public and private scopes. Now we have the “protected” scope, which is very similar to “private” in that any code OUTSIDE of the class cannot touch these variables. the difference between “private” and “protected” is that “private” is accessible only to that EXACT class that has the property. Even child classes can’t see or change the private properties of their parent classes. Private is private!
Protected properties are private, but they CAN be accessed by child classes. So, if the Human class had a protected property, then any class method inside of the Human class or inside of the Man or Woman or ThreeLeggedMan (etc) classes could access that property. So, to recap;
Method Overloading
In many languages, overloading means that you have two different class methods with the same name, but different arguments. For example:
public function eatFood($whatFood)
{
echo "Yum! Eating with bare hands is messy!";
}
public function eatFood($whatFood,$useAFork)
{
if($useAFork)
{
echo "Yum! Eating with a fork is much cleaner!";
}
else
{
echo "Yum! Eating with bare hands is messy!";
}
}
Accessors and Mutators
Every time I hear these terms, I imagine an obsessed science fiction fan coming up with them. I think they are better called “getters” and “setters” because that’s what they do.
Accessors (“getters”) are functions that simply get/return the value of a class property (usually a private property), while Mutators (“setters”) are functions that set/change the value of a class property. There’s nothing really technically different about these functions – the functions are just called “Mutators” and “Accessors” because of what they do. Here’s an example:
class Human
{
private $name;
public function getName()
{
return $this->name();
}
public function setName($name)
{
$this->name = $name;
}
}
The __get Method
There are some “magic” methods that you can define in your classes to make your class “smarter.” These magic methods already exist in every class, but PHP handles them by default. However, you can tell PHP that you want to take over that job instead. All you have to do is create a new class method using any of those special names.
The first magic method is __get, which is a very simple accessor function. Whenever you try to get a property that doesn’t exist, the __get function is called.
The __set Method
The __set method is just the opposite of __get. Instead of handling the cases where your code is trying to access a property that doesn’t exist, the __set method handles the cases where your code tries to SET a property that doesn’t exist. I will leave the example up to your imagination.
The __construct Method
The __construct method is called whenever you create a new instance of a class. This is a very frequently-defined magic method, because you can create some elegant code. Most people use this __construct method to automatically run some extra code as soon as the instance is created
Magic functions with PHP
The function names __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() and __debugInfo() are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them.
__sleep() and __wakeup()
public array __sleep ( void )
void __wakeup ( void )
serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. If the method doesn’t return anything then NULL is serialized and E_NOTICE is issued.
Note:
It is not possible for __sleep() to return names of private properties in parent classes. Doing this will result in an E_NOTICE level error. Instead you may use the Serializable interface.
The intended use of __sleep() is to commit pending data or perform similar cleanup tasks. Also, the function is useful if you have very large objects which do not need to be saved completely.
Conversely, unserialize() checks for the presence of a function with the magic name __wakeup(). If present, this function can reconstruct any resources that the object may have.
The intended use of __wakeup() is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.
An example of above method is shown below:
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
}?>
__toString()
public string __toString ( void )
The __toString() method allows a class to decide how it will react when it is treated like a string. For example, what echo $obj; will print. This method must return a string, as otherwise a fatal E_RECOVERABLE_ERROR level error is emitted.
An example of above method is shown below:
<?php
// Declare a simple class
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new TestClass('Hello');
echo $class;
?>
The above example will output:
Hello
It is worth noting that before PHP 5.2.0 the __toString() method was only called when it was directly combined with echo or print. Since PHP 5.2.0, it is called in any string context (e.g. in printf() with %s modifier) but not in other types contexts (e.g. with %d modifier). Since PHP 5.2.0, converting objects without __toString() method to string would cause E_RECOVERABLE_ERROR.
__invoke()
mixed __invoke ([ $... ] )
The __invoke() method is called when a script tries to call an object as a function.
Note:
This feature is available since PHP 5.3.0.
An example of above method is shown below:
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
The above example will output:
int(5)
bool(true)
__set_state()
static object __set_state ( array $properties )
This static method is called for classes exported by var_export() since PHP 5.1.0.
The only parameter of this method is an array containing exported properties in the form array(‘property’ => value, …).
An example of above method is shown below:
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>
The above example will output:
object(A)#2 (2) {
["var1"]=>
int(5)
["var2"]=>
string(3) "foo"
}
Note:?When exporting an object, var_export() does not check whether __set_state() is implemented by the object’s class, so re-importing such objects will fail, if __set_state() is not implemented. Particularly, this affects some internal classes. It is the responsibility of the programmer to verify that only objects will be re-imported, whose class implements __set_state().
__debugInfo()
array __debugInfo ( void )
This method is called by var_dump() when dumping an object to get the properties that should be shown. If the method isn’t defined on an object, then all public, protected and private properties will be shown.
This feature was added in PHP 5.6.0.
An example of above method is shown below:
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>
The above example will output:
object(C)#1 (1) {
["propSquared"]=>
int(1764)
}
Summary
We conclude the chapter by summarizing the above discussed topics in following points: