Intermediate PHP

Builds upon the foundation principles of PHP, and now follows on into the concept of Object Oriented Programming within PHP.

 

It is assumed that you will already have a good understanding of the general OOP ideas and techniques, and the following material will therefore not go into the theory behind OOP but will focus upon how it is implemented within PHP.

 

Some of the more advanced techniques in PHP will be presented after the OO PHP articles.

class

The keyword class is used to define a user defined (abstract) data type. It is then followed by the user defined class name (/identifier) and a pair of curly braces { }

e.g class className { }

 

As you can see the above is not too useful on its own and this is because classes usually contain class members, consisting of attributes (/properties) and behaviours (/methods).

new

An object is created (/ instantiated) using the keyword new to assign the class to the user defined object name.

e.g. $myObject = new className ;

 

This example uses the var_export() function to view the contents of the object:

Save & refresh browser:

Instantiating a Bike Object

NULL

 

The var_export() function is showing a NULL output since the class is empty (i.e. it has no members; properties/methods).

Properties

Aka attributes 

  • Data type definitions for storing the actual values to be assigned to an individual object
  • Must be defined with a visibility keyword: public, protected, private, final
  • Can also be initialised by assigning a value within the class definition

 

This example shows a property being added to the class:

Save & refresh browser:

Instantiating a Bike Object

A new Bike object has been instantiated, called $myBike

 

The $myBike object's single property, $make, has been assigned a value of: Ducati

 

Bike::__set_state(array(

'make' => 'Ducati',
))

 

 

*Note: the -> (aka small arrow) access operator is used to get or set an object's attributes

-> Access Operator

The -> (aka small arrow) access operator is used to get or set an object’s attributes.

 

This example show the -> access operator being used to set and get a properties values:

Save & refresh browser:

Using the -> access operator to set and get an object's properties

The $myBike object's single property, $make, has been assigned a value of: Ducati

Methods

Aka behaviours

  • Internal functions of an object defining what it can do
  • Public be default, but a good idea to specify, just in case, and for good readability

 

This example now shows a method being added to the class:

Save & refresh browser:

Instantiating a Bike Object

A new Bike object has been instantiated, called $myBike

 

The object's single property, $make, has been assigned a value of: Ducati

 

A method has also been defined that: does something

 

The method can also be called without having the need for an instantiated object, and still: does something
Bike::__set_state(array(
'make' => 'Ducati',
))

 

 

*Note: parentheses must follow the method name

Constructor

The constructor is a magic method that is automatically called upon at the instantiation of a new object.

 

Syntax:

public function __construct() {

... code goes here...

}

 

(*note: magic methods start with a double underscore __ and will be discussed below)

 

A class showing a constructor being automatically called upon an object's instantiation:

Save & refresh browser:

An instance of the the 'Dog' class has been instantiated!

 

 

*note: the above code example also uses the __CLASS__ magic constant, which returns the name of the class

 

  • When using inherited classes, PHP initially looks for and if found will use that constructor in the child class
  • If the child class does not have a constructor, PHP will look to the parent, and then the grand parent, until it reaches the top or finds a constructor
  • Only one constructor will be called

Destructor

PHP (like Java, but unlike C++) has automatic garbage collection.

 

Unless otherwise explicitly carried out, objects are automatically destroyed at the end of the script they were created in.

 

In some cases, it might sometimes be useful to specifically carry out a task when an object  is destroyed, say to close a database connection.

 

Accordingly, the destructor is a magic method that is automatically called when an object is destroyed, e.g. at the end of the script.

 

Syntax:

public function __destruct() {

… code goes here…

 }

 

(*note: magic methods start with a double underscore __ and will be discussed below)

 

A class showing a destructor being automatically called at the end of the script:

Save & refresh browser:

An instance of the the 'Dog' class has been instantiated!
The script ends here.
Yalp!! The 'Dog' object has been destroyed!

 

It can be seen that the destructor was called after the last command in the script, i.e. when the script ended.

Deleting Objects with unset()

To delete an object before the end of a script the keyword unset() is used with the object's variable name within its parentheses

 

Syntax:

unset($myObject);

 

To call the destructor before the end of the script, i.e. when you require, use the unset() function:

Save & refresh browser:

An instance of the the 'Dog' class has been instantiated!
Yalp!! The 'Dog' object has been destroyed!
The script ends here.

 

It can now be seen that the destructor has been called before the end of the script by using the unset() function.

:: Scope Resolution

The scope resolution operator :: (aka in Hebrew as Paamayim Nekudotayim or the double colon) is explicitly used to access static, constant and overridden properties and methods of a class. The class required is defined to the left of the :: operator and the member to the right.

 

Syntax:

className::memberName ;

 

 

Save & refresh browser:

Welcome to the Ducati appreciation club!
The above shows a class method being called without an object instance.

 

The latest Ducati road going sports bike is the Panigale.

 

Welcome to the Ducati appreciation club!
Welcome Ducati MotoGP supporters!
The Desmodici is the MotoGP prototype racing equivalent of their road bike.

 

Welcome Ducati MotoGP supporters!

Parent Constructor

A Parent Constructor is used to add new functionality in a child's constructor whilst also using the Parent's constructor. Thus both the original Parent constructor and the Child constructor are called. This is achieved by using the keyword parent before the scope resolution operator :: and the __construct() magic method, within the child constructor.

 

Syntax:

parent::__construct();

 

This example shows a ParentClass and two child classes, one of which utilises the parent constructor as well as its own constructor:

Save & refresh browser:

ParentClass object instantiated using the ParentClass constructor
RedChild object instantiated using the ParentClass constructor and the RedChild constructor
BlueChild object instantiated using the ParentClass constructor

Objects within objects

Just like any other variable, objects can be used within other objects and are similarly accessed by using the small arrow -> access operator again.

 

This example instantiates a new (Display) object on line 23 that is assigned to the team property within the Rider object, it then assigns a value to the Display object's output property on line 27, and finally echo it back on line 30 to show the assignment has taken place:

Save & refresh browser:

An object instance of the Rider class has been instantiated.
An object instance of the Display class has been instantiated.
My name is Marc Marquez and I currently ride for Honda.

 

*note: the use of constructors, on lines 5 & 14,  is explained under the constructor magic method here

$this

The pseudo variable $this is used within a class to access the properties of the calling object (i.e. itself).

 

To access properties of an object use $this with the small arrow -> access operator, and then the name of the property without its $ dollar sign:

 

e.g. $this->name

 

Using $this to access the object's properties:

Save & refresh browser:

Exploring an object's pseudo varibale $this

Using the display method to show the properties:
Ducati, Panigale, 1200, 175, 17,999

 

Bike::__set_state(array(
'make' => 'Ducati',
'model' => 'Panigale',
'capacity' => '1200',
'topSpeed' => '175',
'cost' => '17,999',
))

Inheritance (extends)

Inheritance is an Object Oriented concept that establishes a relationship between a Parent (/Super) class and a Child (/Sub) class.

 

The child is said to inherit the members of the parent.

 

The keyword extends is used in the class signature, as can be seen on line 8 as follows:

Save and refresh browser:

Hi, my name is Julia, and I'm a Scientist!
I also have long blonde hair!!

 

The new Scientist class has extended the Person class, and in this case has also overridden the speak() method of the parent.

Overriding Methods

Methods within a child class can override the parent class, simply by redefining your own version.

 

 

The parent's display method on line 5 is overridden in the child's redefinition on line 13:

Save & refresh browser:

Vanessa Miasma "Legendary" NYC Goth DJ!

Access Specifiers

The access specifiers (aka access modifiers) define the level of visibility of a class’s members.

 

The following scope keywords are used to define the level of access:

  • public
    • members can be accessed any place the object is visible, in the script
  • protected
    • members can only be accessed from within the class itself and inherited/inheriting classes
  • private
    • members are accessible only from other members of the same class
    • explicitly; they are not accessible by inherited/inheriting classes

The $this-> pseudo variable must be used with the property name to access specific properties! The use of the member name on it's own will be ignored.

 

Example showing public access:

Save & refresh browser:

Hi, my name is Julia

 

To benefit from the essential OO concept of encapsulation (/ data hiding), it is desirable to keep the properties of the class private / protected, and to make the class responsible for setting and getting its own properties via its own methods only, hence disabling unwanted changes in an object's properties by anything other than the object itself.

 

The following example shows a protected property that can be inherited by a child class, if this property was set to private it would not be accessible in the child class and could therefore not be used. The example also shows a private property in the child class that can only be accessed within the class:

Save & refresh browser:

Derrick
Hi, my name is Derrick, and I'm a techie
Julia
Julia is a Scientist who works with lazers!!

 


final

  • used to to declare that a method or class cannot be overridden by a subclass
  • cannot be applied to properties
  • If the class itself is being defined final then it cannot be extended
  • Means of stopping other programmers using the code in unplanned ways

This example will purposefully fail due to the final keyword being applied to the Person class's speak() function.

Save & refresh browser:

Fatal error: Cannot override final method Person::speak() in /root/user/public_html/php/index.php on line 12

 

If the child class had not overridden the parent's final declared method, it would have simply used the parent's method with no errors

 


abstract

  • cannot be used directly
  • has to be inherited by a child class

This examples show an abstract class, Person, being inherited by the child, Scientist, class. When the script tries to instantiate the Parent abstract class a fatal error is returned:

Save & refresh browser:

Julia is a Scientist who works with lazers!!
Fatal error: Cannot instantiate abstract class Person in /root/user/public_html/php/index.php on line 17

static

The keyword static is used to make class members available at all times throughout a script, without the need for instantiating an object.

 

  • Because static methods are callable without an instance of an object being created, the pseudo-variable $this is not available inside a static method
    • instead the keyword self should be used e.g. return self::$myvar;
  • Static properties cannot be accessed through the object using the arrow operator ->
  • Static methods cannot access normal methods (those not declared static) since they belonging to an object, and not the class

 

Properties declared as static within a class mean that just one version of that property is used by all objects of that class. This could be useful for incrementing say a counter to keep a tally of the number of objects instantiated.

 

When a method is declared static it enables the method to be called like any other function.

 

In order to utilise static members from outside the class, the class name and the :: scope resolution operator must be used so that the correct member can be identified and used.

 

Syntax:

ClassName::member;

 

In this example a value has been assigned to the class's static $name property. This is called using self::$name within the class's static greet() function. To access the members from outside the class scope the :: scope resolution operator is used, as can be seen on lines 11 & 12:

Save & refresh browser:

Norman Fisher-Jones
Hi Norman Fisher-Jones

Object Properties Iteration

Since objects are quite similar to arrays, it is possible iterate through it's properties with a foreach loop.

 

  • properties must be accessible
  • private and protected are not accessible in the general scope

 

This example instantiates an object from a simple class with a number of properties that the foreach loop then iterates through. Note the private property on line 6 is not accessible outside the class:

Save & refresh browser:

make = Yamaha
model = YZFR1
cost = 12999
mpg = 67
colour = Blue
country = Japan

bhp = 146

 

 

To access private/protected properties, the foreach loop is moved into the class as a method:

Save & refresh browser:

make = Yamaha
model = YZFR1
cost = 12999
topSpeed = 165
mpg = 67
colour = Blue
country = Japan
bhp = 146

 

Since the object itself is iterating through it's own properties, private and protected properties can now be accessed.

Object type information

The keywords instanceof and is_subclass_of are used to return a boolean TRUE or FALSE value when an object is evaluated against a class name.

 

instanceof will return TRUE if the object belongs to the specified class, or a descendant of that class.

 

Syntax:

$myObject instanceof MyClass;

 

This example creates two objects and tests whether they are instances of the Parent or Child class:

Save & refresh browser:

The r1 object belongs to the Bike class
The m1 object belongs to the Bike class
The r1 is not a MotoGP class object
The m1 object belongs to the MotoGP class

 

It can be seen that the m1 is a Bike object, since it is inherited from the Bike class. Similarly, it can be seen that the r1 object is not a MotoGP object.

 

To determine is an object is just from a child class is_subclass_of will return TRUE if the object is a descendant of the specified class.

 

Syntax:

is_sub_class($myObject, MyClass);

 

This example creates two objects and tests whether they are in sub classes of the the Parent or Child class:

Save & refresh browser:

The r1 object is NOT in a sub class of the Bike class
The m1 object IS in a sub class of the Bike class
The r1 object is NOT in a sub class of the MotoGP class
The m1 object is NOT in a sub class of the MotoGP class

 

As expected only the m1 object is in a sub class

Type hinting

To ensure only the correct data-type objects (i.e. of the correct class) are used when passed into a method, a technique referred to as type hinting can be used. If the wrong type of object is then passed into that method a fatal error will result, as demonstrated in the following example:

Save & refresh browser:

Catchable fatal error: Argument 1 passed to output() must be an instance of Bike, instance of Car given, called in /root/user/public_html/php/index.php on line 15 and defined in /root/user/public_html/php/index.php on line 10

 

Since the $mille object is of the Car class type, it causes an error when the output() function is used, which expects a Bike class type, as can be seen on line 10 above.

 

The use of class type hints overcomes the need for separate instanceof functions, and are simple way to simplify and resolve bugs.

Object Cloning

Sometimes it might be necessary to make a copy of an object, say for backup purposes or when you don't want to effect the state of the original object.

 

To make a copy of an object the keyword clone is used.

 

Syntax:

$copyObject = clone $originalObject;

 

clone can also be used directly within a function's parentheses to pass a copy of the passed in object to the function. In this case $originalObject is left intact and myFunction() acts upon the clone:

 

myFunction(clone $originalObject);

 

 

Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method will be called from the original class, to allow any necessary properties that need to be changed. Also note, an object's __clone() method cannot be called directly.

 

  • clone copies all variables from first object to new object
  • then calls __clone() magic method, from the class it is copying from
    • akin to a constructor for the cloned object

 

In this example an object is instantiated and then assigned to a new object using the clone keyword. Finally, it uses the clone keyword within a function which makes a cloned copy of the passed in object for use within the function:

Save & refresh browser:

Original object Instantiated!
Clone 1 copied.
Clone 2 copied.
This function will firstly clone the object being passed in, it will then use the __clone() magic method in the class, and finally it will print this message.

Comparing Objects

Objects can be compared using:

 

  • Comparison operator ==
    • Checks if the properties are the same 
  • Identity operator ===
    • Also checks if instances of the same class

This example creates a new object, clones it and then copies the original object using a simple assignment:

Save & refresh browser:

$geek object instantiated. 

 

$geek and $techie objects don't compare.
$geek and $imposter objects compare.
$geek and $techie objects are not identical.
$geek and $imposter objects are identical.

 

Person::__set_state(array(
'name' => 'Will',
'now' => 1372934803,
))

 

Person::__set_state(array(
'name' => 'Will',
'now' => 1372934804,
))

 

Person::__set_state(array(
'name' => 'Will',
'now' => 1372934803,
))

Saving Objects - Serialization

To save objects the serialize() function is used to convert them into a format that can be saved, like so:

 

$target = serialize($source);

 

This can now be saved to a file using the file_put_contents() function, like so:

 

file_put_contents('path/file.txt', $target);

 

To read the object the complementary functions unserialize() and file_get_contents are utilised, like so:

 

$target = file_get_contents('path/file.txt'); //assigns the file contents

$source = unserialize($target); //converts back to the correct format

 

 

The following example is broken into 3 separate files. First we have the index.php file:

*note: the var_export() function is being used to show the contents of the object

 

Next is the person.inc file:

Save & refresh browser:

Object instantiated at 1372945579
Sharon object has been stored in the 'file.txt' file.
Click here to go to the retrieving page that reads the Sharon object from 'file.txt'. 

 

Person::__set_state(array(
'name' => 'Sharon',
'created' => 1372945579,
))

 

 

Finally, we have the read.php file:

*note: the var_export() function is being used to show the contents of the object

 

Save & refresh browser:

The Sharon object will now be read from 'file.txt'.
Hi, my name is Sharon and I was created at 1372945579. 

 

Person::__set_state(array(
'name' => 'Sharon',
'created' => 1372945579,
))

 

 

Note: static members of an object are not serialized

 

 

 

When saving and reading objects using serialize() and unserialize, they automatically look for __sleep() and __wakeup() magic methods for their respective function. You will need to provide these magic methods yourself and are used to perform cleanups of the object before being saved or read.

Magic Methods

These are builtin methods provided by PHP that allow additional functionality in OOP.

 

  • start with two underscores e.g. __construct()
  • automatically called under specific conditions

 

So far the above examples have used the following:

  • __construct()
  • __destruct()
  • __clone()
  • __sleep()
  • __wakeup()

 

The following examples now explore the remaining major magic methods:

  • __autload()
  • __get()
  • __set()
  • __call()
  • __tostring()

 

__autoload()

Sometimes there may be a large number of include files required for multiple classes, which could become unmanageable as the number of separate class include files grows, and you might not want to include every file 'just in case'.

 

PHP has a facility to automatically load files by using the __autoload() function, that attempts to load a (perhaps forgotten include) file based on the name of the object trying to be created.

 

A typical __autoload() function syntax:

 

function __autoload($class_name) {

include 'class.' . $class_name . 'inc';

}

 

If a new object were trying to be created, say using $fido = new Dog; and that class had not been defined/included, then the __autoload function would attempt to load class.Dog.inc

 

*note: the autoloading filename is case sensitive and may require the strtolower() function, if your file names are in lower case.

 

Since the autoloading filename is case sensitive, this example uses the previous person.inc and therefore requires the strtolower() function to convert the Person class name to lower case for the person.inc filename:

Save & refresh browser:

Attempting to load person.inc
Object instantiated at 1372952352
Hi, my name is Jim and I was created at 1372952352.
 

Person::__set_state(array(
'name' => 'Jim',
'created' => 1372952352,
))

 


__get()

Used within a class when an attempt is made to access a property that isn't accessible e.g. if it doesn't have public visibility or doesn't exist.

Save & refresh browser:

Access to private property using the __get() magic method called on name: James Tiberius Kirk
__get() magic method called on age:
 

Person::__set_state(array(
'name' => 'James Tiberius Kirk',
))

 


__set()

Used within a class when a call is made to set a property that isn't accessible e.g. if it doesn't have public visibility or doesn't exist.

Save & refresh browser:

__get() magic method called on name: James Tiberius Kirk
Access to private property __set() magic method called!
__get() magic method called on data: Mr Spock
 

Person::__set_state(array(
'name' => 'James Tiberius Kirk',
))

 


__call()

Used within a class when a call is made to a method that isn't accessible e.g. if it doesn't have public visibility or doesn't exist.

 

This example has commented out the fly() method, on lines 5-8, to invoke the __call() magic method:

Save & refresh browser:

Sorry, Peter Parker, Call to fly() with args 'Only, Superman, can, fly!' failed!

 


__tostring()

Defined within a class to decide what an object should do when treated like a string (e.g. echo $myObject;) and must return a string:

Save & refresh browser:

Hi Peter Parker, here's the string for the new Person object!

Class/Object Functions

PHP has many inbuilt functions to help with your programming needs. Here's an example script with a few to be getting on with:

Interfaces

Interfaces provide a way of implementing multiple inheritance (not directly available in PHP) through the use of the keywords interface and implements.

 

Potentially, one could inherit from a parent class, and then inherit from that class and so in a chain like fashion. However, this would likely mean a number of the parents, parents, parents, etc, members might be included that might not be required, and avoids needing a very long trail like this:

class Test implements InterfaceA, InterfaceB, InterfaceC, InterfaceD, InterfaceE......InterfaceZ {}

 

Interfaces:

  • 100% abstract classes
  • Cannot be instantiated
  • Contain just the method names, not their definitions (i.e. the inner guts of their code)
  • Act like a contract to the class implementing the specified interface
  • All method names within an interface have public visibility
  • The implementing class must define the methods

The interface simply uses the keyword interface, which is then used by the class using the interface by way of the keyword implements:

Save & refresh browser:

The guy who invented big bangs: Stephen Hawking is now 71 years old!
Stephen Hawking has just made a measurement!
Stephen Hawking has written a paper! 

 

Geek::__set_state(array(
'name' => 'Stephen Hawking',
'age' => 71,
))

constants

Constant values can be defined within a class using the keyword const.

 

Syntax:

const myConstant = "Constant Value";

 

  • Remain the same and unchangeable
  • Do not use the $ symbol
  • Must be a constant expression
    • not a class's property, result of a mathematical operation or a function call

Example showing a const being defined within the class, then being called from within the class and again externally:

Save & refresh browser:

Constructor: constant value
constant value

URL Functions

A few functions that work with URL strings to encode, decode, parse and generally make sure they are in the correct format for transmission over the internet.

 

urlencode()

Since URLs can only be transmitted over the internet using ASCII characters, it is often necessary to convert non-alphanumeric characters to their ASCII coded equivalent

  • Encodes a string to be used in query part of URL
  • Convenient way to pass variables to other pages
  • Returns string in which all non-alphanumeric characters except -_. have been replaced by the percent sign followed by two hex digits and spaces encoded as +

Save & refresh browser:

What's this doing here?
What%27s+this+doing+here%3F
test

 

Mousing over the test url will show the non-alphanumeric characters in the link have been converted to their ASCII equivalent codes:

https://tech-academy.co.uk/someService?myVar=What%27s+this+doing+here%3F

 

 

urldecode()

  • Decodes any ASCII two digit hex %## encoding in the given string
  • Plus symbols ('+') are decoded to a space character

Save & refresh browser:

https://tech-academy.co.uk/someService?myVar=What%27s+this+doing+here%3F
https://tech-academy.co.uk/someService?myVar=What's this doing here?

 

 

rawurlencode()

  • Similar to above but converts spaces to %20

rawurldecode()

  •  Decodes above rawurlencoded string

Save & refresh browser:

Isn't this a string with % non-alphanumeric $ * £ characters?
Isn%27t%20this%20a%20string%20with%20%25%20non-alphanumeric%20%24%20%2A%20%C2%A3%20characters%3F
test
Isn't this a string with % non-alphanumeric $ * £ characters?

 

Mousing over the test url will show the non-alphanumeric characters in the link have been converted to their ASCII equivalent codes:

https://derrickrobinson.com/php/someService?myVar=Isn%27t%20this%20a%20string%20with%20%25%20non-alphanumeric%20%24%20%2A%20%C2%A3%20characters%3F

 

base64_encode() / base64_decode()

  • Encodes the given data with base64
  • This encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies
  • Base64-encoded data takes about 33% more space than the original data

Save & refresh browser:

This string is being base64 encoded / decoded
VGhpcyBzdHJpbmcgaXMgYmVpbmcgYmFzZTY0IGVuY29kZWQgLyBkZWNvZGVkOiA8YnI+

 

Now decoding:
This string is being base64 encoded / decoded

 

More URL functions here.

Exception Handling

Exception handling is carried out by the use of the keywords throw, trycatch.

 

An exception can be thrown and caught (catched).

 

  • Code may be surrounded in a try block, to facilitate the catching of potential exceptions
  • Each try must have at least one corresponding catch block
  • Multiple catch blocks can be used to catch different classes of exceptions
  • Normal execution (when no exception is thrown within the try block, or when a catch matching the thrown exception's class is not present) will continue after that last catch block defined in sequence
  • Exceptions can be thrown (or re-thrown) within a catch block.

 

  • When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block
  • If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception ..." message, unless a handler has been defined with set_exception_handler().
  • In PHP 5.5 and later, a finally block may also be specified after the catch blocks
  • Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.
  • The thrown object must be an instance of the Exception class or a subclass of Exception. Trying to throw an object that is not will result in a PHP Fatal Error.

Save & refresh browser:

If you see this, the number is 1 or below

PDO

PHP Data Objects, provide database access standardisation (some call this an access abstraction layer) that allows portable code to be used across multiple databases and platforms. Meaning, the same functions to perform queries and fetch data are used regardless of the type of database being used.

 

3 classes:

  • PDO class maintains database connection
  • PDOStatement class, handles SQL queries
  • PDOException class, provides error handling

 

PDO class

requires 3 pieces of information:

  • database location
  • username
  • password

 

The database location is in the form of a DSN (Data Source Name) which conforms to a specific format and is slightly different for each type of database.

 

To determine the available database drivers on your system:

Save & refresh browser:

sqlite 

sqlite2

mysql

 

 

DSN syntax:

database_type:host_location;database_name;

 

A simple connection could then be made using:

 

 

For the purpose of these PDO articles, I will be using my motogp database and the riders table, as follows:

 

CREATE TABLE 'riders' (
'id' mediumint(8) NOT NULL AUTO_INCREMENT,
'name' varchar(25) COLLATE utf8_unicode_ci NOT NULL,
'team' varchar(25) COLLATE utf8_unicode_ci NOT NULL,
'points' mediumint(8) NOT NULL,
'status' varchar(28) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY ('id')
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ; 

 

INSERT INTO 'riders' ('id', 'name', 'team', 'points', 'status') VALUES
(1, 'Dani Pedrosa', 'Honda', 136, 'Factory'),
(2, 'Jorge Lorenzo', 'Yamaha', 127, 'Factory'),
(3, 'Marc Marquez', 'Honda', 113, 'Factory'),
(4, 'Cal Crutchlow', 'Yamaha', 87, 'Factory'),
(5, 'Valentino Rossi', 'Yamaha', 85, 'Factory'),
(6, 'Andrea Dovizioso', 'Ducati', 65, 'Factory'),
(7, 'Stefan Bradl', 'Honda', 51, 'Factory'),
(8, 'Nicky Hayden', 'Ducati', 50, 'Factory'),
(9, 'Alvaro Bautista', 'Honda', 47, 'Factory'),
(10, 'Aleix Espargaro', 'ART', 44, 'CRT');

 

We'll now connect to the above database table and perform a simple query:

Save & refresh browser:

Connected to the motogp database
Dani Pedrosa rides for Honda
Jorge Lorenzo rides for Yamaha
Marc Marquez rides for Honda
Cal Crutchlow rides for Yamaha
Valentino Rossi rides for Yamaha
Andrea Dovizioso rides for Ducati
Stefan Bradl rides for Honda
Nicky Hayden rides for Ducati
Alvaro Bautista rides for Honda
Aleix Espargaro rides for ART

PDO Exceptions

A PDOException will be thrown if there are any connection errors. These can be caught in a try/catch block.

 

The PDO::setAttribute() method is used to set the error reporting level as follows:

  • PDO::ATTR_ERRMODE: Error reporting.
    • PDO::ERRMODE_SILENT: Just set error codes.
    • PDO::ERRMODE_WARNING: Raise E_WARNING.
    • PDO::ERRMODE_EXCEPTION: Throw exceptions.

Syntax:

$object->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

 

Exception methods can now be used:

getCode()

getMessage()

getTrace()

getFile()

getLine()

returns error code

returns the exception message

returns the exception stack trace as an array

returns the name of the file the exception was created

returns the line number where the exception was created

 

For this example, to show the connection error being caught, I have changed the username to potato:

Save & refresh browser:

Error!: SQLSTATE[28000] [1045] Access denied for user 'potato'@'localhost' (using password: YES)

Organising Files

Whilst not strictly a PDO concept, I am showing the use of placing some of the code into external files that are then included.

 

This will keep the examples slightly shorter and show modularity.

 

First the connection to the database:

Save & refresh browser:

Connected to the motogp database

 

Changing any of the connection variables throws an exception :

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2005] Unknown MySQL server host 'xxxxxxx' (25)' in /path/user/public_html/pdo/connect.php:7 Stack trace: #0 /path/user/public_html/pdo/connect.php(7): PDO->__construct('mysql:host=xxxx...', 'testing', 'secret') #1 {main} thrown in /path/user/public_html/pdo/connect.php on line 7

 

 

Now the error handling:

 

The above files can now be included where required and provide neater more readable code:

Save & refresh browser:

Connected to the motogp database
Dani Pedrosa rides for Honda
Jorge Lorenzo rides for Yamaha
Marc Marquez rides for Honda
Cal Crutchlow rides for Yamaha
Valentino Rossi rides for Yamaha
Andrea Dovizioso rides for Ducati
Stefan Bradl rides for Honda
Nicky Hayden rides for Ducati
Alvaro Bautista rides for Honda
Aleix Espargaro rides for ART

PDO Prepared Statements

Precompiled SQL statement that uses the prepare() PDO method that is then executed by the execute() method.

 

Line 10 shows an SQL query being assigned to a variable which is then assigned to the $statement variable using the prepare() method on line 13. The prepared statement is then executed on line 16:

Save & refresh browser:

Connected to the motogp database
Dani Pedrosa rides a Honda Factory MotoGP bike!
Marc Marquez rides a Honda Factory MotoGP bike!
Stefan Bradl rides a Honda Factory MotoGP bike!
Alvaro Bautista rides a Honda Factory MotoGP bike!

 

*note: the fetch() method is now being used in the while loop on line 21, in place of our previous query() method in the foreach loop

PDO Placeholders

To obtain the full benefit of prepared statements placeholders are used within the prepared statement.

 

Placeholders protect against SQL injection, since the data never gets inserted into the SQL query.

 

There are two types of placeholders: named and unnamed

 

The following list shows a comparison of 3 examples:

 

  • No placeholders - ripe for SQL Injection!
    • $statement = $dbh->("INSERT INTO riders (name, team, status) values ($name, $team, $status)");
  • Named placeholders
    • $statement = $dbh->("INSERT INTO riders (name, team, status) value (:name, :team, :status)");
    • the named placeholders are in the rightmost parentheses, and take the form of a colon : followed by the placeholder name without quotes
  • Unnamed placeholders
    • $statement = $dbh->("INSERT INTO riders (name, team, status) values (?, ?, ?);
    • the unnamed placeholders are in the rightmost parentheses, and take the form of a question mark ?

 

 

When using placeholders, the variables need to be bound (/associated) to the placeholders using the bindParam() method (binds a parameter to a variable) for named placeholders or the bindValue() method (binds a value to a parameter) for unnamed placeholders.

 

This example shows the named placeholders within the query on line 10, which is then used in the prepared statement on line 13 and bound to the variables on lines 16 & 17:

Save & refresh browser:

Connected to the motogp database
Jorge Lorenzo rides a Yamaha Factory MotoGP bike!
Cal Crutchlow rides a Yamaha Factory MotoGP bike!
Valentino Rossi rides a Yamaha Factory MotoGP bike!

 

 

The same example this time showing unnamed placeholders within the query on line 10, which is then used in the prepared statement on line 13 and bound to the variables on lines 16 & 17:

Save & refresh browser:

Connected to the motogp database
Jorge Lorenzo rides a Yamaha Factory MotoGP bike!
Cal Crutchlow rides a Yamaha Factory MotoGP bike!
Valentino Rossi rides a Yamaha Factory MotoGP bike!

PDO Binder Function

Since the number of variables to be bound could potentially become quite large, a function can be used to build the bindValue() methods for the prepared statements.

 

First an associative array is created with the variables being associated as the values as the keys:

 

$myArr = array('team'=>$team, 'status'=>$status);

 

The array is then used within a foreach loop to build the prepared statements:

 

foreach($myArr as $key=>$value){

$statement->bindValue(':'.$key,$value);

}

 

Putting this altogether we now have a function that will build the binding prepared statements:

Save & refresh browser:

Connected to the motogp database
Andrea Dovizioso rides a Ducati Factory MotoGP bike!
Nicky Hayden rides a Ducati Factory MotoGP bike!

 

 

We can even take this one step further and place the binding function into an external file:

*note: use of & denoting that references are being passed in and therefore the original values will be modified

 

The above pdoBinder.php file can now be included in the main file, as can be seen on line 5, and it's arrayBinder() function called on line 23 passing in the prepared statement and the array:

Save & refresh browser:

Connected to the motogp database
Andrea Dovizioso rides a Ducati Factory MotoGP bike!
Nicky Hayden rides a Ducati Factory MotoGP bike!

PDO utilising OOP

Building on the previous examples of moving functions into external files, we can now develop an OO class that will perform the same functions.

 

The error_handling.php and pdoBinder.php files can be placed into a single pdoClass.php file, and encapsulated within a class as follows:

The only difference here is that the previous functions have now been prefixed with the public visibility keyword.

 

The pdoClass.php can now be included within the main file as per line 4, and an object instantiated upon it as per line 8. The $myObject object is then used with the access operator -> on lines 16 and 22 to perform the same functionality as previously but we are now using an object oriented approach:

Save & refresh browser:

Connected to the motogp database
Dani Pedrosa rides a Honda Factory MotoGP bike!
Marc Marquez rides a Honda Factory MotoGP bike!
Stefan Bradl rides a Honda Factory MotoGP bike!
Alvaro Bautista rides a Honda Factory MotoGP bike!

PDO Transactions

Transactions provide a method of batch processing a saved set of queries to be carried out (committed) at a later time. They also have the advantage of being able to roll back should a problem arise.

 

The 3 PDO methods utilised for this functionality are:

  • beginTransaction()
  • commit()
  • rollback()

 

After much testing, and finding the rollBack() method wasn't working, I discovered:

  • Ensure your database supports transactions!
  • MyISAM tables do not support transactions
  • Use InnoDB

 

This example has been stripped right down to purely focus on transactions:

  1. The beginTransaction() method is called by the database object, thus turning off auto-commit mode
  2. Four SQL insert queries are executed, but are not committed to the database
  3. The fifth SQL insert query contains errors
  4. The commit() method is called by the database object, but since the above contains an error an exception is thrown
  5. The exception is caught in the catch block
  6. The rollBack() method is called by the database object, and rolls back the above queries
  7. The database appears unchanged

Save & refresh browser:

Connected to the motogp database
Error!
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'motogp.potato' doesn't exist
Class & Method: PDO & query
File: /path/user/public_html/pdo/index.php
Line: 13

 

 

Simply comment out line 12 with the errors to see the queries committed to the database:

Save & refresh browser:

Connected to the motogp database
Dani Pedrosa rides for Honda
Jorge Lorenzo rides for Yamaha
Marc Marquez rides for Honda
Cal Crutchlow rides for Yamaha
Valentino Rossi rides for Yamaha
Andrea Dovizioso rides for Ducati
Stefan Bradl rides for Honda
Nicky Hayden rides for Ducati
Alvaro Bautista rides for Honda
Aleix Espargaro rides for ART
Bradley Smith rides for Yamaha
Michele Pirro rides for Ducati
Andrea Iannone rides for Ducati
Randy De Puniet rides for ART

header redirect

The header() function is used to send a raw HTTP header and must be called before any output is sent, either by normal HTML tags, blank lines in a file, or from PHP.

 

This examples gives the standard redirect to the specified URL after the Location keyword, both enclosed within quotes:

 

A slight variation to redirect after a specified time using the refresh keyword with a chosen delay time and URL:

 

<?php header('refresh:5;url=/'); ?>

 

 

Or the sleep() function could be prior to the header() redirect function.

 

<?php

sleep(2);

header('location:/');

?>

 

 

Some other header() function examples:

 

Prevent page caching

 

Prompt user to download content.

(Content-Disposition header is used to supply a recommended filename and force the browser to display the save dialog box):

 

Basic HTTP Authentication example