Phone: 415-963-0926 | 415-963-0927
Log in Currency: £ $
Basket: 0 domains, no hosting yet
 

PHP programming tutorial

10. Classes

A class, at its simplest is a way of grouping functions and their associated variables into a smaller scope than the global scope. In big projects, pollution of the global scope can become a problem because you can easily reuse a variable name, forgetting that you've used it before and get unintended side-effects in your code from the fact that the variable has already been assigned. A way is neeeded of localising variable scope but still sharing scope between functions within the same localisation. Classes allow you to write modular, easy-to-reuse chunks of code. The bigger the project becomes, the more obvious the benefit of using objects, such that when you know a project is going to get big, it makes sense to start using objects right from the very beginning so that you don't end up rewriting code later.

So that's all a class is really - a grouping of functions (in a class they're normally called methods) and variables (often called properties or members). A class also has a name, which must not be one of PHP's reserved words. A class may also have instances and this is where a lot of the real power of object orientation comes in, but we're going to first look at static classes - that is, classes without instances. This is the simplest way you can use a class which is why we're looking at it first. Here's a very basic example:

<?php
    
class Counter {
        static 
$a 0;
        function 
incrementA() {
            
self::$a++;
        }
        function 
returnA() {
            return 
self::$a;
        }
    }
    
Counter::incrementA();
    
Counter::incrementA();
    echo 
Counter::returnA();    
?>

You can test this example here - you can see we've got all the code associated with the counter in a class called Counter, including a static member $a. This is a variable that is available within the scope of each of the class's methods and always keeps its value. If you create an instance of the class, static variables are shared between all instances of the same type of class.

We have introduced a new operator - the scope resolution operator (::) - sometimes called Paamayim Nekudotayim - this operator allows you to access the static members of a class and call its methods statically without having to create an instance of the class. From within the class itself, the special keyword 'self' refers to the static members of the class.

You can also access a class's variable members directly as in this example:

<?php
    
class Counter {
        static 
$a 0;
        function 
incrementA() { 
            
self::$a++;
        }
    }
    
Counter::incrementA();
    echo 
Counter::$a;
?>

Test this example here. You can see that you can access the static variable $a directly from outside of the class as long as you use the class name followed by the scope resolution operator followed by the variable name. In other words, member variables are public by default.

If you want to prevent a member variable from being accessible from outside the class like this, you can prefix it with the 'private' keyword - this stops the variable from being accessible from outside the class. This example shows what happens if you try to access a private static from outside the class it's defined in:

<?php
    
class Counter {
        private static 
$a 0;
        function 
incrementA() { 
            
self::$a++;
        }
    }
    
Counter::incrementA();    // This line is okay
    
echo Counter::$a;         // This line causes an error
?>

If you run this code it will generate an error; "Cannot access private property", however, you can write an accessor function that allows you to get the value of a private variable - here's an example of an accessor function allowing you to read the value of $a from the Counter class even though it's private:

<?php
    
class Counter {
        private static 
$a 0;
        function 
incrementA() {
            
self::$a++;
        }
        function 
returnA() {
            return 
self::$a;
        }
    }
    
Counter::incrementA();
    
Counter::incrementA();
    
Counter::incrementA();
    echo 
Counter::returnA();    
?>

See it working here. Like variables, functions are public by default too - you can see in the previous examples that we're calling the functions inside our class from outside of the class. You can also have private functions which can only be accessed from within the class, for example this program will fail with a "Call to private method" error:

<?php
    
class Counter {
        static 
$a 0;
        private function 
incrementA() { 
            
self::$a++;
        }
    }
    
Counter::incrementA();    // This line causes an error
?>

This program fails because you cannot call a private function from outside the class, you can see it failing here. You can always access private functions from within the class though, so if you write a wrapper function like this, the program will work again:

<?php
    
class Counter {
        static 
$a 0;
        private function 
incrementA() { 
            
self::$a++;
        }
        function 
doIncrement() {
            
self::incrementA();
        }
    }
    
Counter::doIncrement();
    echo 
Counter::$a;
?>

See it working here. This example works because doIncrement() is a public function which calls the private incrementA() function from within the scope of the class.

So far we've only looked at static classes. But what happens when you instantiate a class?

<?php
    
class Person {
        public 
$firstname;
        public 
$lastname;
        function 
getFullname() {
            return 
$this->firstname ' ' $this->lastname;
        }
    }
    
$bob = new Person();
    
$alice = new Person();
    
$bob->firstname 'Bob';
    
$bob->lastname 'Jones';
    
$alice->firstname 'Alice';
    
$alice->lastname 'Walker';
    echo 
'Hello ' $bob->getFullname() . ' and ' $alice->getFullname();
?>

Test this example here. In this example we're defining a class called Person, and then creating two instances of that class and assigning them to the variables $bob and $alice. We're then setting the two public properties for each of the instances individually, and then we're executing the getFullname() function on each of the objects.

This is one of the great powers of object orientated programming - that you can use objects to represent real world things on which a common set of operations must be performed.

If we add a special function called __construct, this function will be called when a new instance of the class is created. We can have arguments to the __construct function to allow certain parameters on the object to be set at the time it's created. Here you can see an example using the __construct function:

<?php
    
class Person {
        public 
$firstname;
        public 
$lastname;
        function 
__construct ($firstname ''$lastname '') {
            
$this->firstname $firstname;
            
$this->lastname $lastname;
        }
        function 
getFullname() {
            return 
$this->firstname ' ' $this->lastname;
        }
    }
    
$bob = new Person('Bob''Jones');
    
$alice = new Person();
    
$alice->firstname 'Alice';
    
$alice->lastname 'Walker';
    echo 
'Hello ' $bob->getFullname() . ' and ' $alice->getFullname();
?>

Test this example here. You can see that this example has a constructor with two arguments, both of which have default values. This allows the object to still be created if no arguments are given to the constructor. We then create two instances of the Person object - one by passing the name attribute values as arguments to the constructor ($bob), and the second one by setting them manually as we did in the previous example ($alice).

Here's a simple example showing the fact that static variables exist across all instances - you can use this to implement an instance counter like this:

<?php
    
class Person {
        private static 
$instanceCounter 0;
        private 
$instance;
        private 
$firstname;
        private 
$lastname;
        function 
__construct ($firstname ''$lastname '') {
            
$this->firstname $firstname;
            
$this->lastname $lastname;
            
$this->instance self::$instanceCounter++;
        }
        function 
getNumberedFullname() {
            return 
$this->instance ' ' $this->firstname ' ' $this->lastname;
        }
    }
    
$bob = new Person('Bob''Jones');
    
$alice = new Person('Alice''Walker');
    
$fred = new Person('Fred''Smith');
    echo 
$bob->getNumberedFullname() . "<br />\n";
    echo 
$alice->getNumberedFullname() . "<br />\n";
    echo 
$fred->getNumberedFullname() . "<br />\n";
?>

Test the instance counter example here. This class has a static variable $instanceCounter which is shared across all instances - the instance counter works by saving this value into the instance's own normal instance variable as part of the constructor. The $instanceCounter static variable is also incremented as part of the constructor function.

Here's an example with a static function:

<?php
    
class Person {
        private static 
$instanceCounter 0;
        private 
$instance;
        private 
$firstname;
        private 
$lastname;
        function 
__construct ($firstname ''$lastname '') {
            
$this->firstname $firstname;
            
$this->lastname $lastname;
            
$this->instance self::$instanceCounter++;
        }
        function 
getNumberedFullname() {
            return 
$this->instance ' ' $this->firstname ' ' $this->lastname;
        }
        static function 
getInstanceCounter() {
            return 
self::$instanceCounter;
        }
    }
    
$bob = new Person('Bob''Jones');
    
$alice = new Person('Alice''Walker');
    
$fred = new Person('Fred''Smith');
    echo 
Person::getInstanceCounter();
?>

Test ths static function example.

You can also create a class that inherits from another class - to do this you use the 'extends' keyword after the class name. Child classes inherit the functions and members from the parent class - they allow you to create a class heirarchy. Here's an example with an extension class called 'Staff' which inherits from its parent class 'Person':

<?php
    
class Person {
        static 
$instanceCounter 0;
        public 
$instance;
        public 
$firstname;
        public 
$lastname;
        function 
__construct ($firstname ''$lastname '') {
            
$this->firstname $firstname;
            
$this->lastname $lastname;
            
$this->instance self::$instanceCounter++;
        }
        function 
getNumberedFullname() {
            return 
$this->instance ' ' $this->firstname ' ' $this->lastname;
        }
        static function 
getInstanceCounter() {
            return 
self::$instanceCounter;
        }
    }
    class 
Staff extends Person {
        private 
$jobtitle;
        private 
$salary;
        function 
__construct ($firstname ''$lastname ''
                              
$jobtitle ''$salary '') { 
            
$this->firstname $firstname;
            
$this->lastname $lastname;
            
$this->jobtitle $jobtitle;
            
$this->salary $salary;
            
$this->instance parent::$instanceCounter++;
        }
    }
    
$bob = new Person('Bob''Jones');
    
$alice = new Person('Alice''Walker');
    
$fred = new Staff('Fred''Smith''Sales Manager''80000');
    
$joe = new Staff('Joe''Bloggs''Operations Manager''90000');
    echo 
$bob->getNumberedFullname() . "<br />\n";
    echo 
$alice->getNumberedFullname() . "<br />\n";
    echo 
$fred->getNumberedFullname() . "<br />\n";
    echo 
$joe->getNumberedFullname() . "<br />\n";
?>

Test the extension class example. You can see that an extension class has its own __construct function and the parent's constructor is not called unless you call it speifically with parent::_construct().

In an extension class, you can override methods in the parent class with new definitions so, we can adapt the above program to instead call a getInfo() function on the instances - then if the object is of type Person, the getInfo() function in the Person class is executed, but if the object is of type Staff, the extension class's version of the function is used, here's an example:

<?php
    
class Person {
        static 
$instanceCounter 0;
        public 
$instance;
        public 
$firstname;
        public 
$lastname;
        function 
__construct ($firstname ''$lastname '') {
            
$this->firstname $firstname;
            
$this->lastname $lastname;
            
$this->instance self::$instanceCounter++;
        }
        function 
getInfo() {
            return 
$this->instance ' ' $this->firstname ' ' $this->lastname;
        }
        static function 
getInstanceCounter() {
            return 
self::$instanceCounter;
        }
    }
    class 
Staff extends Person {
        private 
$jobtitle;
        private 
$salary;
        function 
__construct ($firstname ''$lastname ''
                              
$jobtitle ''$salary '') { 
            
$this->firstname $firstname;
            
$this->lastname $lastname;
            
$this->jobtitle $jobtitle;
            
$this->salary $salary;
            
$this->instance parent::$instanceCounter++;
        }
        function 
getInfo() {
            return 
$this->instance ' ' $this->firstname ' ' $this->lastname 
                   
' (Salary: ' $this->salary ', Job Title: '$this->jobtitle ')';
        }
    }
    
$bob = new Person('Bob''Jones');
    
$alice = new Person('Alice''Walker');
    
$fred = new Staff('Fred''Smith''Sales Manager''80000');
    
$joe = new Staff('Joe''Bloggs''Operations Manager''90000');
    echo 
$bob->getInfo() . "<br />\n";
    echo 
$alice->getInfo() . "<br />\n";
    echo 
$fred->getInfo() . "<br />\n";
    echo 
$joe->getInfo() . "<br />\n";
?>

Test this example here. You can see that the getInfo() function is defined in the base class (Person), and then defined again in the child class (Staff). When an object of type Person has its getInfo() method executed, the function in the bass class is run. When getInfo() is called on an instance of the child class (Staff), the more advanced function is run outputting the full details about the staff member.

 

Back to top


About Digital Crocus:

Digital Crocus offer affordable UK web hosting to get you up and running from just $32.49 per year or $3.99 per month. Our most basic account would be enough to get started learning PHP and host a few websites with a moderate amount of traffic. We offer easy upgrade options as your requirement grows and a friendly and helpful email and phone customer support service. If you're looking to buy web hosting, consider giving us a try - under our money back guarantee we'll refund you if you're not 100% satisfied.

About the author:

Kieran Simkin is an experienced software developer and co-founder of Digital Crocus. Kieran is also a keen amateur photographer and musician and has a personal portfolio which you can see online.

Questions Resellers Hosting Domains Home