Monday, September 13, 2010

PHP Class functions

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()
Each of these is shown here beginning with the get_declared_interfaces().

get_declared_interfaces()

This helper function provides an array of all the available declared interfaces.

interface 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 faxprinter{
  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.'';
        }
?>
The above code should produce a list such as this:

  • 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
From the list above you can see the SPL interfaces available and at the bottom is our fax and printer interfaces. The printerfax is not listed as it is not an interface, rather it is an implentation of an interface.

Other functions

Here we will see three helper functions for our classes
  • get_class()
  • class_exists()
  • get_declared_classes

/*** 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';
echo 
class_exists("printer").'';
echo 
'Declared classes are: ';
foreach(
get_declared_classes() as $key=>$classname)
    {
    echo 
$key.' -> '.$classname.'';
    }
?>
The little snippet above will produce over one hundred available classes, shortened here for the sake of sanity, such as these below. Note our fax and printer classes at the bottom of the list.
  • $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.


/*** 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;
?>
As you can see, this is quite cumbersome. The solution to this sort of mess is __autoload(). The __autoload() function will internally search out the class and load its definition. So the above block of code could be reduced to this.

/*** 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;
?>
Now we can load up as many class definitions as we like because they will be autoloaded when we try to use a class that has not been defined. This can save much coding and much searching for code. It is important to remember the naming convention of your classes and class files. Each class file should be named the same as the class definition itself. eg: a class definition file named fax would have the filename fax.class.php
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.

/*** code here ***/?>

Overloading

Comes a time in every programmers life when...hmm
Overloading in PHP has caused much confusion for no real reason. PHP Overloading can be broken downinto two basic components
  • Method overloading
  • Property overloading
Simply put, Method Overloading is achieved by a special function named __call(). It is available as a sort of method wildcard for calls to undefined methods within a class. This special function is only called when the original method name does not exist. The __call() will only work when the class method you are trying to access does not exist. Lets take it for a spin..

class 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();?>
Of course the above snippet of code will produce an error such as
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.


class my_class{
 public function 
foo() {
    return 
"This is the foo function";
 }
  
/*** __call() method with two args ***/
  
public function __call($method$arg){
   echo 
$method.'';
   
print_r($arg);
 }
/*** end of class ***/

/*** create a new class object ***/
$obj = new my_class;/*** call a non-existant method ***/$obj->bar("arg1""arg2");?>
The above code will print the following
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.


class 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($method03));
 
$property strtolower(substr($method3));

 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() . '';
echo 
'Price: ' $obj->getPrice() . '';
$obj->setItem('CD');$obj->setPrice(25);

echo 
'Item: ' $obj->getItem() . '';
echo 
'Price: ' $obj->getPrice() . '';?>
The second part of overloading refers to properties and the ability to be able to dynamically get and set object properties. The __get() function is called when reading the value of an undefined property, and __set() is called when trying to change that properties value. I hope this is clear as it can get a little confusing... Lets see how it works by example.


 
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 result from above will be:
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 ....



 
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.'';
     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;
?>
From the above code we get the result
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;
?>
The above snippit would output
An Error has occured!
To define a class constant we use the const keyword.


class my_class {
 
/*** define a class constant ***/
 
const _ERROR_MSG 'An Error has occured!';

public function 
show(){
 echo 
self::_ERROR_MSG;
}

/*** end of class ***/?>
There are now three ways the class constant can be access from this example.
/*** 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();?>
Each of the above methods would output the same line
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.

No comments:

Post a Comment