PHP Classes and Objects

PHP class is a template for an object. To give an analogy from a real life example, if a class was "Animal", then we could create an object $tiger from that class, which is an animal that exists in real life.

class Animal { } $tiger = new Animal; //$tiger is an object instance of Animal class

So, to continue from the template Animal, we could ask questions like, what does every animal have and what can every animal do? The haves will turn into properties and could be something like animal's prey, and the dos will become methods or actions which every animal can perform like run or make a sound. Knowing some things about animals, we can incorporate them into our Animal class template:

class Animal { //we don't set any value for the properties because every animal will be different public $prey; public $max_speed; function make_sound( $sound ) { echo $sound; } } //we can now create the tiger object from class Animal //and set values that are specific to tiger $tiger = new Animal; $tiger->prey = "deer"; $tiger->max_speed = 40; echo "I'm an animal that loves to eat $tiger->prey. The fastest I can go is $tiger->max_speed mph"; $tiger->make_sound("Roar...."); //output: I'm an animal that loves to eat deer. The fastest I can go is 40 mph. Roar....

The properties and methods of the class become available to our variable object $tiger when we create the instance of the object with the "new" keyword followed by the class name (Animal), and we are able to access them using the -> (dart) operator, also known as the object operator.

Pseudo Variable $this

Make sure you really understand the difference between a class and an object before moving on, otherwise $this following concept will be confusing.

$this refers to the object instance inside of a class

class Animal { //set default property value, just for fun public $sound = "Cows don't growl. "; function make_sound( ) { //$this = $cow object ($cow->sound) echo $this->sound; } } $cow = new Animal; echo $cow->sound; $cow->sound = 'Moooooooo'; $cow->make_sound(); //output: Cows don't growl. Moooooooo

Okay...so what happens is we create the object $cow from the Animal class and we set it's sound property to 'Moooooooo'. We are then able to access $cow object from within Animal class using $this pseudo variable. By using $this, we no longer need to pass any parameters into make_sound() method. It's like magic!

It's also perfectly okay to set default property values inside of a class as shown in the above example, which is later overwritten with $cow->sound = 'Moooooooo'; line.

It's also possible to set the value of $this->sound property from within the class method as follows:

class Animal { public $sound; function set_sound( $sound ) { $this->sound = $sound; } function make_sound( ) { echo $this->sound; } } $cat = new Animal; $cat->set_sound( "Meow" ); //we can then either echo out the $sound property or call make_sound() method echo $cat->sound; $cat->make_sound(); //output: MeowMeow

Property Setters and Getters

In a similar way we have "set" the property $sound to a value which was specified outside of the class using the method set_sound(), we can also get the value of the $sound by creating a method called get_sound();

class Animal { public $sound; function get_sound( ) { return $this->sound; } function set_sound( $sound ) { $this->sound = $sound; } } $mouse = new Animal; $mouse->set_sound("Squeak"); echo $mouse->get_sound(); //output: Squeak

Magic PHP Methods Get and Set

Time for some real magic now! The right way to create getters and setters is to use PHP magic methods called __get() and __set() (that's two underscores before method name). Doing so will let us get and set any property, instead of creating these methods for every property which would be redundant, and redundancy is evil, especially in object-oriented programming! I hope this won't look too scary, if it does, don't worry I'll explain everything.

class Animal { //private keyword makes properties available only inside this class private $sound; private $max_speed; public function __get($property) { //check if property exists if (property_exists($this, $property)) { return $this->$property; } } public function __set($property, $value) { if (property_exists($this, $property)) { $this->$property = $value; } return $this; } } $monkey = new Animal; //property name is provided in a string format, without using the dollar sign $monkey->__set( 'sound', 'Scream' ); echo $monkey->__get( 'sound' ); //output: Scream $monkey->__set( 'max_speed', 34 ); echo $monkey->__get( 'max_speed' ); //output: 34 //trying to access private property outside the class: echo $monkey->sound; //Fatal Error

This should look somewhat familiar, though there are a few important differences. First of all, we are declaring our properties using the "private" scope keyword, which makes direct property access available only within the context of the Animal class. The reason for this is good programming design, since we're going to be setting and getting the value of the property using methods, it doesn't make sense to also have direct access to those properties outside of the class.

Second, we are checking if the property exists using an if statement and a self explanatory function called property_exists( ), which takes in two parameters - $this (object) and $property (property name)

Lastly, we're using __get() and __set() PHP magic methods which makes it possible to set and get the value of any property we create in the future.