PHP OBJECT
ORIENTATION
(APIE)
OBJECT
ORIENTATION
PHP is an Object-Oriented programming
language
Fundamental feature of OO is the class
PHP classes support
Encapsulation
Inheritance
Polymorphism
Abstraction
2
OOP in Web Programming
Small Web projects
• Consist of web scripts designed and written using an ad-hoc approach; a
function-oriented, procedural methodology
Large Web software projects
• Need a properly thought-out development methodology – OOP →
• OO approach can help manage project complexity, increase code
reusability, reduce costs.
• OO analysis and design process = decide what object types, what hidden
data/operations and wrapper operations for each object type
• UML – as tool in OO design, to allow to describe classes and class
relationships
3
OBJECT ORIENTED
CONCEPT
Classes, which are the "blueprints" for an object and are
the actual code that defines the properties and methods.
Objects, which are running instances of a class and
contain all the internal data and state information needed
for your application to function.
Encapsulation, which is the capability of an object to
protect access to its internal data
Inheritance, which is the ability to define a class of one
kind as being a sub-type of a different kind of class
(much the same way a square is a kind of rectangle).
WHAT IS A CLASS?
Classes
Sophisticated ‘variable types’
Data variables (data members) and functions
(methods) are wrapped up in a class.
Collectively, data members and methods are
referred to as class members.
An instance of a class is known as an object.
//defining a new class named Robot
class Robot {
//place class members here...
}
CREATING CLASS
Let's start with a simple example. Save the following in a file
called class.lat.php:
<?php
class Demo
{
}
?>
ADDING METHOD
The Demo class isn't particularly useful if it isn't able to do
anything, so let's look at how you can create a method.
<?php
class Demo
{
function SayHello($name)
{
echo “Hello $name !”;
}
}
?>
ADDING PROPERTIES
Adding a property to your class is as easy as adding a
method.
<?php
class Demo
{
public $name;
function SayHello()
{
echo “Hello $this->$name !”;
}
}
?>
OBJECT
INSTANTIATION
You can instantiate an object of type Demo like this:
<?php
require_once('class.lat.php');
$objDemo = new Demo();
$objDemo->name = “Bayu”;
$objDemo->SayHallo();
?>
INSTANTIATING A CLASS USING
NEW
Once a class has been created, any number of
object instances of that class can be created.
$dogRobot = new Robot();
To invoke methods:
e.g.
object->method() <?php
....
$dogRobot = new Robot();
$dogRobot ->crawlWeb();
$dogRobot -> play();
echo $dogRobot ->talk();
...
?>
DEFINING CLASSES
<?php
class Person { Data members
private $strFirstname = “Napoleon";
private $strSurname = “Reyes";
function getFirstname() {
return $this->strFirstname;
} Methods
function getSurname() {
return $this->strSurname;
}
}
// outside the class definition
$obj = new Person; // an object of type Person
echo "<p>Firstname: " . $obj->getFirstname() . "</p>";
echo "<p>Surname: " . $obj->getSurname() . "</p>";
?>
DATA MEMBERS AND METHODS
class Class1 {
We need to provide
• private $strName = “A”; accessor functions to
• private $intNumber = 1; allow users of Class1
• function getName() { to access the private
•}
data members:
• function getNumber(){ function getName(){
•} return $this-
} >strName;
}
Is this publicly
accessible?
$THIS OBJECT POINTER
As with so many languages, there is a special
pointer that references an instance of a class:
$this
function getName(){ function getName(){
return $this->strName;
return strName;
}
}
INVOKING METHODS INSIDE A CLASS
$this->functionName();
class Person{
...
function setFirstname($strSurname) {
$this->strFirstname = $strSurname;
}
function setSurname($strSurname) {
$this->strSurname = $strSurname;
}
private function display() {
echo "<p>Firstname: " . $this->strFirstname . "</p>";
echo "<p>Surname: " . $this->strSurname . "</p>";
}
function setDisplayFirstnameSurname($strFirstname, $strSurname) {
$this->setFirstname($strFirstname);
$this->setSurname($strSurname);
$this->display();
}
}
Getters and Setters
Encapsulation : hide attributes from direct access from
outside a class and provide controlled access through
accessor and mutator functions
• You can write custom getVariable() / setVariable($var) functions or
• Overload the functionality with the __get() and __set() functions in PHP
__get() and __set()
• Prototype:
mixed __get($var);
// param represents the name of an attribute, __get returns the value of
that attribute
void __set($var, $value);
// params are the name of an attribute and the value to set it to
Getters and Setters
__get() and __set()
• Can only be used for non-static attributes!
• You do not directly call these functions;
For an instance $acc of the BankAccount class:
$acc->Balance = 1000;
implicitly calls the __set() function with the value of $name set
to ‘Balance’, and the value of $value set to 1000.
(__get() works in a similar way)
Getters and Setters
__get() and __set() functions’ value: a single access point to
an attribute ensures complete control over:
• attribute’s values
function __set($name, $value) {
echo "<p>Setter for $name called!</p>";
if (strcasecmp($name, "Balance")==0 && ($value>=0))
$this->$name = $value;
...
}
• underlying implementation: as a variable, retrieved from a db when
needed, a value inferred based on the values of other attributes
→ transparent for clients as long as the accessor / mutator
functions’ contract doesn’t change.
Designing Classes
Classes in Web development:
• Pages
• User-interface components
• Shopping carts
• Product categories
• Customers
TLA Consulting example revisited - a Page class, goals:
• A consistent look and feel across the pages of the website
• Limit the amount of HTML needed to create a new page: easily
generate common parts, describe only uncommon parts
• Easy maintainable when changes in the common parts
• Flexible enough: ex. allow proper navigation elements in each page
EXAMPLE: DEFINING CLASSES
class ShoppingCart {
private $name; // Name of shopper
private $items; // Items in our shopping cart
public function ShoppingCart($inputname) {
$this->name = $inputname;
}
// Add $num articles of $artnr to the cart
public function addItem($artnr, $num) {
$this->items[$artnr] += $num;
}
// Take $num articles of $artnr out of the cart
public function removeItem($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} elseif ($this->items[$artnr] == $num) {
unset($this->items[$artnr]);
return true;
} else {
return false;
}
}
}
CLASS EXAMPLE
<?php
class Point {
public $x;
public $y;
# equivalent of a Java constructor
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
public function distance($p) {
$dx = $this->x - $p->x;
$dy = $this->y - $p->y;
return sqrt($dx * $dx + $dy * $dy);
}
# equivalent of Java's toString method
public function __toString() {
return "(" . $this->x . ", " . $this->y . ")";
}
} ?> PHP
CLASS USAGE
EXAMPLE
<?php
# this code could go into a file named use_point.php
include("Point.php");
$p1 = new Point(0, 0);
$p2 = new Point(4, 3);
print "Distance between $p1 and $p2 is " . $p1->distance($p2) .
"\n\n";
var_dump($p2); # var_dump prints detailed state of an object
?> PHP
Distance between (0, 0) and (4, 3) is 5
object(Point)[2]
public 'x' => int 4
public 'y' => int 3
PHP
ENCAPSULATION
Data members are normally set inaccessible from outside
the class (as well as certain types of methods)
protecting them from the rest of the script and other
classes.
This protection of class members is known as
encapsulation.
e.g.
<?php
....
$dogRobot = new Robot();
$dogRobot ->crawlWeb();
$dogRobot -> play();
echo $dogRobot ->talk();
...
PROTECTING ACCESS TO
MEMBER VARIABLES (1)
There are three different levels of visibility that a member
variable or method can have :
Public
▪ members are accessible to any and all code
Private
▪ members are only accessible to the class itself
Protected
▪ members are available to the class itself, and to classes that inherit
from it
Public is the default visibility level for any member variables or functions
that do not explicitly set one, but it is good practice to always explicitly
state the visibility of all the members of the class.
PROTECTING ACCESS TO
MEMBER VARIABLES (2)
Try to change access level of property named “name” to
private of previous code.
What the possible solution of this problem?
Make the getter and setter function...
Always use get and set functions for your properties. Changes to business
logic and data validation requirements in the future will be much easier to
implement.
PRIVATE ACCESS SPECIFIER
class MyClassName{
private $strFirstName;
}
private – limits the
visibility of the
methods and data
members only to the
class that defines them.
MODIFYING DATA MEMBERS
intNumber is private
Outside the class, trying to execute
the following:
$clMyObj->intNumber++;
will fail!...
We need a method to access and change
its value:
function setNumber($intNumber) {
$this->intNumber = $intNumber;
} Look at the position of the dollar sign ($) – no
PUBLIC ACCESS SPECIFIER
class MyClassName{
public $strFirstName;
public function getFirstName(){
}
}
public – class
members can be
accessed both
within and outside
the class.
PROTECTED ACCESS SPECIFIER
//protected for public use, but accessible in
Class MyClassName{ a derived class
protected $strFirstName;
protected function getFirstName(){
}
Inherited protected class members
}
– accessible inside a derived class
Visibility of protected class
members outside the class
definition – protected class
members are inaccessible.
EXAMPLE: ACCESS SPECIFIERS
<?php
class MyClass {
public $public = 'Public';
protected $protected = 'Protected'; //protected for public use, but accessible in a derived class
private $private = 'Private';
function printHello() {
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
// outside the class definition
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
//...
http://php.net/manual/en/language.oop5.visibility.php
EXAMPLE: ACCESS SPECIFIERS
<?php a Derived class
//...
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
// protected – ‘protected’ for public use, but accessible in a derived class
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
// outside the class definition
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
?>
http://php.net/manual/en/language.oop5.visibility.php
Example: Method Declaration
<?php //OUTSIDE THE CLASS DEFINITION...
class MyClass
{
// Declare a public constructor
public function __construct() { }
$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
// Declare a public method
public function MyPublic() { }
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private
work
// Declare a protected method
protected function MyProtected() { } //...
// Declare a private method
private function MyPrivate() { }
// This is public
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
http://php.net/manual/en/language.oop5.visibility.php
EXAMPLE: METHOD DECLARATION
<?php class MyClass2 extends MyClass
class MyClass
{
{
// Declare a public constructor // This is public
public function __construct() { } function Foo2()
{
// Declare a public method
$this->MyPublic();
public function MyPublic() { }
$this->MyProtected();
// Declare a protected method $this->MyPrivate(); // Fatal Error
protected function MyProtected() { } }
}
// Declare a private method
private function MyPrivate() { }
$myclass2 = new MyClass2;
// This is public $myclass2->MyPublic(); // Works
function Foo()
$myclass2->Foo2(); // Public and Protected work, not Private
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
http://php.net/manual/en/language.oop5.visibility.php
EXAMPLE: METHOD DECLARATION
<?php
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
$myFoo = new foo();
public function testPublic() {
echo "Bar::testPublic\n"; $myFoo->test(); // Bar::testPrivate
}
private function testPrivate() { ?>
// Foo::testPublic
echo "Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}
private function testPrivate() {
echo "Foo::testPrivate\n";
}
}
http://php.net/manual/en/language.oop5.visibility.php
ACCESSING PRIVATE MEMBERS
OF THE SAME OBJECT TYPE
<?php
class Test
{
private $foo;
Objects of the same type will have access to each others
Private and protected members even though they are
public function __construct($foo)
not the same instances.
{
$this->foo = $foo;
} string(5) "hello"
private function bar()
{
Accessed the private method
echo 'Accessed the private method.';
}
public function baz(Test $other)
{
// We can change the private property:
$other->foo = 'hello';
var_dump($other->foo);
// We can also call the private method:
$other->bar();
}
}
$test = new Test('test');
$test->baz(new Test('other'));
?>
http://php.net/manual/en/language.oop5.visibility.php
CLASS CONSTANTS
It is possible to define constant values on a per-class
basis remaining the same and unchangeable.
Constants differ from normal variables in that you don't
use the $ symbol to declare or use them
The value must be a constant expression, not (for
example) a variable, a property, a result of a mathematical
operation, or a function call
CLASS CONSTANTS
(CONT.)
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
echo MyClass::constant . "\n";
?>
STATIC KEYWORD
Declaring class properties or methods as static makes them
accessible without needing an instantiation of the class.
A property declared as static can not be accessed with an
instantiated class object
EXAMPLE
<?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";
CONTRUCTOR
Constructor is the method that will be
implemented when object has been initiated
Commonly, constructor is used to initialize
the object
Use function __construct to create
constructor in PHP
<?php
class Demo
{
function __construct
{
}
}
?>
DESTRUCTOR
Destructor, is method that will be run when object is ended
<?php
class Demo
{
function __destruct
{
}
}
?>
CREATING OBJECTS
•Instantiate classes using new keyword
– $myCart= new ShoppingCart(“Charlie”);
Constructors
– In earlier versions of PHP (< PHP5.3.3) Same as the
name of the class. This no longer holds!
– (PHP5 only) declared as
• public function __construct(…)
Destructors
– Declared as
– public function __destruct()
Latest in PHP5.3.3
<?php
namespace Foo;
class Bar {
public function Bar() {
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method in PHP 5.3.3
}
}
?>
CONSTRUCTORS
A constructor is a function that does initializations when the
class is instantiated
function __construct($intNumber, $strName){
$this->set_intNumber($intNumber);
$this->set_strName($strName);
$this->printInit();//use this method
}
CONSTRUCTORS
Default arguments
function __construct ($strName = “A”,
$intNumber=0) {
$this->set_intNumber($int_Number);
$this->set_strName($str_Name);
}
Instantiating a class without parameters will make use of the
default values
ANOTHER EXAMPLE: CONSTRUCTORS
<?php
class vehicle {
private $strDescription;
function getDescription() {
return $this->strDescription;
}
function setDescription($strDescription) {
$this->strDescription = $strDescription;
}
function __construct ($strDescription) {
$this->strDescription = $strDescription;
}
}
?>
ANOTHER EXAMPLE: CONSTRUCTORS
<?php
require_once("vehicle.php");
$objBike = new vehicle("Bicycle");
echo "<p>Vehicle: " . $objBike->getDescription() . "</p>";
?>
DESTRUCTORS
Called when objects are destroyed – free up memory
e.g.:
function __destruct () {
echo “freeing up memory, destroying this object... <br>”;
}
This sample code above simply informs us that the object is
being destroyed already.
OBJECTS AS VARIABLES
Can be used in arrays
Can be passed to functions
Passed as reference all the time (PHP 5)
e.g.:
function test1($objClass1){
$objClass1->set_intName(“B”);
}
No need to use & in the formal parameter definition. It is
always passed by reference.
ARRAYS AND OBJECTS
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
}
$objSimon = new revisedperson("Simon", "Stobart");
$objLiz = new revisedperson("Liz", "Hall");
$objIan = new revisedperson("Ian", "Walker");
$objBilly = new revisedperson("Billy", "Lee");
$objHayley = new revisedperson("Hayley", "West");
$arrPeople = array($objSimon, $objLiz, $objIan, $objBilly, $objHayley);
foreach($arrPeople as $objThePerson){
echo($objThePerson->display());
}
?>
The function display() is common to all array elements
(elements = objects in this example).
MULTIPLE OBJECT INSTANCES
<?php
$cart1 = new ShoppingCart(“Joe Bloggs”);
$cart1->addItem("10", 1);
$cart2 = new ShoppingCart(“Fred Smith”);
$cart2->addItem("0815", 3);
?>
INHERITANCE
New classes can be defined very similar to existing
ones. All we need to do is specify the differences
between the new class and the existing one.
Data members and methods which are not defined as
being private to a class are automatically accessible
by the new class.
This is known as inheritance and is an extremely
powerful and useful programming tool.
INHERITANCE
There are many benefits of inheritance with PHP, the
most common is simplifying and reducing instances
of redundant code.
INHERITANCE (2)
class hewan
{
protected $jml_kaki;
protected $warna_kulit;
function __construct()
{
}
function berpindah()
{
echo "Saya berpindah";
}
function makan()
{
echo "Saya makan";
}
}
INHERITANCE (3)
class kucing extends hewan }
{
function berpindah() function makan()
{ {
echo "Saya merangkak echo "Saya makan
dengan 4 kaki"; dengan mematuk";
} }
}
}
class burung extends hewan
{ class monyet extends hewan
protected $sayap; {
function berpindah() }
{
echo "Saya terbang";
POLYMORPHISM
A concept where a number of related classes all have a
method, which shares the same name.
class Fish { draw()... //draws a fish... }
class Dog { draw()... //draws a dog... }
class Bird { draw()... //draws a bird... }
We can write a generic code that can operate on any of
these classes, invoking the appropriate draw() method
based on certain conditions.
EXAMPLE: POLYMORPHISM
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
}
$objRectangle = new rectangle(100,50, "rectangle.gif");
$objSquare = new square(100, "square.gif");
$objTriangle = new triangle(50,100, "triangle.gif");
$objEllipse = new ellipse(50,100, "ellipse.gif");
$arrShapes = array ($objRectangle,$objSquare,$objTriangle,$objEllipse);
foreach ($arrShapes as $objShape){
$objShape->display();
$objShape->area();
}
?>
The functions area() and display() are common to all array
elements, but executes a different formula for each type of object.
REMEMBER THESE PHP
CONSTRUCTS?
• require(….)
Includes file specified, terminates on errors
• include(…)
Includes file specified, gives warning on errors
• require_once(….)
Includes file specified only if it has not already been
included, terminates on errors
• include_once(….)
Includes file specified only if it has not already been
included, gives warning on errors
Really useful but would require you to write a long list of include() or require()
statements
at the beginning of each script, one for each class. In PHP5, this is no longer
necessary. You may define an __autoload function!
FUNCTION __AUTOLOAD()
• The function is invoked automatically each time a
class is required but has not been defined.
• We can insert this function into our script:
function __autoload($class_name) {
require_once $class_name . '.php';
}
Note: Class_name = File_name
FUNCTION __AUTOLOAD()
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
} Class definition comes
from another file.
$objSimon = new person;
$objSimon->setDisplayFirstnameSurname(“Napoleon", “Reyes");
$objBike = new vehicle("Bicycle");
echo "<p>Vehicle: " . $objBike->getDescription() . "</p>";
?>
EXCEPTIONS
Like all good OO languages, PHP5 supports the exception
mechanism for trapping and handling “unexpected conditions”
Note: not all exceptions are necessarily errors
Exceptions not supported in PHP4
EXCEPTIONS
Extend the built-in PHP Exception class with your own
exceptions (as in Java)
class MyException extends Exception {
// Redefine the exception so message isn't
optional
public function __construct($message, $code = 0)
{
// some code To generate an exception
// make sure everything is assigned properly
<?php
Throw new MyException("Message to display");
parent::__construct($message, $code); ?>
}
// custom string representation of object
public function __toString() {
return __CLASS__ . ": $this->message\n";
}
public function customFunction() {
echo "A Custom function for this type of
OBJECTS CAN...
Invoke another
Be embedded within another object
Support for:
Inheritance
Scope resolution ( :: operator)
Class abstraction (define a class that does not instantiate, use
“abstract class classname”)
Polymorphism (same function names with different data / behaviour)
'==‘ to check if two object have the same attributes and values
'===‘ to check if two objects are the same instance of the same class
ADVANCED OO IN PHP
PHP5 has rich OO support (similar to the Java model)
Single inheritance (multiple inheritance not allowed)
Abstract classes and methods
Interfaces
PHP is a reflective programming language
Names of functions/classes to be invoked do not have to be hard
wired
See also documentation at www.php.net
REFLECTION-ORIENTED
PROGRAMMING
Normally, instructions are
// without reflection executed and data is
$Foo = new Foo(); processed; however, in some
languages, programs can
$Foo->hello(); also treat instructions as
data and therefore make
reflective modifications.
// with reflection
New in PHP, not properly
$f = new documented yet!
ReflectionClass("Foo");
Program execution could
$m = $f->getMethod("hello"); be modified at run-time.
$m->invoke( $f-
>newInstance() );
http://en.wikipedia.org/wiki/Reflection_(computer_science)
http://nz2.php.net/manual/en/reflectionclass.newinstance.php
BASIC INHERITANCE
class ClassName extends ClassName {
...
} PHP
class Point3D extends Point {
public $z;
public function __construct($x, $y, $z) {
parent::__construct($x, $y);
$this->z = $z;
}
...
} PHP
The given class will inherit all data and behavior from
ClassName
CS380
STATIC METHODS,
FIELDS, AND CONSTANTS
static $name = value; # declaring a static field
const $name = value; # declaring a static constant
PHP
# declaring a static method
public static function name(parameters) {
statements;
} PHP
ClassName::methodName(parameters); # calling a
static method (outside class)
self::methodName(parameters); # calling a static
method (within class) PHP
static fields/methods are shared throughout a class
rather than replicated in every object
CS380
ABSTRACT CLASSES
AND INTERFACES
interface InterfaceName {
public function name(parameters);
public function name(parameters);
...
}
class ClassName implements InterfaceName { ...
PHP
abstract class ClassName {
abstract public function name(parameters);
...
} PHP
CS380
ABSTRACT CLASSES
AND INTERFACES
interfaces are supertypes that specify
method headers without implementations
• cannot be instantiated; cannot contain function
bodies or fields
• enables polymorphism between subtypes without
sharing implementation code
abstract classes are like interfaces, but you
can specify fields, constructors, methods
• also cannot be instantiated; enables polymorphism
with sharing of implementation code
CS380
CONSTRUCTING AND
USING OBJECTS
# construct an object
$name = new ClassName(parameters);
# access an object's field (if the field is public)
$name->fieldName
# call an object's method
$name->methodName(parameters);
PHP
$zip = new ZipArchive();
$zip->open("moviefiles.zip");
$zip->extractTo("images/");
$zip->close(); PHP
the above code unzips a file
test whether a class is installed with class_exists
CS380
OBJECT EXAMPLE:
FETCH FILE FROM WEB
# create an HTTP request to fetch student.php
$req = new HttpRequest("student.php",
HttpRequest::METH_GET);
$params = array("first_name" => $fname, "last_name"
=> $lname);
$req->addPostFields($params);
# send request and examine result
$req->send();
$http_result_code = $req->getResponseCode(); # 200
means OK
print "$http_result_code\n";
print $req->getResponseBody();
PHP
PHP's HttpRequest object can fetch a document from
the web
CS380
EXERCISE: TUGAS
TUGAS (CONT.)
Class product :
name
price
discount
Class CDMusic :
artist
Genre
Class CDRack
capacity
model
TUGAS (CONT.)
CDMusic
Menuruni name, price dan discount dari Product
Price = price + 10%
Ada penambahan 5% pada discount
CDRack
Menuruni name, price dan discount dari Product
Price = price + 15%
Tidak ada penambahan discount
Buatlah code dalam PHP, serta simulasi untuk kasus
tersebut!