OOP was first invented for the purpose of physical modelling in the Simula-67.
What is an Object
Simply put, an object is a bunch of variables and functions all lumped into a single entity. The object can then be called rather than calling the variables or functions themselves. Within an object there are methods and properties. The methods are functions that manipulate data withing the object. The properties are variables that hold information about the object.What is a Class
A class is the blueprint for your object. The class contains the methods and properties, or the charactaristics of the object. It defines the object. Lets just start with some examples to see how it all pieces together. We will use a vehicle as our object. All vehicles share similar charactaristics, eg: number of doors, they are painted some color, they each have a price. All vehicles do similar things also, drive, turn left, turn right, stop etc. These can be described as functions, or in OOP parlance, methods. So, the class holds the definition, and the object holds the value. You declare class in PHP by using the class keyword.
<?phpclass vehicle{/*** define public properties ***/
/*** the color of the vehicle ***/public $color;/*** the number of doors ***/public $num_doors;/*** the price of the vehicle ***/public $price;/*** the shape of the vehicle ***/public $shape;/*** the brand of vehicle ***/public $brand;/*** the constructor ***/public function __construct(){
echo 'About this Vehicle.<br />';
}/*** define some public methods ***/
/*** a method to show the vehicle price ***/public function showPrice(){
echo 'This vehicle costs '.$this->price.'.<br />';
}/*** a method to show the number of doors ***/public function numDoors(){
echo 'This vehicle has '.$this->num_doors.' doors.<br />';
}/*** method to drive the vehicle ***/public function drive(){
echo 'VRRROOOOOOM!!!';
}
} /*** end of class ***/?>
<?php/*** create a new vehicle object ***/$vehicle = new vehicle;/*** the brand of vehicle ***/$vehicle->brand = 'Porsche';/*** the shape of vehicle ***/$vehicle->shape = 'Coupe';/*** the color of the vehicle ***/$vehicle->color = 'Red';/*** number of doors ***/$vehicle->num_doors = 2;/*** cost of the vehicle ***/$vehicle->price = 100000;/*** call the showPrice method ***/$vehicle->showPrice();/*** call the numDoors method ***/$vehicle->numDoors();/*** drive the vehicle ***/$vehicle->drive();?>
About this vehicle.
This vehicle costs 100000.
This vehicle has 2 doors.
Lets step through the class definition first to see what its all about.
We began the class with the class keyword. This tells PHP that what follows is a class definition.
<?phpclass vehicle{?>
<?php/*** the color of the vehicle ***/public $color;/*** the number of doors ***/public $num_doors;/*** the price of the vehicle ***/public $price;/*** the shape of the vehicle ***/public $shape;/*** the brand of vehicle ***/public $brand;?>
<?php/*** the constructor ***/public function __construct(){
echo 'About this vehicle.<br />';
}?>
<?php/*** a method to show the vehicle price ***/public function showPrice(){
echo 'This vehicle costs '.$this->price.'.<br />';
}/*** a method to show the number of doors ***/public function numDoors(){
echo 'This vehicle has '.$this->num_doors.' doors.<br />';
}/*** method to drive the vehicle ***/public function drive(){
echo 'VRRROOOOOOM';
}?>
Following on from the class definition we see our userland code. This is the code we use to instantiate (create) a new instance, or new object, of our vehicle class. As mentioned earlier we do this with the use of the new keyword.
<?php/*** create a new vehicle object ***/$vehicle = new vehicle;?>
<?php/*** the brand of vehicle ***/$vehicle->brand = 'Porsche';/*** the shape of vehicle ***/$vehicle->shape = 'Coupe';/*** the color of the vehicle ***/$vehicle->color = 'Red';/*** number of doors ***/$vehicle->num_doors = 2;?>
<?php/*** call the showPrice method ***/$vehicle->showPrice();/*** call the numDoors method ***/$vehicle->numDoors();/*** drive the vehicle ***/$vehicle->drive();?>
Commenting Code
In the previous sections you have seen comments for almost every line of code. This is a good practice, although some may find it excessive, as it may not be you who has to edit the code next time. OOP can get very abstracted and if you are not careful it is easy to lose site of your programmatical work flow. Most methods within a class will return a value, rather than echo a line of HTML code. A class method may also take one, or several, arguements. It is good practice to show what these arguements are and there types. An example follows below.
<?php
/**
* adds an array of numbers and returns the value
*
* @param array $numbers An array of numbers to add
*
* @access private
*
* @return int Returns sum of numbers
*
*/
private function sum_of_numbers($numbers){
/*** return the sum of the $numbers array ***/
return array_sum($numbers);
}?>
Inheritance (Extending a class)
Probably the greatest feature of the PHP OOP model is Inheritence. Inheritence is the ability of php to extend classes (child classes) that inherit the charactaristics of the parent class. The resulting object of an extend class has all the charactaristics of the parent class, plus whatever is in the new child, or extended class. In this instance we will extend the vehicle class and add a motorcyle. A motorcycle is still a vehicle and shares many of the same attributes such as price, drive etc. But a motorcycle has some unique features that a car does not.Rather than type out the whole of the vehicle class definition again, we will save it in a file of its own called vehicle.class.php. It is important here to note the naming convention here as it will be important later in this tutorial. Lets see how it works.
<?php/*** include the vehicle class definition ***/include('vehicle.class.php');
class motorcycle extends vehicle{/*** the number of side cars ***/private $num_sidecars;
private $handlebars;/**
*
* set the type of handlebars
*
* @access public
*
* @param string
*
* @return string
*
**/public function setHandlebars($handlebarType){
$this->handlebars=$handlebarType;
}/**
*
* Set number of side cars
*
* @access public
*
* @param int
*
* @return int
*
**/public function setSidecar($numSidecars){
$this->numSidecars = $numSidecars;
}
/**
*
* Show the numbers of sidecars
*
* @return string
*
**/public function showSideCar(){
echo 'This motorcyle has '. $this->numSidecars.' sidecar<br />';
}
} /*** end of class ***/
/*** our userland code ***/
/*** create a new vehicle object ***/$vehicle = new motorcycle;/*** the brand of vehicle ***/$vehicle->brand = 'Harley Davidson';/*** the shape of vehicle ***/$vehicle->shape = 'Sportster';/*** the color of the vehicle ***/$vehicle->color = 'Black';/*** number of doors ***/$vehicle->num_doors = 0;/*** cost of the vehicle ***/$vehicle->price = 25000;/*** type of handle bars ***/$vehicle->setHandlebars('Ape Hangers');/*** set the sidecar ***/$vehicle->setSidecar(1);/*** show the vehicle brand and type ***/echo $vehicle->brand.': '.$vehicle->shape.'<br />';
/*** call the showPrice method ***/$vehicle->showPrice();/*** show the sidecars ***/$vehicle->showSideCar();/*** drive the vehicle ***/$vehicle->drive();?>
If you run the above code with out including the parent class, you will get a Fatal Error like this:
Fatal error: Class 'vehicle' not found in /www/oop.php on line 3
You MUST include the class definition on *every page* when you store an object
This means when you use an object or wish to extend from it. you must include the class file. Either as code, or most commonly, with an include() statement.Visibility (public, private, protected)
The visibility of class members, (properties, methods), relates to how that member may be manipulated within, or from outside the class. Three levels of visibilty exist for class members.- public
- private
- protected
Public class members (properties and methods) are available through-out the script and may be accessed from outside the class as we demonstrated in our car class. Lets create a simple new class to demonstrate.
<?phpclass mathematics{/*** a number ***/public $num;/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
}/*** end of class ***/
/*** Instantiate a new class instance ***/$math = new mathematics;/*** set the value of the number ***/$math->num = 2;/*** call the addTwo method ***/echo $math->addTwo();?>
<?phpclass mathematics{/*** a number ***/private $num;/**
*
* Set the value of $num
*
* @access public
*
* @param $num The number to set
*
* @return int
*
**/public function setNum($num){
$this->num = $num;
}/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
}/*** end of class ***/
/*** Instantiate a new class instance ***/$math = new mathematics;/*** set the value of the number ***/$math->setNum(2);/*** call the addTwo method ***/echo $math->addTwo();?>
?>
Fatal error: Cannot access private property mathematics::$num in /www/mathematics.class.php on line 43
Even if you were to try to access the private $num property from a child class it would fail. This is because private methods and properties in a parent class are not visible to child classes and cannot be accessed. To access a parent method or property from a child class you need to use the protected keyword. Like the private keyword, protetected methods and properties are available only to the class that created them. But unlike private, protected methods and properties are visible from a parent class. Lets see how this works.
<?phpclass mathematics{/*** a number ***/protected $num;/**
*
* Set the value of $num
*
* @access public
*
* @param $num The number to set
*
* @return int
*
**/public function setNum($num){
$this->num = $num;
}/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
}/*** end of class ***/class divide extends mathematics{/**
*
* Divide a number by two
*
* @access public
*
* @return int
*
**/public function divideByTwo(){
/*** divide number by two ***/
$new_num = $this->num/2;
/*** return the new number and round to 2 decimal places ***/
return round($new_num, 2);
}
} /*** end of class ***/
/*** Instantiate a new class instance ***/$math = new divide;/*** set the value of the number ***/$math->setNum(14);
echo $math->divideByTwo();?>
Final
As we saw in the previous section there are ways to protect your code from being used in an improper manner. Another way of protecting yourself is the Final keyword. Any method or class that is declared as Final cannot be overridden or inherited by another class. Lets put it to the test.
<?phpfinal class mathematics{
} /*** end of class ***/class divide extends mathematics{
}?>
Fatal error: Class divide may not inherit from final class (mathematics) in /www/final.php on line 8
This can protect us from those who wish to use our code for a purpose other than that for which it was intended.
Abstract Classes
An abstract class is a class that cannot be instantiated on its own. You cannot create a new object from it. To see this lets make a basic class.
<?phpabstract class mathematics{/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
} /*** end of class ***/
/*** try to create new object from the mathematics class ***/$math = new mathematics
?>
Fatal error: Cannot instantiate abstract class mathematics in /www/abstract.php on line 23.
As you can see, this is not allowed. Also if you declare any class method to be abstract, you must also declare the class itself as abstract too. So, whats the point you ask? Well, you can inherit from an abstract class. Any class that extends an abstract parent class must create an interface of the parent abstract methods. If this is not done a fatal error is generated. This ensures that the implementation is correct.
<?phpabstract class mathematics{/*** child class must define these methods ***/abstract protected function getMessage();
abstract protected function addTwo($num1);/**
*
* method common to both classes
*
**/public function showMessage() {
echo $this->getMessage();
}
} /*** end of class ***/class myMath extends mathematics{/**
*
* Prefix to the answer
*
* @return string
*
**/protected function getMessage(){
return "The anwser is: ";
}/**
*
* add two to a number
*
* @access public
*
* @param $num1 A number to be added to
*
* @return int
*
**/public function addTwo($num1) {
return $num1+2;
}
} /*** end of class ***/
/*** a new instance of myMath ***/$myMath = new myMath;/*** show the message ***/$myMath->showMessage();/*** do the math ***/echo $myMath->addTwo(4);?>
Static Methods and Properties
The use of the static keyword allows class members (methods and properties) to be used without needing to instantiate a new instance of the class. The static declaratin must come after the visibility declaration, eg:public static myClass{
Because there is no object created when using a static call, the keyword $this and the arrow operator, -> are not available. Static variables belong to the class itself and not to any object of that class. To access withing the class itself you need to use the self keyword along with the :: scope resolution operator. Lets whip up a quick example of using static.
<?php/*** a simple class ***/class myClass{/*** a static variable ***/ static $foo;
}/** give the static variable a value ***/myClass::$foo = 'Bar';/*** echo the static variable ***/echo (myClass::$foo ).?>
Bar
This is rather basic as an example, so lets use something practical. Static properties are often used as counters. Here we will use a basic counter class.
<?phpclass counter{/*** our count variable ***/private static $count = 0;/**
* Constructor, duh
**/function __construct() {
self::$count++;
}/**
*
* get the current count
*
* @access public
*
* @return int
*
**/public static function getCount() {
return self::$count;
}
} /*** end of class ***/
/*** create a new instance ***/$count = new counter(); /*** get the count ***/echo counter::getCount() . '<br />';/*** create another instance ***/$next = new counter(); /*** echo the new count ***/echo counter::getCount().'<br />'; /*** and a third instance ***/$third = new counter;
echo counter::getCount().'<br />';?>
Interfaces
Interfaces in PHP allow you to define a common structure for your classes. An interface cannot be instantiated on its own. One of the goals of OOP is re-use of code. Interfaces make this a much easier process. The interface methods have no internal logic, they are simply a "mapping" or constraint of what the class, or classes, should implement. Here we will demonstrate how this works using our vehicle class from earlier, with the addition of a stop() function.
<?phpclass vehicle implements testdrive{/*** define public properties ***/
/*** the color of the vehicle ***/public $color;/*** the number of doors ***/public $num_doors;/*** the price of the vehicle ***/public $price;/*** the shape of the vehicle ***/public $shape;/*** the brand of vehicle ***/public $brand;/*** the constructor ***/public function __construct(){
echo 'About this Vehicle.<br />';
}/*** define some public methods ***/
/*** a method to show the vehicle price ***/public function showPrice(){
echo 'This vehicle costs '.$this->price.'.<br />';
}/*** a method to show the number of doors ***/public function numDoors(){
echo 'This vehicle has '.$this->num_doors.' doors.<br />';
}/*** method to drive the vehicle ***/public function drive(){
echo 'VRRROOOOOOM!!!';
}/**
* a method to stop the car
*
* @access public
*
**/public function stop(){
echo 'SSSCCRRREEEEEECCHH!!!<br />';
}
} /*** end of class ***/
/*** declare our interface ***/interface testdrive{/*** some functions that must be implemented ***/function drive();
function stop();
}/*** an new vehicle object ***/$object = new vehicle;/*** call some methods ***/$object->drive();$object->stop();?>
In the real world interfaces provide us with the tools harness parts of multiple classes. Consider this scenario. If we had two classes, one for a fax and the other for a printer. Each has seperate uses and could be described like this:
<?phpclass fax{
public function dial();
public function send();
public function recieve();
}
class printer{
public function printBlack();
public function printColor();
public function printDraft();
}?>
<?phpclass fax{
public function dial();
public function send();
public function recieve();
}
class printer extends fax{
public function printBlack();
public function printColor();
public function printDraft();
public function kick();
}
class printerFax extends fax{
}$object = new printerFax;?>
To counter this problem an interface can be used to tell the classes what functions (methods) are required. Lets look at the design.
<?phpinterface fax{
public function dial();
public function send();
public function recieve();
}
interface printer{
public function printBlack();
public function printColor();
public function printDraft();
public function kick();
}
class printerFax implements fax, printer{
public function dial(){ }
public function send(){ }
public function recieve(){ }
public function printBlack(){ }
public function printColor(){ }
public function printDraft(){ }
public function kick(){ }
}
$object = new printerFax;?>
public function kick(){ }
and run it again. What you should now get is an error such as:
Fatal error: Class printerFax contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (printer::kick) in /www/oop.php on line 22
With the kick() function removed from our implementation, we have essentially broken the contract that says we will implement every function (method) specified in the interface. We can gather these functions fractionally from multiple classes, but we MUST have them all or we will get errors such as the one above.
Interfaces play a major role in with SPL and it is recommend you implement the interfaces from SPL and not just the class methods.
PHP Class functions
PHP has available several class functions to help you through the OOP mine field.- get_declared_interfaces()
- class_exists()
- get_class()
- get_declared_classes()
get_declared_interfaces()
This helper function provides an array of all the available declared interfaces.
<?phpinterface fax{
public function dial();
public function send();
public function recieve();
}
interface printer{
public function printBlack();
public function printColor();
public function printDraft();
public function kick();
}/*** our interface implementation ***/class printerFax implements fax, printer{
public function dial(){ }
public function send(){ }
public function recieve(){ }
public function printBlack(){ }
public function printColor(){ }
public function printDraft(){ }
public function kick(){ }
}
/*** create and printerfax object ***/
$object = new printerFax;
/*** get the declared interfaces ***/
foreach(get_declared_interfaces() as $key=>$interface)
{
echo $key.' => '.$interface.'<br />';
}?>
- 0 => Traversable
- 1 => IteratorAggregate
- 2 => Iterator
- 3 => ArrayAccess
- 4 => Serializable
- 5 => RecursiveIterator
- 6 => OuterIterator
- 7 => SeekableIterator
- 8 => Countable
- 9 => SplObserver
- 10 => SplSubject
- 11 => Reflector
- 12 => fax
- 13 => printer
Other functions
Here we will see three helper functions for our classes- get_class()
- class_exists()
- get_declared_classes
<?php/*** a pretend class ***/class fax{
public function dial(){ }
public function send(){ }
public function recieve(){ }
}/*** another pretend class ***/class printer{
public function printBlack(){ }
public function printColor(){ }
public function printDraft(){ }
public function kick(){ }
}/*** create an instance of the fax class ***/$foo = new fax;/*** create an instance of the printer class ***/$bar = new printer;
echo '$foo is from the ' get_class($foo).' class<br />';
echo class_exists("printer").'<br />';
echo 'Declared classes are:<br /> ';
foreach(get_declared_classes() as $key=>$classname)
{
echo $key.' -> '.$classname.'<br />';
}?>
- $foo is from the fax class
- 1
- 0 -> stdClass
- 1 -> Exception
- ---8<--- snip ---
- 106 -> fax
- 107 -> printer
Autoload
Earlier in this tutorial we stated that the class definition must be included in every call to an object. This is commonly achieved with the include() or require() functions such as below.
<?php/*** include our class definitions ***/include('classes/vehicle.class.php');
include('classes/motorcycle.class.php');
include('classes/printer.class.php');
include('classes/printer.class.php');/*** instantiate a new vehicle class object ***/$vehicle = new vehicle;
*** instantiate a new motorcycle class object ***/$bike = new motorcycle;
*** instantiate a new printer class object ***/$printer = new printer;
*** instantiate a new fax class object ***/$fax = new fax;?>
<?php/*** Autoload class files ***/function __autoload($class){
require('classes/' . strtolower($class) . '.class.php');
}/*** instantiate a new vehicle class object ***/$vehicle = new vehicle;/*** instantiate a new motorcycle class object ***/$bike = new motorcycle;/*** instantiate a new printer class object ***/$printer = new printer;/*** instantiate a new fax class object ***/$fax = new fax;?>
The use of the strtolower() function assures compatibility of naming conventions as windows machines fail to be case sensitive for filenames.
Serializing Objects
We have seen a lot of code above for the use of objects and how they can save us time (and $$$) by re-using them. But what if we needed to somehow store an object for later retrieval, perhaps in a database or in a session variable? PHP has given us the serialize() function to make this rather effortless. There are some limitations, but this can be a very useful tool for applications. Lets see how it performs with a little code.
<?php/*** code here ***/?>
Overloading
Comes a time in every programmers life when...hmmOverloading in PHP has caused much confusion for no real reason. PHP Overloading can be broken downinto two basic components
- Method overloading
- Property overloading
<?phpclass my_class{
public function foo() {
return "This is the foo function";
}
} /*** end of class ***/
/*** create a new class object ***/$obj = new my_class;/*** call a non-existant method ***/$obj->bar();?>
Fatal error: Call to undefined method my_class::bar() in /www/overload.php on line 12
because we have called the bar() class method that does not exist. Enter __call(). With the __call() function in place, PHP will try to create the function and you have any code within the _call() method that you like. The __call() method takes two arguements, the method name, and the arguements. Your call to the undefined method may have many arguements and these are returned in an array. Lets put it to the test with two args.
<?phpclass my_class{
public function foo() {
return "This is the foo function";
}
/*** __call() method with two args ***/
public function __call($method, $arg){
echo $method.'<br />';
print_r($arg);
}
} /*** end of class ***/
/*** create a new class object ***/$obj = new my_class;/*** call a non-existant method ***/$obj->bar("arg1", "arg2");?>
bar
Array ( [0] => arg1 [1] => arg2 )
The __call() method has returned the method name that we called along with the array of args passed to it.
Lets now look at we can dynimically manipulate or overload our data.
<?phpclass readyGetSet {/*** declare $item ***/private $item = 'Skate Board';/*** declare the price ***/private $price = 100;/*** our call function ***/function __call($method, $arguments){/*** set property and prefix ***/
$prefix = strtolower(substr($method, 0, 3));
$property = strtolower(substr($method, 3));
if (empty($prefix) || empty($property))
{
return;
}
if ($prefix == 'get' && isset($this->$property))
{
return $this->$property;
}
if ($prefix == 'set')
{
$this->$property = $arguments[0];
}
}
}$obj = new readyGetSet;
echo 'Item: ' . $obj->getItem() . '<br />';
echo 'Price: ' . $obj->getPrice() . '<br />';$obj->setItem('CD');$obj->setPrice(25);
echo 'Item: ' . $obj->getItem() . '<br />';
echo 'Price: ' . $obj->getPrice() . '<br />';?>
<?php
class candy{
/*** declare a property ***/
public $type='chocolate';
/*** a normal method ***/
public function wrap(){
echo 'Its a wrap';
}
/*** our __set() function ***/
public function __set($index, $value){
echo 'The value of '.$index.' is '.$value;
}
} /*** end of class ***/
/*** a new candy object ***/$candy = new candy;/*** set a non existant property ***/$candy->bar = 'Blue Smarties';?>
The value of bar is Blue Smarties
Lets see what we have done. We have described a class named candy which contains a public property named $type. It has a simple method and our __set() method. After the class our user code creates a new instance of the candy class. Then we try to set a variable that does not exist in the class. Here the __set method takes control and assigns it for us. We then see in our __set method that it echoes the name of the variable, plus its intended value. The __set() method takes two arguements, the name of the non existant variable, and its intended value.
The __get() method ....
<?php
class candy{
/*** declare a property ***/
public $type='chocolate';
public $choctype = array('milk'=>0, 'dark'=>1, 'plain'=>2);
/*** a normal method ***/
public function wrap(){
echo 'Its a wrap';
}
/*** our __set() function ***/
public function __get($index){
echo 'Retrieving element of $choctype property with index of '.$index.'<br />';
return $this->choctype[$index];
}
} /*** end of class ***/
/*** a new candy object ***/$candy = new candy;/*** set a non existant property ***/
echo 'The value of the following element property is '.$candy->milk;?>
Retrieving element of $choctype property with index of milk
The value of the following element property is 0
Class Constants
You have more than likely seen the use standard constants in PHP. To define a standard constant we use this code:
/*** define an error message ***/
define('_ERROR_MSG', 'An Error has occured!');
/*** echo the constant ***/
echo _ERROR_MSG;
?>
An Error has occured!
To define a class constant we use the const keyword.
<?phpclass my_class {
/*** define a class constant ***/
const _ERROR_MSG = 'An Error has occured!';
public function show(){
echo self::_ERROR_MSG;
}
} /*** end of class ***/?>
<?php/*** static call to constant ***/echo my_class::_ERROR_MSG;/*** instantiate a class object ***/$my_class = new my_class;/*** can run the show() method ***/$my_class->show();/*** static call to the show method() ***/my_class::show();?>
An Error has occured!
A class constant, like standard constants, must be exactly as the name suggests, a constant value. It cannot be a variable or the result of a function or method.
Credits
This concludes our little insight into PHP OOP. If you have anything you would like to see here just contact us and we will do our best to help.Source: phpro.org
Post a Comment
Silahkan anda tulis komentar di bawah ini !