Roll Your Own PDO PHP Class

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 32

Roll your own PDO PHP Class

Last week I introduced PDO, a database abstraction layer that you can use in your applications to allow
for future flexibility in your database choice and protect you from SQL Injection.
Whilst the class we looked at is great for getting started with PDO quickly, it does have some
restrictions if you want to do more complicated things than simple selects, inserts, updates and deletes.
I think it is also far more beneficial to know exactly what is going on under the hood of your code. By
knowing exactly how something works you will gain a much deeper sense of understanding and you
will be able to troubleshoot and advance your code when the time comes.
So if you haven’t read last week’s post, go back and read that as an introduction to PDO, Prevent PHP
SQL Injection with PDO Prepared Statements.

Setting up the files


The first thing to do is to create the files we are going to need to work with. Firstly we need a file to hold
our class. I will be referring to this as databass.class.php. Secondly we need a file to use our new class, I
will be referring to this as tutorial.php.
Next, in the database.class.php we need to create the class. Copy and paste the following into that file.

<?php
class Database
{
}
Here we are simply defining a new class called Database.
Now in the tutorial.php file we need to include the class. Copy and paste the following line to include the
database class in your tutorial file.

// Include database class


include ‘database.class.php’;
Next, still in tutorial.php, we need to define our connection configuration.

// Define configuration
define("DB_HOST", "localhost");
define("DB_USER", "username");
define("DB_PASS", "password");
define("DB_NAME", "database");
Back in database.class.php, we need to set up the variables in the class.

private $host = DB_HOST;


private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
And finally we need to instantiate a new instance of the database class.

// Instantiate database.
$database = new Database();
Hopefully you understand all of the above as there is nothing specifically PDO related so far.

Construct
The first method we will look at is the construct method.
public function __construct()
{

}
When a class has a construct method, it is automatically called on all newly-created objects. This
enables you to set up any initialisation you might need on the new object before it is used.

Database Source Name


The next thing to do is to set the Database Source Name.

When using PDO, you need to set the database connection method because PDO can be used with many
different types of database. Each different database has a slightly different connection string. To set a
particular database connection type, we just set the specific string.

// Set DSN
$dsn = ‘mysql:host=’ . $this->host . ‘;dbname=’ . $this->dbname;
In this example I’m setting the DSN to MySQL and I’m using the host and the database name we defined
earlier.

If you know you are going to be using MySQL for the foreseeable future, this is probably going to be fine.
However, it does take away some of the flexibility and reusability of PDO by hardcoding the connection
into a string like this. To make this more flexible and resizable you would use Dependency Injection. I
think Dependency Injection deserves it’s own tutorial, so I’ll leave that for another day. Just be aware
that you could make your construct a lot more future proof.

Options
When connecting to the database we can set a couple of different attributes. To set these options on
connection, we simply include them as an array.

// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
PDO::ATTR_PERSISTENT
This option sets the connection type to the database to be persistent. Persistent database connections
can increase performance by checking to see if there is already an established connection to the
database.
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
PDO can use exceptions to handle errors. Using ERRMODE_EXCEPTION will throw an exception if an
error occurs. This then allows you to handle the error gracefully.

To read more about PHP exceptions, take a look at The ins and outs of PHP exceptions.
Handling exceptions in PHP deserves it’s own tutorial and is out of the scope of this tutorial. I’ll write a
tutorial for handling exceptions in the coming weeks.

Try/Catch
Next we use a try/catch block to attempt to make a connection, or handle any exceptions if an error
occurs.

First we need to create a new variable, $dbh (Database Handler).

Declare a new variables at the top of your class for the Database Handler and any errors.

private $dbh;
private $error;
Back in the construct method we attempt a new PDO instance.

try {
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
Next we catch any errors that might occur.

// Catch any errors


catch (PDOException $e) {
$this->error = $e->getMessage();
}
Now whenever you create a new instance of your database class, a new PDO instance will be created. If
any errors occur when trying to create a new PDO instance, they will be handled gracefully.

So far your class should look like this:

class Database{
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;

private $dbh;
private $error;
public function __construct(){
// Set DSN
$dsn = ‘mysql:host=’ . $this->host . ‘;dbname=’ . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
}
}
}
Query
The next method we will be creating is the query method.

The query method introduces the $stmt variable to hold the statement.

So firstly, at the top of the class, declare the new variable.

private $stmt;
Prepare
The query method also introduces the PDO::prepare function.
The prepare function allows you to bind values into your SQL statements. This is important because it
takes away the threat of SQL Injection because you are no longer having to manually include the
parameters into the query string.
Using the prepare function will also improve performance when running the same query with different
parameters multiple times.
Copy and paste the following method into your class:

public function query($query){


$this->stmt = $this->dbh->prepare($query);
}
Bind
The next method we will be looking at is the bind method. In order to prepare our SQL queries, we need
to bind the inputs with the placeholders we put in place. This is what the Bind method is used for.
The main part of this method is based upon the PDOStatement::bindValue PDO method.
Firstly, we create our bind method and pass it three arguments.
public function bind($param, $value, $type = null){

}
Param is the placeholder value that we will be using in our SQL statement, example :name.
Value is the actual value that we want to bind to the placeholder, example “John Smith”.
Type is the datatype of the parameter, example string. Next we use a switch statement to set the
datatype of the parameter:

if (is_null($type))
{
switch (true)
{
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
Finally we run bindValue.
$this->stmt->bindValue($param, $value, $type);
The final bind method is:
public function bind($param, $value, $type = null)
{
if (is_null($type))
{
switch (true)
{
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
Execute
The next method we will be look at is the PDOStatement::execute. The execute method executes the
prepared statement.

public function execute(){


return $this->stmt->execute();
}
Result Set
The Result Set function returns an array of the result set rows. It uses the PDOStatement::fetchAll PDO
method. First we run the execute method, then we return the results.

public function resultset(){


$this->execute();
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
Single
Very similar to the previous method, the Single method simply returns a single record from the
database. Again, first we run the execute method, then we return the single result. This method uses the
PDO method PDOStatement::fetch.

public function single(){


$this->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
Row Count
The next method simply returns the number of effected rows from the previous delete, update or insert
statement. This method use the PDO method PDOStatement::rowCount.

public function rowCount(){


return $this->stmt->rowCount();
}
Last Insert Id
The Last Insert Id method returns the last inserted Id as a string. This method uses the PDO method
PDO::lastInsertId.

public function lastInsertId(){


return $this->dbh->lastInsertId();
}
Transactions
Transactions allows you to run multiple changes to a database all in one batch to ensure that your work
will not be accessed incorrectly or there will be no outside interferences before you are finished. If you
are running many queries that all rely upon each other, if one fails an exception will be thrown and you
can roll back any previous changes to the start of the transaction.
For example, say you wanted to enter a new user into your system. The create new user insert worked,
but then you had to create the user configuration details in a separate statement. If the second
statement fails, you could then roll back to the beginning of the transaction.
Transactions also prevent anyone accessing your database from seeing inconsistent data. For example,
say we created the user but someone accessed that data before the user configuration was set. The
accessing user would see incorrect data (a user without configuration) which could potentially expose
our system to errors.

To begin a transaction:
public function beginTransaction(){
return $this->dbh->beginTransaction();
}
To end a transaction and commit your changes:

public function endTransaction(){


return $this->dbh->commit();
}
To cancel a transaction and roll back your changes:

public function cancelTransaction(){


return $this->dbh->rollBack();
}
Debug Dump Parameters
The Debut Dump Parameters methods dumps the the information that was contained in the Prepared
Statement. This method uses the PDOStatement::debugDumpParams PDO Method.

public function debugDumpParams(){


return $this->stmt->debugDumpParams();
}
Using your PDO class
Now that we’ve finished writing the database class, it’s time to test it out.
The remaining bit of this tutorial will be using the tutorial.php file you created at the very start.
I’m going to be using the same MySQL table that I created in last week’s tutorial. If you haven’t read last
week’s tutorial, you can create the table by running the following SQL.
[sql]
CREATE TABLE mytable (
ID int(11) NOT NULL AUTO_INCREMENT,
FName varchar(50) NOT NULL,
LName varchar(50) NOT NULL,
Age int(11) NOT NULL,
Gender enum(‘male’,’female’) NOT NULL,
PRIMARY KEY (ID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
[/sql]

Insert a new record


Firstly you need to instantiate a new database.

$database = new Database();


Next we need to write our insert query. Notice how I’m using placeholders instead of the actual data
parameters.
$database->query(‘INSERT INTO mytable (FName, LName, Age, Gender) VALUES (:fname, :lname,
:age, :gender)’);
Next we need to bind the data to the placeholders.

$database->bind(‘:fname’, ‘John’);
$database->bind(‘:lname’, ‘Smith’);
$database->bind(‘:age’, ’24’);
$database->bind(‘:gender’, ‘male’);
And finally we run execute the statement.

$database->execute();
Before running the file, echo out the lastInsertId function so you will know that the query successfully
ran when viewed in the browser.
echo $database->lastInsertId();
Insert multiple records using a Transaction
The next test we will try is to insert multiple records using a Transaction so that we don’t have to repeat
the query.

The first thing we need to do is to begin the Transaction.


$database->beginTransaction();
Next we set the query.
$database->query(‘INSERT INTO mytable (FName, LName, Age, Gender) VALUES (:fname, :lname,
:age, :gender)’);
Next we bind the data to the placeholders.

$database->bind(‘:fname’, ‘Jenny’);
$database->bind(‘:lname’, ‘Smith’);
$database->bind(‘:age’, ’23’);
$database->bind(‘:gender’, ‘female’);
And then we execute the statement.

$database->execute();
Next we bind the second set of data.

$database->bind(‘:fname’, ‘Jilly’);
$database->bind(‘:lname’, ‘Smith’);
$database->bind(‘:age’, ’25’);
$database->bind(‘:gender’, ‘female’);
And run the execute method again.

$database->execute();
Next we echo out the lastInsertId again.

echo $database->lastInsertId();
And finally we end the transaction

$database->endTransaction();
Select a single row
The next thing we will do is to select a single record.

So first we set the query.

$database->query(‘SELECT FName, LName, Age, Gender FROM mytable WHERE FName = :fname’);
Next we bind the data to the placeholder.

$database->bind(‘:fname’, ‘Jenny’);
Next we run the single method and save it into the variable $row.

$row = $database->single();
Finally, we print the returned record to the screen.

echo "<pre>";
print_r($row);
echo "</pre>";
Select multiple rows
The final thing we will do is to run a query and return multiple rows.

So once again, set the query.

$database->query(‘SELECT FName, LName, Age, Gender FROM mytable WHERE LName = :lname’);
Bind the data.

$database->bind(‘:lname’, ‘Smith’);
Run the resultSet method and save it into the $rows variable.

$rows = $database->resultset();
Print the return records to the screen.

echo "<pre>";
print_r($rows);
echo "</pre>";
And finally display the number of records returned.

echo $database->rowCount();
Conclusion
And there you have it, your first rolled PDO database abstraction class. Hopefully this tutorial has
introduced the main aspects of PDO and how it actually works. I think actually creating something like
this is far more beneficial than using someone else’s library because you need to fully understand how
all of this works, even if it takes longer in the long run.

I’ve missed out, or brushed over a number of important areas throughout this tutorial to try and keep it
on topic. If you are interested in learning more about these related areas, subscribe to our RSS feed or
follow us on Twitter to keep up to date with the latest posts and tutorials.

If you have any questions, or you can a think of a way to improve this class, please leave a comment!
Really simple inline Javascript validation
Just about any website or web application will require user input in one form or another. Whether it’s
filling in a contact form or entering profile details into a new application, handling input errors can be
the difference between a good or a bad user experience.
Have you ever filled in a huge form online, only to submit it and find that there was an error so you have
to start again? Frustrating, isn’t it? It is these kind of fundamental errors that stop people returning to
your website.
A much better way of solving this problem is to include inline validation that checks the user’s input as
she progresses. This alerts the user to any errors and allows her to correct her errors before proceeding
and losing her progress.
Inline validation powered by Javascript can be incredibly easy to implement, so there really is no excuse
for not making your user’s lives as easy as possible.

Here is a tutorial for building your own Javascript validation that you can use on any input on your
website or web application. I’ve intentionally kept it as easy, simple and lightweight as possible.

Creating your page


For this tutorial I’m just going to include all of the HTML and Javascript in one file to keep things simple.
So to start off, create yourself a little HTML file, like this.

<!doctype html>
<html lang="en">

<meta charset="utf-8">
<title>Validation tutorial</title>
<script>
// JS
</script>

Create the form


Next we need to a create an input field to validate. Create a form and an input field to allow you to enter
your name.

<form action="">
<fieldset>
<label for="name">Name</label>
<input type="text" name="name" id="name" />
</fieldset>
</form>
Next we need to add the onblur Javascript event to the input field. The onblur event allows you to run
Javascript code when the user clicks away from the field. In this case, we want to be able to validate
what the user has entered into the field, but we only want to do that when she has finished typing and
has moved on.
Update your input field so it looks like this.
<input type="text" name="name" id="name" onblur="validateName(name)" />
As you can see, I’ve already named the Javascript function that we are going to make in a minute and
I’ve passed in the name of the the field, in this case “name”.

Introducing the Javascript


Next we need to create the Javascript function.

In between the <script></script> tags at the top of the page, type the following code.
function validateName(x){
alert(document.getElementById(x).value);
}
Now save your file and open it in the browser. Enter some text into the input field and click away from
the field. An alert box should appear with the text you entered.

So as you can see…

We created an input field. Added an onblur event which is triggered when the user clicks away
We then used a Javascript function to display the contents of the input in an alert box. So hopefully you
can see how the Javascript is run when it is triggered, and how we are able to get whatever the user has
typed into the input box and do something with it.

Next I’ll show you how to validate the input.

Delete the following line from your Javascript.


alert(document.getElementById(x).value);
Javascript Regular Expressions
In order to validate the input, we have to test it against a set of rules that define a pass or fail. For
example, you don’t want your users to enter & or @ or % into your name field because these characters
don’t belong there.
In order to create a set of rules we use a Regular Expression (Regex). A Regular Expression is a way of
matching an input to a set of rules. If the input matches the pattern it will return true, but if it does not,
it will return false. So in the above example, if the input contained an @ when the pattern does not
include an @ the test would return false and the validation would fail.
To create a validation for your name field, type the following line into your validateName() function.
var re = /[A-Za-z -‘]$/;
In the above line of code, we create a variable called re and assign it the regex of any capital letter (A-Z),
any lower case letter (a-z), a space, a hyphen or an apostrophe.

With this regex rule saved, we can then run a test on our input to see if what was entered matches our
defined rule.
Type the following code after the previous line.
if(re.test(document.getElementById(x).value)){
document.getElementById(x).style.background =’#ccffcc’;
return true;
}else{
document.getElementById(x).style.background =’#e35152′;
return false;
}
Here’s how the above code breaks down.

if(re.test(document.getElementById(x).value)){
We test to see if the input value matches our rule. If it does, we change the input box’s background to
green.

document.getElementById(x).style.background =’#ccffcc’;
return true;
But if it doesn’t, we turn the input box red.

}else{
document.getElementById(x).style.background =’#e35152′;
return false;
}
Save this out and refresh the page in your browser. You should now have a swanky input box that
validates and gives a visual feedback to the user to tell them if their input was accepted or not.

Including a prompt
We’ve added a huge amount of usability to our form already, but there is still more we can do.
Not every input field will have obvious rules. For example, you might have a username field where you
have a very precise set of allowed characters. In this instance, it is important to give your user some
kind of message to help them complete the form. Without this prompt, you are likely going to annoy
your user if they are repeatedly failing your validation test.

To add a validation prompt, add the following line of code to your form, just under your input field.

<span id="nameError" style="display: none;">You can only use alphabetic characters, hyphens and
apostrophes</span>
Next add the following line to the else branch of your if else statement in your Javascript.
document.getElementById(x + ‘Error’).style.display = "block";
Save your file and fresh your browser. You should now be given a prompt when you enter invalid
characters.

Finally add the following line to the if branch of your if else statement.
document.getElementById(x + ‘Error’).style.display = "none";
This will clean up the prompt message once the user corrects their mistake.
Validation on form submission
The validation you’ve added so far is great because it allows the user to correct their mistakes as they
progress. The next step is to prevent the form from being submitted if any of the validation rules are
broken.

This is handy because we don’t really want to allow our user to submit a form with invalid data. Once
the form is validated on the server side, it should spit it back out with an error message. However, we
can stop it from ever getting this far by validating on the client side too.

Client side validation


So the first thing we need to do is to create a button to allow our form to be submitted.

<input type="submit" id="submit" name="submit" value="Submit" />


Next we need to add an onsubmit event. This is very similar to the onblur event we created earlier, the
only difference is it is run only when the form is submitted.

Update your form tag so it looks like this.

<form action="" onsubmit="return validateForm()">


More Javascript
Now we need to create the validateForm() function that will check the entire form for valid date.

In between the script tags, write the following.


function validateForm(){
}
Next we need to create an error count.

// Set error catcher


var error = 0;
Next we run our validateName() function.

// Check name
if(!validateName(‘name’)){
document.getElementById(‘nameError’).style.display = "block";
error++;
}
This runs the validateName() function on the name input field. If it returns false we know that the input
field did not validate and so we display our error prompt and increase the error counter by 1.

Finally we create a little catch so if there are errors the form will not submit.

// Don’t submit form if there are errors


if(error > 0){
return false;
}
Now when you save out your form you shouldn’t be able to submit it if there are errors. To successfully
submit the form you need to correct all the errors so the fields turn green.

Extending our Javascript validation


You know have a full working example of inline validation and client side validation that you can
implement on your website’s forms. Hopefully this has given you enough of a start to extend the code to
meet your requirements.
Here are some further Javascript validation functions that you can add to you code to extend it further
and help you get started making some really awesome inline validation.

Validate email addresses


HTML

<fieldset>
<label for="email">Email</label>
<input type="text" name="email" id="email" onblur="validateEmail(value)" />
<span id="emailError" style="display: none;">You must enter a valid email address</span>
</fieldset>
Javascript

// Validate email
function validateEmail(email){
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-
9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(re.test(email)){
document.getElementById(’email’).style.background =’#ccffcc’;
document.getElementById(’emailError’).style.display = "none";
return true;
}else{
document.getElementById(’email’).style.background =’#e35152′;
return false;
}
}
Validate dropdown boxes
HTML

<fieldset>
<label for="animal">Favourite Animal</label>
<select name="animal" id="animal" onblur="validateSelect(name)">
<option value="">Animals</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="badger">Badger</option>
</select>
<span class="validateError" id="animalError" style="display: none;">You must select your favourite
animal</span>
</fieldset>
Javascript

// Validate Select boxes


function validateSelect(x){
if(document.getElementById(x).selectedIndex !== 0){
document.getElementById(x).style.background =’#ccffcc’;
document.getElementById(x + ‘Error’).style.display = "none";
return true;
}else{
document.getElementById(x).style.background =’#e35152′;
return false;
}
}
Validate Radio buttons
HTML

<fieldset>
<label for="hand">Left or Right handed?</label>
<ul>
<li>
<input type="radio" name="hand" id="left" value="Left" onblur="validateRadio(id)" />
<label for="left">Left handed</label>
</li>
<li>
<input type="radio" name="hand" id="right" value="Right" onblur="validateRadio(id)" />
<label for="right">Right handed</label>
</li>
</ul>
<span class="validateError" id="handError" style="display: none;">Which hand do you use?</span>
</fieldset>
Javascript

function validateRadio(x){
if(document.getElementById(x).checked){
return true;
}else{
return false;
}
}
Validate Checkboxes
<fieldset>
<label for="terms">Terms and Conditions</label>
<ul>
<li>
<input type="checkbox" name="terms" id="accept" value="accept" onblur="validateCheckbox(id)" />
<label for="accept">Accept our <a href="#">Terms and Conditions</a></label>
</li>
</ul>
<span class="validateError" id="termsError" style="display: none;">You need to accept our terms and
conditions</span>
</fieldset>
Javascript

function validateCheckbox(x){
if(document.getElementById(x).checked){
return true;
}
return false;
}
Validate your entire form
And finally, add the following code to your validateForm() function to validate your whole form when it
is submitted.

// Validate email
if(!validateEmail(document.getElementById(’email’).value)){
document.getElementById(’emailError’).style.display = "block";
error++;
}
// Validate Radio
if(validateRadio(‘left’)){

}else if(validateRadio(‘right’)){

}else{
document.getElementById(‘handError’).style.display = "block";
error++;
}
// Validate Checkbox
if(!validateCheckbox(‘accept’)){
document.getElementById(‘termsError’).style.display = "block";
error++;
}
The full code
Here is the full code.

<!doctype html>
<html lang="en">

<meta charset="utf-8">
<title>Validation tutorial</title>
<script>
function validateName(x)
{
// Validation rule
var re = /[A-Za-z -‘]$/;
// Check input
if(re.test(document.getElementById(x).value)){
// Style green
document.getElementById(x).style.background =’#ccffcc’;
// Hide error prompt
document.getElementById(x + ‘Error’).style.display = "none";
return true;
}else{
// Style red
document.getElementById(x).style.background =’#e35152′;
// Show error prompt
document.getElementById(x + ‘Error’).style.display = "block";
return false;
}
}
// Validate email
function validateEmail(email)
{
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]
{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(re.test(email))
{
document.getElementById(’email’).style.background =’#ccffcc’;
document.getElementById(’emailError’).style.display = "none";
return true;
}else{
document.getElementById(’email’).style.background =’#e35152′;
return false;
}
}
// Validate Select boxes
function validateSelect(x)
{
if(document.getElementById(x).selectedIndex !== 0)
{
document.getElementById(x).style.background =’#ccffcc’;
document.getElementById(x + ‘Error’).style.display = "none";
return true;
}
else
{
document.getElementById(x).style.background =’#e35152′;
return false;
}
}
function validateRadio(x)
{
if(document.getElementById(x).checked)
{
return true;
}
else
{
return false;
}
}
function validateCheckbox(x)
{
if(document.getElementById(x).checked)
{
return true;
}
return false;
}
function validateForm()
{
// Set error catcher
var error = 0;
// Check name
if(!validateName(‘name’))
{
document.getElementById(‘nameError’).style.display = "block";
error++;
}
// Validate email
if(!validateEmail(document.getElementById(’email’).value))
{
document.getElementById(’emailError’).style.display = "block";
error++;
}
// Validate animal dropdown box
if(!validateSelect(‘animal’))
{
document.getElementById(‘animalError’).style.display = "block";
error++;
}
// Validate Radio
if(validateRadio(‘left’))
{

}
else if(validateRadio(‘right’))
{

}
Else
{
document.getElementById(‘handError’).style.display = "block";
error++;
}
if(!validateCheckbox(‘accept’))
{
document.getElementById(‘termsError’).style.display = "block";
error++;
}
// Don’t submit form if there are errors
if(error > 0)
{
return false;
}
}
</script>

<form action="" onsubmit="return validateForm()">


<fieldset>
<label for="name">Name</label>
<input type="text" name="name" id="name" onblur="validateName(name)" />
<span id="nameError" style="display: none;">You can only use alphabetic characters, hyphens and
apostrophes</span>
</fieldset>
<fieldset>
<label for="email">Email</label>
<input type="text" name="email" id="email" onblur="validateEmail(value)" />
<span id="emailError" style="display: none;">You must enter a valid email address</span>
</fieldset>
<fieldset>
<label for="animal">Favourite Animal</label>
<select name="animal" id="animal" onblur="validateSelect(name)">
<option value="">Animals</option>
<option value="cat">Cat</option>
<option value="dog">Dog</option>
<option value="badger">Badger</option>
</select>
<span class="validateError" id="animalError" style="display: none;">You must select your favourite
animal</span>
</fieldset>
<fieldset>
<label for="hand">Left or Right handed?</label>
<ul>
<li>
<input type="radio" name="hand" id="left" value="Left" onblur="validateRadio(id)" />
<label for="left">Left handed</label>
</li>
<li>
<input type="radio" name="hand" id="right" value="Right" onblur="validateRadio(id)" />
<label for="right">Right handed</label>
</li>
</ul>
<span class="validateError" id="handError" style="display: none;">Which hand do you use?</span>
</fieldset>
<fieldset>
<label for="terms">Terms and Conditions</label>
<ul>
<li>
<input type="checkbox" name="terms" id="accept" value="accept" onblur="validateCheckbox(id)" />
<label for="accept">Accept our <a href="#">Terms and Conditions</a></label>
</li>
</ul>
<span class="validateError" id="termsError" style="display: none;">You need to accept our terms and
conditions</span>
</fieldset>
<fieldset>
<input type="submit" id="submit" name="submit" value="Submit" />
</fieldset>
</form>
What is Bootstrap Grid System
Bootstrap grid system provides the quick and convenient way to create responsive website layouts. The
latest Bootstrap 4 version introduces the new mobile-first flexbox grid system that appropriately scales
up to 12 columns as the device or viewport size increases.
Bootstrap 4 includes predefined grid classes for quickly making grid layouts for different types of
devices like cell phones, tablets, laptops and desktops, etc. For example, you can use the .col-* classes to
create grid columns for extra small devices mobile phones in portrait mode, similarly you can use
the .col-sm-* classes to create grid columns for small screen devices like mobile phone in landscape mode,
the .col-md-* classes for medium screen devices like tablets, the .col-lg-* classes for large devices like
desktops, and the .col-xl-* classes for extra large desktop screens.
The following table summarizes some of the key features of the new grid system.

Features Extra small Small Medium Large Extra large


Bootstrap 4 Grid System <576px ≥576px ≥768px ≥992px ≥1200px

Max container width None (auto) 540px 720px 960px 1140px


Ideal for Mobile (Portrait) Mobile (Landscape) Tablets Laptops Laptops & Desktops

Class prefix .col- .col-sm- .col-md- .col-lg- .col-xl-

Number of columns 12

Gutter width 30px (15px on each side of a column)

Nestable Yes

Column ordering Yes

Above table demonstrates one important thing, applying any .col-sm-* class to an element will not only
affect its styling on small devices, but also on medium, large and extra large devices having screen width
greater than or equal to 540px, if a .col-md-*, .col-lg-* or .col-xl-* class is not present. Similarly, the .col-md-
* class will not only affect the styling of elements on medium devices, but also on large and extra large
devices if a .col-lg-* or .col-xl- class is not present.
Now the question arises how to create rows and columns using this 12 column responsive grid system.
The answer is pretty simple, at first create a container that acts as a wrapper for your rows and columns
using the .container class, after that create rows inside the container using the .row class, and to create
columns inside any row you can use the .col-*, .col-sm-*, .col-md-*, .col-lg-* and .col-xl-* classes. The
columns are actual content area where we will place our contents. Let's put all these things into real
action. Let's see how it actually works:

Creating Two Column Layouts


The following example will show you how to create two column layouts for medium, large and extra
large devices like tables, laptops and desktops etc. However, on mobile phones (screen width less than
768px), the columns will automatically become horizontal.

Example
Try this code »

<div class="container">
<!--Row with two equal columns-->
<div class="row">
<div class="col-md-6">Column left</div>
<div class="col-md-6">Column right</div>
</div>

<!--Row with two columns divided in 1:2 ratio-->


<div class="row">
<div class="col-md-4">Column left</div>
<div class="col-md-8">Column right</div>
</div>

<!--Row with two columns divided in 1:3 ratio-->


<div class="row">
<div class="col-md-3">Column left</div>
<div class="col-md-9">Column right</div>
</div>
</div>
Note: In a grid layout, content must be placed inside columns (.col and .col-*) and only columns may be
the immediate children of rows (.row). Rows should be placed inside a .container (fixed-width)
or .container-fluid (full-width) for proper padding and alignment.
Tip: Grid column widths are set in percentages, so they're always fluid and sized relative to their parent
element. In addition, each column has horizontal padding (called a gutter) for controlling the space
between individual columns.
Since the Bootstrap grid system is based on 12 columns, therefore to keep the columns in a one line (i.e.
side by side), the sum of the grid column numbers within a single row should not be greater than 12. If
you go through the above example code carefully you will find the numbers of grid columns (i.e. col-md-
*) add up to twelve (6+6, 4+8 and 3+9) for every row.

Creating Three Column Layouts


Similarly, you can create other layouts based on the above principle. For instance, the following
example will typically create three column layouts for laptops and desktops screens. It also works in
tablets in landscape mode if screen resolution is more than or equal to 992 pixels (e.g. Apple iPad).
However, in portrait mode the grid columns will be horizontal as usual.

Example
Try this code »

<div class="container">
<!--Row with three equal columns-->
<div class="row">
<div class="col-lg-4">Column left</div>
<div class="col-lg-4">Column middle</div>
<div class="col-lg-4">Column right</div>
</div>

<!--Row with three columns divided in 1:4:1 ratio-->


<div class="row">
<div class="col-lg-2">Column left</div>
<div class="col-lg-8">Column middle</div>
<div class="col-lg-2">Column right</div>
</div>

<!--Row with three columns divided unevenly-->


<div class="row">
<div class="col-lg-3">Column left</div>
<div class="col-lg-7">Column middle</div>
<div class="col-lg-2">Column right</div>
</div>
</div>
Note: If more than 12 grid columns are placed within a single row, then each group of extra columns, as
a whole, will wrap onto a new line. See column wrapping behavior.
Bootstrap Auto-layout Columns
You can also create equal width columns for all devices (extra small, small, medium, large, and extra
large) through simply using the class .col, without specifying any column number.
Let's try out the following example to understand how it exactly works:

Example
Try this code »

<div class="container">
<!--Row with two equal columns-->
<div class="row">
<div class="col">Column one</div>
<div class="col">Column two</div>
</div>

<!--Row with three equal columns-->


<div class="row">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
</div>
Additionally, you can also set the width of one column and let the sibling columns automatically resize
around it equally. You may use the predefined grid classes or inline widths.
If you try the following example you'll find columns in a row with class .col has equal width.

Example
Try this code »

<div class="container">
<!--Row with two equal columns-->
<div class="row">
<div class="col">Column one</div>
<div class="col">Column two</div>
</div>

<!--Row with three columns divided in 1:2:1 ratio-->


<div class="row">
<div class="col">Column one</div>
<div class="col-sm-6">Column two</div>
<div class="col">Column three</div>
</div>
</div>

Column Wrapping Behavior


Now we are going to create more flexible layouts that changes the column orientation based on the
viewport size. The following example will create a three column layout on large devices like laptops and
desktops, as well as on tablets (e.g. Apple iPad) in landscape mode, but on medium devices like tablets
in portrait mode (768px ≤ screen width < 992px), it will change into a two column layout where the
third column moves at the bottom of the first two columns.

Example
Try this code »

<div class="container">
<div class="row">
<div class="col-md-4 col-lg-3">Column one</div>
<div class="col-md-8 col-lg-6">Column two</div>
<div class="col-md-12 col-lg-3">Column three</div>
</div>
</div>
As you can see in the example above the sum of the medium grid column numbers (i.e. col-md-*) is 3 + 9 
+ 12 = 24 > 12, therefore the third <div> element with the class .col-md-12 that is adding the extra columns
beyond the maximum 12 columns in a .row, gets wrapped onto a new line as one contiguous unit on the
medium screen size devices.
Similarly, you can create even more adaptable layouts for your websites using the Bootstrap's grid
column wrapping feature. Here're some ready to use Bootstrap grid examples.

Creating Multi-Column Layouts with Bootstrap


With the new Bootstrap 4 mobile first flexbox grid system you can easily control how your website
layout will render on different types of devices that have different screen or viewport sizes like mobile
phones, tablets, desktops, etc. Let's consider the following illustration.

In the above illustration there are total 12 content boxes in all devices, but its placement varies
according to the device screen size, like in mobile device the layout is rendered as one column grid
layout which has 1 column and 12 rows placed above one another, whereas in tablet it is rendered as
two column grid layout which has 2 columns and 6 rows.
Further, in large screen size devices like laptops and desktops it is rendered as three column grid layout
which has 3 columns and 4 rows and finally in extra large screen devices like large desktops it is
rendered as four column grid layout which has 4 columns and 3 rows.
Now the question is how we can create such responsive layouts using this Bootstrap new grid system.
Let's start with the primary target device. Suppose our primary target device is laptop or normal
desktop. Since our laptop layout has 3 columns and 4 rows i.e. 3x4 grid layout, so the HTML code for
making such grid structure would look something like this.

Example
Try this code »
<div class="container">
<div class="row">
<div class="col-lg-4"><p>Box 1</p></div>
<div class="col-lg-4"><p>Box 2</p></div>
<div class="col-lg-4"><p>Box 3</p></div>
<div class="col-lg-4"><p>Box 4</p></div>
<div class="col-lg-4"><p>Box 5</p></div>
<div class="col-lg-4"><p>Box 6</p></div>
<div class="col-lg-4"><p>Box 7</p></div>
<div class="col-lg-4"><p>Box 8</p></div>
<div class="col-lg-4"><p>Box 9</p></div>
<div class="col-lg-4"><p>Box 10</p></div>
<div class="col-lg-4"><p>Box 11</p></div>
<div class="col-lg-4"><p>Box 12</p></div>
</div>
</div>
If you see the output of the above example in a laptop or desktop which has screen or viewport width
greater than or equal to 992px but less than 1200px, you will find the layout has 4 rows where each row
has 3 equal columns resulting in 3x4 grid layout.
Now it's time to customize our layout for other devices. Let's first start by customizing it for tablet
device. Since inside the tablet our layout rendered as 2x6 grids (i.e. 2 columns and 6 rows). So, go ahead
and add the class .col-md-6 on every column.

Example
Try this code »

<div class="container">
<div class="row">
<div class="col-lg-4 col-md-6"><p>Box 1</p></div>
<div class="col-lg-4 col-md-6"><p>Box 2</p></div>
<div class="col-lg-4 col-md-6"><p>Box 3</p></div>
<div class="col-lg-4 col-md-6"><p>Box 4</p></div>
<div class="col-lg-4 col-md-6"><p>Box 5</p></div>
<div class="col-lg-4 col-md-6"><p>Box 6</p></div>
<div class="col-lg-4 col-md-6"><p>Box 7</p></div>
<div class="col-lg-4 col-md-6"><p>Box 8</p></div>
<div class="col-lg-4 col-md-6"><p>Box 9</p></div>
<div class="col-lg-4 col-md-6"><p>Box 10</p></div>
<div class="col-lg-4 col-md-6"><p>Box 11</p></div>
<div class="col-lg-4 col-md-6"><p>Box 12</p></div>
</div>
</div>
Tip: For convenience choose your primary target device and create layout for that device first after that
add classes to make it responsive for other devices.
Similarly, you can customize the layout for extra large devices like a large desktop screen by adding the
class .col-xl-3 on each column, as every row in our extra large device layout contains 4 columns. Here's
the final code after combining the whole process.

Example
Try this code »

<div class="container">
<div class="row">
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 1</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 2</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 3</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 4</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 5</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 6</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 7</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 8</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 9</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 10</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 11</p></div>
<div class="col-lg-4 col-md-6 col-xl-3"><p>Box 12</p></div>
</div>
</div>
Tip: According to the above illustration there is no need to customize the layout for mobile phones;
since columns on extra small devices will automatically become horizontal and rendered as 1x12
column grid layout in absence of .col-* or .col-sm-* classes.

Nesting of Grid Columns


The Bootstrap grid columns are also nestable, that means you can put rows and columns inside an
existing column. However, the formula for placing the columns will be the same, i.e. the sum of column
numbers should be equal to 12 or less within a single row.

Example
Try this code »

<div class="container">
<div class="row">
<div class="col-sm-8">Column left</div>
<div class="col-sm-4">
<!--Column right with nested rows and columns-->
<div class="row">
<div class="col-12"></div>
</div>
<div class="row">
<div class="col-6"></div>
<div class="col-6"></div>
</div>
</div>
</div>
</div>

Creating Variable Width Columns


You can use the col-{breakpoint}-auto classes to size columns based on the natural width of their content.
Try out the following example to see how it works:

Example
Try this code »

<div class="container">
<div class="row justify-content-md-center">
<div class="col-md-3">Column left</div>
<div class="col-md-auto">Variable width column</div>
<div class="col-md-3">Column right</div>
</div>
<div class="row">
<div class="col">Column left</div>
<div class="col-auto">Variable width column</div>
<div class="col">Column right</div>
</div>
</div>

Alignment of Grid Columns


You can use the flexbox alignment utilities to vertically and horizontally align grid columns inside a
container. Try out the following examples to understand how it works:

Vertical Alignment of Grid Columns


You can use the classes .align-items-start, .align-items-center, and .align-items-end to align the grid columns
vertically at the top, middle and bottom of a container, respectively.

Example
Try this code »

<div class="container">
<div class="row align-items-start">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
<div class="row align-items-center">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
<div class="row align-items-end">
<div class="col">Column one</div>
<div class="col">Column two</div>
<div class="col">Column three</div>
</div>
</div>
Individual columns inside a row can also be aligned vertically. Here's an example:

Example
Try this code »

<div class="container">
<div class="row">
<div class="col align-self-start">Column one</div>
<div class="col align-self-center">Column two</div>
<div class="col align-self-end">Column three</div>
</div>
</div>
Note: You can skip the number in .col-* grid class and just use the .col class to create equal size columns
for all devices (extra small, small, medium, large, and extra large).
Horizontal Alignment of Grid Columns
You can use the classes .justify-content-start, .justify-content-center, and .justify-content-end to align the grid
columns horizontally at the left, center and right of a container, respectively. Let's check out the
following example to see how it works:

Example
Try this code »

<div class="container">
<div class="row justify-content-start">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
<div class="row justify-content-center">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
<div class="row justify-content-end">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
</div>
Alternatively, you can use the class .justify-content-around to distribute grid columns evenly with half-
size spaces on either end, whereas you can use the class .justify-content-between to distribute the grid
columns evenly where the first column placed at the start and the last column placed at the end. Try out
the following example to see how it actually works:

Example
Try this code »

<div class="container">
<div class="row justify-content-around">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
<div class="row justify-content-between">
<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
</div>
</div>
Please check out the tutoiral on css3 flexbox to learn more about flex items alignment.

Reordering of Grid Columns


You can even change the visual order of your grid columns without changing their order in actual
markup. Use the class .order-last to order the column in last, whereas use the class .order-first to order
the column at first place. Let's checkout an example:

Example
Try this code »

<div class="container">
<div class="row">
<div class="col order-last">First, but ordered at last</div>
<div class="col">Second, but unordered</div>
<div class="col order-first">Last, but ordered at first</div>
</div>
</div>
You can also use the .order-* classes to order the grid columns depending on the order numbers. Grid
column with higher order number comes after the grid column with lower order number or grid
column with no order classes. It includes support for 1 through 12 across all five grid tiers.

Example
Try this code »

<div class="container">
<div class="row">
<div class="col order-4">First, but ordered at last</div>
<div class="col">Second, but ordered at first</div>
<div class="col order-1">Last, but ordered at second</div>
</div>
</div>

Offsetting the Grid Columns


You can also move grid columns to the right for alignment purpose using the column offset classes
like .offset-sm-*, .offset-md-*, .offset-lg-*, and so on.
These classes offset the columns by simply increasing its left margin by specified number of columns.
For example, the class .offset-md-4 on column .col-md-8 moves it to the right over four columns from its
original position. Try out the following example to see how it works:

Example
Try this code »

<div class="container">
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm-8"></div>
</div>
<div class="row">
<div class="col-sm-8 offset-sm-4"><!--Column with 4 columns offset--></div>
</div>
</div>
You can also offset columns using the margin utility classes. These classes are useful in the situations
where the width of the offset is not fixed. Here's an example:

Example
Try this code »

<div class="container">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4 ml-auto"><!--Offset this column to right--></div>
</div>
<div class="row">
<div class="col-auto mr-auto"></div>
<div class="col-auto"><!--Move this column away from previous column--></div>
</div>
</div>
Note: You can use the class .col-auto to create columns that only take up as much space as needed, i.e.
the column sizes itself based on the contents.

Creating Compact Columns


You can remove the default gutters between columns to create compact layouts by adding the class .no-
gutters on .row. This class removes the negative margins from row and the horizontal padding from all
immediate children columns. Here's an example:

Example
Try this code »

<div class="row no-gutters">


<div class="col-4">Column one</div>
<div class="col-4">Column two</div>
<div class="col-4">Column three</div>
</div>

Breaking Columns to a New Line


You can also create equal-width columns that span multiple rows by inserting a <div> with .w-100 class
where you want the columns to break to a new line. Additionally, you can make these breaks responsive
by combining the .w-100 class with responsive display utility classes.

Example
Try this code »

<div class="container">
<!-- Break columns on all devices -->
<div class="row">
<div class="col">.col</div>
<div class="col">.col</div>
<div class="w-100"></div>
<div class="col">.col</div>
<div class="col">.col</div>
</div>
<!-- Break columns on all devices except extra large devices -->
<div class="row">
<div class="col">.col</div>
<div class="col">.col</div>
<div class="w-100 d-xl-none"></div>
<div class="col">.col</div>
<div class="col">.col</div>
</div>
</div>
We hope you've understood the basics of new Bootstrap 4 grid system. In next few chapters you'll learn
how to create basic web page layouts using this flexbox grid system.