Home PHP

Apache .htaccess RewriteRule Examples with PHP for Clean URLs

Our code for today will make your website URLs clean and attractive. Clean URLs are user and SEO friendly, it does not contain any query string like:

...page.php?param1=something&id=1111

Thus, giving our users and search engines (like Google) an idea what your link is all about once it was shared to social media or indexed by Google or Bing.

.htaccess rewriterule examples - first example is smashing magazine

We are going to use .htaccess (hypertext access) rewrite rules to achieve these clean URLs. The .htaccess file provide a directory level configuration that is supported by several web servers such as Apache.

Our post for today covers the following contents:

1.0 Existing Apache .htaccess Rewriterule Examples

2.0 Four Apache .htaccess Rewriterule Example Codes
2.1 URL with two parameters: letter and number
2.2 URL with one parameter: name of the PHP file
2.3 URL with one parameter: numbers
2.4 URL with one parameter: numbers with underscore

3.0 Complete .htaccess Code Used
4.0 Apache .htaccess RewriteRule Resources

1.0 Existing or Live Apache .htaccess Rewriterule Examples

Below are other example websites with clean URLs.

Of couse you know this blog, don't you?

Of couse you know this blog, don't you? :))

Chris' blog

Chris' blog

David’s blog

David’s blog

2.0 Four Apache .htaccess Rewriterule Examples

Our .htaccess and PHP files are placed in the "htaccess-clean-urls" folder.

.htaccess uses regular expressions to identify which PHP file will be loaded on the browser, based on the parameter(s) given.

We have 4 example codes below. Please note that "localhost" refers to "yoursite.com". I was using my local server when I did these examples so please keep it in mind.

2.1 URL with two parameters: letter and number

This URL:

http://localhost/htaccess-clean-urls/parameter_letter_and_number.php?param=post¶m2=143

Is equivalent to this clean URL:

http://localhost/htaccess-clean-urls/post/143

.htaccess code used:

RewriteRule ^([a-z]+)\/([0-9]+)\/?$ parameter_letter_and_number.php?param=$1&param2=$2 [NC]

PHP page used: parameter_letter_and_number.php

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Clean URL with .htaccess by https://codeofaninja.com/</title>
        
        </style>
    </head>
<body>

<h1>Parameter: Letter and Number ONLY. This is parameter_letter_and_number.php</h1>
<?php 
echo "PARAMETER VALUE 1: " . $_REQUEST['param'];
echo "<br />";
echo "PARAMETER VALUE 2: " . $_REQUEST['param2'];
?>

</body>
</html>

Output screenshot:

.htaccess RewriteRule Example - parameter and number

2.2 URL with one parameter: name of the PHP file

This URL:

http://localhost/htaccess-clean-urls/login.php
http://localhost/htaccess-clean-urls/register.php

Is equivalent to this clean URL:

http://localhost/htaccess-clean-urls/login/
http://localhost/htaccess-clean-urls/register/

.htaccess code used:

RewriteRule ^([a-z]+)\/?$ $1.php [NC]

PHP pages used:

login.php

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>login - Clean URL tutorial with .htaccess and PHP by https://codeofaninja.com/</title>
        
        </style>
    </head>
<body>

<h1>Login. This is login.php</h1>

</body>
</html>

register.php

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>register - Clean URL with .htaccess and PHP by https://codeofaninja.com/</title>
        
        </style>
    </head>
<body>

<h1>Register. This is register.php</h1>

</body>
</html>

Output Screenshots:

login page clean url

register page rewriterule example

2.3 URL with one parameter: numbers

This URL

http://localhost/htaccess-clean-urls/parameter_number.php?param=5254

Is equivalent to this clean URL:

http://localhost/htaccess-clean-urls/5254/

.htaccess code used:

RewriteRule ^([0-9]+)\/?$ parameter_number.php?param=$1 [NC]

PHP page used: parameter_number.php

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>parameter is number - Clean URL with .htaccess and PHP by https://codeofaninja.com/</title>
        
        </style>
    </head>
<body>

<h1>Parameter: Number ONLY. This is parameter_number.php</h1>
<?php echo "PARAMETER VALUE: " . $_REQUEST['param']; ?>

</body>
</html>

Output Screenshot:

htaccess rewriterule number example

2.4 URL with one parameter: numbers with underscore

This URL:

http://localhost/htaccess-clean-urls/parameter_number_and_underscore.php?param=143_5254

Is equivalent to this clean URL:

http://localhost/htaccess-clean-urls/143_5254/

.htaccess code used:

RewriteRule ^([0-9_]+)\/?$ parameter_number_and_underscore.php?param=$1 [NC]

PHP page used: parameter_number_and_underscore.php

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>parameter is number and underscore- Clean URL with .htaccess and PHP by https://codeofaninja.com/</title>
        
        </style>
    </head>
<body>

<h1>Parameter: Number and Underscore ONLY. This is parameter_number_and_underscore.php</h1>
<?php echo "PARAMETER VALUE: " . $_REQUEST['param']; ?>

</body>
</html>

Output Screenshot:

htaccess rewriterule example - number and underscore

3.0 Complete .htaccess Code Used

The following codes are the ones we used in the examples above, put into one .htaccess file.

<IfModule mod_rewrite.c>

    RewriteEngine on

    RewriteRule ^([a-z]+)\/([0-9]+)\/?$ parameter_letter_and_number.php?param=$1&param2=$2 [NC]
    
    RewriteRule ^([a-z]+)\/?$ $1.php [NC]
    
    RewriteRule ^([0-9]+)\/?$ parameter_number.php?param=$1 [NC]
    
    RewriteRule ^([0-9_]+)\/?$ parameter_number_and_underscore.php?param=$1 [NC]
    
</IfModule>

4.0 .htaccess RewriteRule Resources

If you want to learn more, here's a mod_rewrite or regex cheat sheet.
An In Depth Guide to mod_rewrite for Apache
Apache mod_rewrite

Download Source Code

You can download all the code used in this tutorial for only $9.99 $5.55!

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

If you have some questions or want to add more Apache .htaccess RewriteRule examples, please drop it in the comments section below! I will update this post once you did, thanks for your contribution!

shopping-cart-in-php-sessions
Home PHP

PHP and MySQL Shopping Cart Tutorial – Using SESSIONS To Store Cart Data

shopping-cart-in-php-sessions

Previously, we learned how to build a Shopping Cart with PHP & MySQL where we used a database to store cart items. Today, we will learn another version of it. We will use PHP session variables to store cart items.

Read more

Home PHP

How To Salt, Hash and Store Passwords Securely?

What is password hashing?

It turns a string (of any length) to a fixed length “fingerprint” that cannot be reversed. For example, my password is “i1love2coding3″, when hashed, it can be converted to a 60 character “ytwqwxpbx1oxbfvmpoaafckmat2zkdsjaxs…” which will be stored to the database.

RELATED: PHP Login Script with Session Tutorial – Step by Step Guide!

Why do we have to hash passwords?

I think the main reason why we have to hash passwords is to prevent passwords from being stolen or compromised.

You see, even if someone steal your database, they will never read your actual or cleartext password.

I know that some PHP frameworks or CMS already provide this functionality, but I believe that it is important for us to know how its implementation can be made.

php+hash+password+database+with+a+record

We are going to use a Portable PHP Password Hashing Framework called phpass (pronounced “pH pass”) recommended by a lot of forums and is used by some famous Web applications like phpBB3, WordPress, Drupal, Vanilla, etc.

This post will focus and provide you a quick grasp and basic idea on how to salt, hash and store passwords in a MySQL database. This is essential to your PHP login script.

Let’s Code

Our SQL table structure looks like this:

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(32) NOT NULL,
  `password` char(60) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

libs/PasswordHash.php – our password framework file, yes, it is just this one file. You can download it here.

libs/DbConnect.php – configuration to be connected to database.

register.php – The user registration page, this is where we are going to save the user’s password. On this example web app, we require these two fields only during registration.

<html>
    <head>
        <title>registration page - php salt and hash password - www.codeofaninja.com</title>
        <link type="text/css" rel="stylesheet" href="css/style.css" />
    </head>
<body>

<div id="loginForm">

    <?php
    // save the username and password
    if($_POST){
    
        try{
            // load database connection and password hasher library
            require 'libs/DbConnect.php';
            require 'libs/PasswordHash.php';
            
            /* 
             * -prepare password to be saved
             * -concatinate the salt and entered password 
             */
            $salt = "ipDaloveyBuohgGTZwcodeRJ1avofZ7HbZjzJbanDS8gtoninjaYj48CW" . $_POST['email'];
            $password = $salt . $_POST['password'];
            
            /* 
             * '8' - base-2 logarithm of the iteration count used for password stretching
             * 'false' - do we require the hashes to be portable to older systems (less secure)?
             */
            $hasher = new PasswordHash(8,false);
            $password = $hasher->HashPassword($password);

            // insert command
            $query = "INSERT INTO users SET email = ?, password = ?";

            $stmt = $con->prepare($query);

            $stmt->bindParam(1, $_POST['email']);
            $stmt->bindParam(2, $password);

            // execute the query
            if($stmt->execute()){
                echo "<div>Successful registration.</div>";
            }else{
                echo "<div>Unable to register. <a href='register.php'>Please try again.</a></div>";
            }
            
        }
        
        //to handle error
        catch(PDOException $exception){
            echo "Error: " . $exception->getMessage();
        }
    }
    
    // show the registration form
    else{
    ?>

    <!-- 
        -where the user will enter his email and password
        -required during registration
        -we are using HTML5 'email' type, 'required' keyword for a some validation, and a 'placeholder' for better UI
    -->
    <form action="register.php" method="post">
    
        <div id="formHeader">Registration Form</div>
        
        <div id="formBody">
            <div class="formField">
                <input type="email" name="email" required placeholder="Email" />
            </div>
            
            <div class="formField">
                <input type="password" name="password" required placeholder="Password" />
            </div>
        
            <div>
                <input type="submit" value="Register" class="customButton" />
            </div>
            <div id='userNotes'>
                Already have an account? <a href='login.php'>Login</a>
            </div>
        </div>
        
    </form>
    
    <?php
    }
    ?>
    
</div>

</body>
</html>

login.php – the user login page, we are going to check if the users’s password is valid or not .

<html>
    <head>
        <title>login page - php salt and hash password - www.codeofaninja.com</title>
        <link type="text/css" rel="stylesheet" href="css/style.css" />
    </head>
<body>

<div id="loginForm">

    <?php
    // form is submitted, check if acess will be granted
    if($_POST){
    
        try{
            // load database connection and password hasher library
            require 'libs/DbConnect.php';
            require 'libs/PasswordHash.php';
            
            // prepare query
            $query = "select email, password from users where email = ? limit 0,1";
            $stmt = $con->prepare( $query );
            
            // this will represent the first question mark
            $stmt->bindParam(1, $_POST['email']);
            
            // execute our query
            $stmt->execute();
            
            // count the rows returned
            $num = $stmt->rowCount();
            
            if($num==1){
                
                //store retrieved row to a 'row' variable
                $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
                // hashed password saved in the database
                $storedPassword = $row['password'];
                
                // salt and entered password by the user
                $salt = "ipDaloveyBuohgGTZwcodeRJ1avofZ7HbZjzJbanDS8gtoninjaYj48CW";
                $postedPassword = $_POST['password'];
                $saltedPostedPassword = $salt . $postedPassword;
            
                // instantiate PasswordHash to check if it is a valid password
                $hasher = new PasswordHash(8,false);
                $check = $hasher->CheckPassword($saltedPostedPassword, $storedPassword);
                
                /*
                 * access granted, for the next steps,
                 * you may use my php login script with php sessions tutorial :) 
                 */
                if($check){
                    echo "<div>Access granted.</div>";
                }
                
                // $check variable is false, access denied.
                else{
                    echo "<div>Access denied. <a href='login.php'>Back.</a></div>";
                }
                
            }
            
            // no rows returned, access denied
            else{
                echo "<div>Access denied. <a href='login.php'>Back.</a></div>";
            }
            
        }
        //to handle error
        catch(PDOException $exception){
            echo "Error: " . $exception->getMessage();
        }
    
        
    }
    
    // show the registration form
    else{
    ?>

    <!-- 
        -where the user will enter his email and password
        -required during login
        -we are using HTML5 'email' type, 'required' keyword for a some validation, and a 'placeholder' for better UI
    -->
    <form action="login.php" method="post">
    
        <div id="formHeader">Website Login</div>
        
        <div id="formBody">
            <div class="formField">
                <input type="email" name="email" required placeholder="Email" />
            </div>
            
            <div class="formField">
                <input type="password" name="password" required placeholder="Password" />
            </div>
        
            <div>
                <input type="submit" value="Login" class="customButton" />
            </div>
        </div>
        <div id='userNotes'>
            New here? <a href='register.php'>Register for free</a>
        </div>
    </form>
    
    <?php
    }
    ?>
    
</div>

</body>
</html>

css/style.css – just for some styling.

body{
    font: 20px "Lucida Grande", Tahoma, Verdana, sans-serif;
    color: #404040;
}

input[type=text],
input[type=password],
input[type=email]{
    padding:10px;
    width:100%;
}

#userNotes{
    font-size:0.7em;
    text-align:left;
    padding:10px;
}

#actions{
    padding:10px;
}

#infoMesssage{
    padding:10px;
    background-color:#BDE5F8;
    color:black;
    font-size:0.8em;
}


#successMessage{
    padding:10px;
    background-color:green;
    color:white;
}

#failedMessage{
    padding:10px;
    background-color:red;
    color:white;
    font-size:15px;
}

#formBody{
    padding:5px;
}

#loginForm{
    
    text-align:center;
    border:thin solid #000;
    width:300px;
    margin:7em auto 0 auto;
}

#formHeader{
    border-bottom:thin solid gray;
    padding:10px;
    background:#f3f3f3;
}

#loginForm{
    
}

.customButton {
    padding:5px;
    width:100%;
    -moz-box-shadow:inset 0px 1px 0px 0px #bbdaf7;
    -webkit-box-shadow:inset 0px 1px 0px 0px #bbdaf7;
    box-shadow:inset 0px 1px 0px 0px #bbdaf7;
    background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #79bbff), color-stop(1, #378de5) );
    background:-moz-linear-gradient( center top, #79bbff 5%, #378de5 100% );
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#79bbff', endColorstr='#378de5');
    background-color:#79bbff;
    -moz-border-radius:6px;
    -webkit-border-radius:6px;
    border-radius:6px;
    border:1px solid #84bbf3;
    display:inline-block;
    color:#ffffff;
    font-family:arial;
    font-size:15px;
    font-weight:bold;
    text-decoration:none;
    text-shadow:1px 1px 0px #528ecc;
    cursor:pointer;
}

.customButton:hover {
    background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #378de5), color-stop(1, #79bbff) );
    background:-moz-linear-gradient( center top, #378de5 5%, #79bbff 100% );
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#378de5', endColorstr='#79bbff');
    background-color:#378de5;
}

.customButton:active {
    position:relative;
    top:1px;
}
/* This imageless css button was generated by CSSButtonGenerator.com */

Demo Screenshots

Empty database.

Empty database.

Registration form.

Registration form.

Just a sample HTML5 validation.

Just a sample HTML5 validation.

After successful registration.

After successful registration.

Our database will have the record.  Notice the password field, it was hashed.

Our database will have the record.
Notice the password field, it was hashed.

Our login page.

Our login page.

Just an example HTML5 validation during login.

Just an example HTML5 validation during login.

Login with wrong credentials.

Login with wrong credentials.

After login with correct username and password.

After login with correct username and password.

Some references

Please note that password hashing is often wrongly referred to as “password encryption”. Hashing is a more appropriate term since encryption is something that is supposed to be easily reversible. ~ phpass

If there’s something you want to add, something wrong, or any questions, please let me know in the comments. Thanks a lot!

You can download all the code used in this tutorial for only $9.99 $5.55!

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

Thank you for learning from our post about: How To Salt, Hash and Store Passwords Securely?

RELATED: PHP Login Script with Session Tutorial – Step by Step Guide!

Home PHP

How To Create Dynamic Pie Chart in PHP or JavaScript with MySQL?

Graphical or visual representation of data is usually a requirement for a software, mostly, business apps. Today I'm going to show you the two and free ways to generate dynamic Pie Charts for your web applications.

We say "dynamic" because the data that will be shown in the pie chart were pulled from a database which can be updated frequently.

You can also create other types of charts such as bar charts, line charts, and many other types of charts, but in this post, we will cover pie charts only which can give you a good idea on how to create dynamic charts.

how to create dynamic pie chart in php or javascript

In this post, we will cover the following topics:

1.0 Dummy Database for Dynamic Pie Chart
2.0 Using LibChart to Create Dynamic Charts (PHP)
3.0 Using the Google Chart Tools (JavaScript)

The first way I will give you is generating a chart using PHP, and in the second way, we will use JavaScript.

1.0 Dummy Database for Dynamic Pie Chart

This will be our example table and data.

--
-- Table structure for table `programming_languages`
--

CREATE TABLE IF NOT EXISTS `programming_languages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `ratings` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

--
-- Dumping data for table `programming_languages`
--

INSERT INTO `programming_languages` (`id`, `name`, `ratings`) VALUES
(1, 'C', 17),
(2, 'Java', 16),
(3, 'C++', 9),
(4, 'Objective-C', 9),
(5, 'C#', 7),
(6, 'Basic', 6),
(7, 'PHP', 5),
(8, 'Phyton', 3),
(9, 'Pearl', 2),
(10, 'Ruby', 1);

2.0 Using LibChart to Create Dynamic Charts (PHP)

We will do the first way using the LibChart, the simple and free PHP chart drawing library.

Here's a code:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Pie Chart Demo (LibChart)- https://codeofaninja.com/</title>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15" />
</head>
<body>

<?php
    //include the library
    include "libchart/libchart/classes/libchart.php";

    //new pie chart instance
    $chart = new PieChart( 500, 300 );

    //data set instance
    $dataSet = new XYDataSet();
   
    //actual data
    //get data from the database
   
    //include database connection
    include 'db_connect.php';

    //query all records from the database
    $query = "select * from programming_languages";

    //execute the query
    $result = $mysqli->query( $query );

    //get number of rows returned
    $num_results = $result->num_rows;

    if( $num_results > 0){
   
        while( $row = $result->fetch_assoc() ){
            extract($row);
            $dataSet->addPoint(new Point("{$name} {$ratings})", $ratings));
        }
   
        //finalize dataset
        $chart->setDataSet($dataSet);

        //set chart title
        $chart->setTitle("Tiobe Top Programming Languages for June 2012");
       
        //render as an image and store under "generated" folder
        $chart->render("generated/1.png");
   
        //pull the generated chart where it was stored
        echo "<img alt='Pie chart'  src='generated/1.png' style='border: 1px solid gray;'/>";
   
    }else{
        echo "No programming languages found in the database.";
    }
?>

</body>
</html>

Some advantage of using the LibChart includes: Free, it will work even offline or if you're just debugging on your localhost, easy to use and can be used for multiple data sets.

Some disadvantages are: It is limited to Line, Bar and Pie charts only and it works with PHP5 only.

3.0 Using the Google Chart Tools (JavaScript)

Google chart tools are powerful, simple to use, and also free.

Our index.php code:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
        <title>Pie Chart Demo (Google VAPI) - https://codeofaninja.com/</title>
    </head>
   
<body style="font-family: Arial;border: 0 none;">
    <!-- where the chart will be rendered -->
    <div id="visualization" style="width: 600px; height: 400px;"></div>

    <?php

    //include database connection
    include 'db_connect.php';

    //query all records from the database
    $query = "select * from programming_languages";

    //execute the query
    $result = $mysqli->query( $query );

    //get number of rows returned
    $num_results = $result->num_rows;

    if( $num_results > 0){

    ?>
        <!-- load api -->
        <script type="text/javascript" src="http://www.google.com/jsapi"></script>
       
        <script type="text/javascript">
            //load package
            google.load('visualization', '1', {packages: ['corechart']});
        </script>

        <script type="text/javascript">
            function drawVisualization() {
                // Create and populate the data table.
                var data = google.visualization.arrayToDataTable([
                    ['PL', 'Ratings'],
                    <?php
                    while( $row = $result->fetch_assoc() ){
                        extract($row);
                        echo "['{$name}', {$ratings}],";
                    }
                    ?>
                ]);

                // Create and draw the visualization.
                new google.visualization.PieChart(document.getElementById('visualization')).
                draw(data, {title:"Tiobe Top Programming Languages for June 2012"});
            }

            google.setOnLoadCallback(drawVisualization);
        </script>
    <?php

    }else{
        echo "No programming languages found in the database.";
    }
    ?>
   
</body>
</html>

The advantages of using Google chart tools include: Free, easy to use, multiple data sets, and has wide range of charts types that you can use, looks good and interactive.

I think the only disadvantage will be: you cannot use it when you don't have internet connection.

Download Source Code

You can download all the code used in this tutorial for only $9.99 $5.55!

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

How about you, do you have any other suggestions or solutions on how to create dynamic pie chart in PHP or JavaScript? Thanks for sharing it in the comments section below!

Home PHP

Append Subtitle/Caption Image Using PHP and Hide It with CSS

Note: People say it isn’t actually a watermark, the image appended can be called a “Caption” or “Hidden Subtitle”. So in this post, when I say “watermark”, it refers to the ”Caption” or “Hidden Subtitle”.
Nowadays I see many websites with image contents. Funny images, interesting images, cosplay, art and many more kinds of images. Many people don’t want to hotlink or copy the image link and share it to any social networking site such as Facebook, instead they copy or download the image (using browser’s “Save image as” option) and upload it to their own account without linking it to the source or website where they found it.

One solution websites do is to append a watermark on their images. The don’t want this watermark to be shown on their website but they want it to appear when the user went to the actual image link or when this image was copied or downloaded.
An example website the does this is 9gag.com. When you see the image on their site, it does not have any watermark. But when you try to save the image, the watermark will appear, appended at the bottom part of the image, it is in white background.
Today we’re going to do a code the does something like that.

DOWNLOAD CODE LIVE DEMO

  • Append a watermark at the bottom part of the image using PHP
  • Hide it using CSS

First, we need to prepare:

  • Sample image – the image you want to put a watermark
  • Watermark image – the image that will be put as watermark on the sample image
    • As for the sample image, we’re going to use this image of my pets (yes, my pets):

      Append Subtitle/Caption Image Using PHP and Hide It with CSS

      For the watermark image:

      This will be appended on the main image

      This will be appended on the main image

      Some notes:

      • “sample.jpg” and “watermark.jpg” should be your variable
      • PHP GD library should be enabled on your server

      Our index.php, we are going to have the following code:

      <?php
      
          //set the header
          header( "Content-type: image/jpg" );
      
          //get image sizes first
          $image_size = getimagesize( "sample.jpg" );
          $watermark_size = getimagesize( "watermark.jpg" );
      
          $image_size_width = $image_size[0];
          $image_size_height = $image_size[1];
      
          $watermark_size_width = $watermark_size[0];
          $watermark_size_height = $watermark_size[1];
      
          //create images
          $main_img = imagecreatefromjpeg( "sample.jpg" );
          $watermark = imagecreatefromjpeg( "watermark.jpg" );
      
          //create canvas
          $canvas = imagecreatetruecolor(
      
              $image_size_width, //width of main image
              $image_size_height + $watermark_size_height //this is the new height, height of main image plus watermark image
          ) or die('Cannot Initialize new GD image stream.');
      
          
          //set white background of canvas
          $bg = imagecolorallocate( $canvas, 255, 255, 255 );
          imagefill ( $canvas, 0, 0, $bg );
      
      
          //paste main image to the canvas
          imagecopymerge(
              $canvas, 
              $main_img, 
              0, //main_img x coordinate ( distance from left side of main_img )
              0, //main_img y coordinate ( distance form top of main_img )
              0, //main_img x coordinate image ( distance from left side of main_img )
              0, //main_img y coordinate image ( distance from top side of main_img )
              $image_size_width, //main_img width
              $image_size_height, //main_img height
              100 //the opacity of main_img
      
          );
      
          //paste the watermark image to the canvas
          imagecopymerge(
              $canvas, 
              $watermark, 
              0, //watermark x coordinate ( distance from left side of main_img )
              $image_size_height, //watermark y coordinate ( distance form top of main_img )
              0, //watermark x coordinate image ( distance from left side of watermark )
              0, //watermark y coordinate image ( distance from top side of watermark ) 
              $watermark_size_width, //watermark width
              $watermark_size_height, //watermark height
              100 //the opacity of watermark
      
          );
      
          //show the new image
          imagejpeg( $canvas );
      
          //if you want to save it to your server directory, just add the second param
          //something like:
          //imagejpeg($canvas, 'your_directory/new_img.jpg');
      
          imagedestroy( $canvas );
          imagedestroy( $main_img );
          imagedestroy( $watermark );
      
      ?>
      

      new_img

      Now, we are going to the second part of this post. We are going to show the output image on a webpage, but the watermark is hidden using CSS.

      Our page.php should have the following code:

      <html>
      
          <head>
      
              <title></title>
      
          </head>
      
      <body>
      
          <div style='font-weight:bold; font-size:18px;'>The image below has a watermark, but it was hidden.</div>
          <div style='margin:5px 0;'>Try to go to the actual image by doing 'open image in new tab' or downloading it.</div>
      
      
          <div style='overflow:hidden;'>
      
              <!-- -30px here is the height of our watermark -->
              <img src='new_img.jpg' style='margin:0 0 -30px 0;' />
      
          </div>
      
      </body>
      </html>
      

      See the live demo for the output! :)

Home PHP

PHP CRUD Tutorial for Beginners – Step By Step Guide!

Previously, we learned how to run your first PHP script. This time, we we learn CRUD operations with PHP and MySQL. CRUD stands for Create, Read, Update and Delete database records.

We will cover the following topics

1.0 Overview
2.0 Program output
3.0 File structure

4.0 Prepare the database
4.1 Create the database
4.2 Create the database table
4.3 Dump sample data on the table
4.4 Create database connection file
4.5 Output

5.0 Create or insert record in PHP
5.1 HTML5 boilerplate for create.php
5.2 HTML form to input new record data
5.3 Code create a new record
5.4 Output

6.0 Read records in PHP
6.1 Basic HTML code for index.php
6.2 Read records from the database
6.3 Add HTML table with heading
6.4 Add HTML table body
6.5 Output

7.0 Read one record in PHP
7.1 Basic HTML code for read_one.php
7.2 Read records from the database
7.3 Display record details
7.4 Output

8.0 Update record in PHP
8.1 Basic HTML code for update.php
8.2 Read a record by ID parameter
8.3 HTML form to update a record
8.4 Code to update the record
8.5 Output

9.0 Delete record in PHP
9.1 Tell the user if record was deleted
9.2 JavaScript to confirm record deletion
9.3 Delete record from the database

10.0 Pagination in PHP
10.1 Set pagination variables
10.2 Add LIMIT clause in SELECT query
10.3 Count total number of records
10.4 Include paging file
10.5 Create paging.php
10.6 Add first page button
10.7 Add clickable page numbers
10.8 Add last page button
10.9 Output

11.0 File upload in PHP
11.1 Add HTML "file" field
11.2 Add "image" field
11.3 Set variables for file upload
11.4 Make sure submitted file is a real image
11.5 Make sure certain file types are allowed
11.6 Make sure file does not exist
11.7 make sure submitted file is not too large
11.8 Make sure the 'uploads' folder exists
11.9 Try to upload the file
11.10 Output

12.0 Show uploaded image in PHP
12.1 Add image field in query
12.2 Add HTML image tag
12.3 Output

13.0 How to run the source code?
14.0 Download LEVEL 1 source code
15.0 Download LEVEL 2 source code
16.0 Download LEVEL 3 source code
17.0 Download ALL LEVELS

18.0 Online resources
19.0 What's next?
20.0 Related tutorials
21.0 Notes

1.0 Overview

This tutorial is for your if:

  • You need a high quality and updated reference for a PHP CRUD tutorial.
  • You need to learn how to do CRUD operations in PHP and MySQL.
  • You are beginner in this kind of PHP web programming.

Coding CRUD with PHP and MySQL is one of the basics. PHP web programmers must be able to code it with less effort. We can perform this task using any of the three PHP Database extensions:

  1. Using the MySQL extension.
  2. Using the MySQLi extension.
  3. Using the PDO extension.

PHP 5.5 deprecated the MySQL extension. It is not recommended to use these days.

If you are programming with PHP, you'll have to use either MySQLi (i means improved) or PDO extension.

With that in mind, we will use the PDO extension. It is the newest and actively developed way of programming these CRUD grids.

2.0 PHP CRUD tutorial program output

We usually have three LEVELS of source code output. But WHY? Because I believe in "Learning Progression" to ensure efficient learning. Learn more

Below are some screenshots of our script's output. You can click an image to view the larger version of it. Use the left and right arrow to navigate through the screenshots.

Please note that the following images are just output previews. New features might be added already the time you are reading this.

2.1 LEVEL 1 source code output


2.2 LEVEL 2 source code output


2.3 LEVEL 3 source code output


The LEVEL 2 and LEVEL 3 source code outputs proves that you can add and customize more features. It's easier and faster if you will learn by following our tutorial below.

Downloading our source codes is your huge advantage as well. For now, let's proceed to the step by step tutorial of our LEVEL 1 source code. Enjoy!

3.0 Project file structure

Our PHP CRUD tutorial will contain the following main files.

  • dev/products.sql – contains the database table structure and sample data used in this project. Once you created your database in PhpMyAdmin, you can import this file.
  • config/database.php – used for database connection and configuration.
  • create.php – used for creating a new record. It contains an HTML form where the user can enter details for a new record.
  • index.php – used for reading records from the database. It uses an HTML table to display the data retrieved from the MySQL database.
  • read_one.php – used for reading one or single record from database. It uses an HTML table to display the data retrieved from the MySQL database.
  • update.php – used for updating a record. It uses an HTML form which will be filled out with data based on the given “id” parameter.
  • delete.php – used for deleting a record. It accepts an “id” parameter and deletes the record with it. Once it execute the delete query, it will redirect the user to the index.php page.

4.0 Prepare the database

4.1 Create the database

On your PhpMyAdmin, create a database named "php_beginner_crud_level_1".

If you're not sure how to do it, please take a look at the following example. Follow only the "create database" part.

4.2 Create the database table

Next, run the following SQL code. This is to create our "products" database table. If you're not sure how to do this, take a look at this resource.

--
-- Table structure for table `products`
--

CREATE TABLE IF NOT EXISTS `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `description` text NOT NULL,
  `price` double NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;

4.3 Dump sample data on the table

Again, run the following SQL code on your PhpMyAdmin. This will insert the sample data or record on our 'products' database table.

--
-- Dumping data for table `products`
--

INSERT INTO `products` (`id`, `name`, `description`, `price`, `created`, `modified`) VALUES
(1, 'Basketball', 'A ball used in the NBA.', 49.99, '2015-08-02 12:04:03', '2015-08-06 06:59:18'),
(3, 'Gatorade', 'This is a very good drink for athletes.', 1.99, '2015-08-02 12:14:29', '2015-08-06 06:59:18'),
(4, 'Eye Glasses', 'It will make you read better.', 6, '2015-08-02 12:15:04', '2015-08-06 06:59:18'),
(5, 'Trash Can', 'It will help you maintain cleanliness.', 3.95, '2015-08-02 12:16:08', '2015-08-06 06:59:18'),
(6, 'Mouse', 'Very useful if you love your computer.', 11.35, '2015-08-02 12:17:58', '2015-08-06 06:59:18'),
(7, 'Earphone', 'You need this one if you love music.', 7, '2015-08-02 12:18:21', '2015-08-06 06:59:18'),
(8, 'Pillow', 'Sleeping well is important.', 8.99, '2015-08-02 12:18:56', '2015-08-06 06:59:18');

As you may have noticed, steps 1 and 2 are both SQL queries. Yes, they can run at the same time. But I wanted it to be on separate steps to emphasize those SQL queries' purpose.

4.4 Create database connection file

This section will answer the question: how to connect to MySQL database with PDO?

  • Create "php-beginner-crud-level-1" folder and open it.
  • Create "config" folder and open it.
  • Create database.php file.
  • Place the following code inside it.
<?php
// used to connect to the database
$host = "localhost";
$db_name = "php_beginner_crud_level_1";
$username = "root";
$password = "";
 
try {
    $con = new PDO("mysql:host={$host};dbname={$db_name}", $username, $password);
}
 
// show error
catch(PDOException $exception){
    echo "Connection error: " . $exception->getMessage();
}
?>

4.5 Output

We have set up the database successfully! The only output we have so far is the database, database table and sample records we setup via PhpMyAdmin.

Let's proceed to the next section below.

5.0 Create or insert record in PHP

5.1 HTML5 boilerplate for create.php

We use Bootstrap user interface for this project. If you are not familiar with Bootstrap, please learn our Bootstrap Tutorial for Beginners.

  • Go back to "php-beginner-crud-level-1" folder.
  • Create a new "create.php" file.
  • Place the code following code inside the create.php file.
<!DOCTYPE HTML>
<html>
<head>
    <title>PDO - Create a Record - PHP CRUD Tutorial</title>
     
    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
         
</head>
<body>
 
    <!-- container -->
    <div class="container">
  
        <div class="page-header">
            <h1>Create Product</h1>
        </div>
     
    <!-- html form to create product will be here -->
         
    </div> <!-- end .container -->
     
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
 
</body>
</html>

5.2 HTML form to input new record data

Now we are going to start answering the question: how to create a record with PDO?

The code below will create an HTML form with input fields that matches the fields in the database. Replace <!-- html form to create product will be here --> comment of the previous section with the following code.

<!-- PHP insert code will be here -->

<!-- html form here where the product information will be entered -->
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post">
	<table class='table table-hover table-responsive table-bordered'>
		<tr>
			<td>Name</td>
			<td><input type='text' name='name' class='form-control' /></td>
		</tr>
		<tr>
			<td>Description</td>
			<td><textarea name='description' class='form-control'></textarea></td>
		</tr>
		<tr>
			<td>Price</td>
			<td><input type='text' name='price' class='form-control' /></td>
		</tr>
		<tr>
			<td></td>
			<td>
				<input type='submit' value='Save' class='btn btn-primary' />
				<a href='index.php' class='btn btn-danger'>Back to read products</a>
			</td>
		</tr>
	</table>
</form>

5.3 Code to create a new record

We are still working in the create.php file. Once the user filled out the form and clicked the save button, the code below will save it to the MySQL database.

Replace <!-- PHP insert code will be here --> comment of the previous section with the following code.

<?php
if($_POST){

	// include database connection
	include 'config/database.php';

	try{
	
		// insert query
		$query = "INSERT INTO products SET name=:name, description=:description, price=:price, created=:created";

		// prepare query for execution
		$stmt = $con->prepare($query);

		// posted values
		$name=htmlspecialchars(strip_tags($_POST['name']));
		$description=htmlspecialchars(strip_tags($_POST['description']));
		$price=htmlspecialchars(strip_tags($_POST['price']));

		// bind the parameters
		$stmt->bindParam(':name', $name);
		$stmt->bindParam(':description', $description);
		$stmt->bindParam(':price', $price);
		
		// specify when this record was inserted to the database
		$created=date('Y-m-d H:i:s');
		$stmt->bindParam(':created', $created);
		
		// Execute the query
		if($stmt->execute()){
			echo "<div class='alert alert-success'>Record was saved.</div>";
		}else{
			echo "<div class='alert alert-danger'>Unable to save record.</div>";
		}
		
	}
	
	// show error
	catch(PDOException $exception){
		die('ERROR: ' . $exception->getMessage());
	}
}
?>

5.4 Output

Congrats! For the first time, we can now see an output on a webpage. Go to this URL: http://localhost/php-beginner-crud-level-1/create.php to see the output that looks like the following images.

When user fill out the form.

When user submitted the form.

New record added to database.

6.0 Read records in PHP

6.1 Basic HTML code for index.php

Create new index.php file. We prepare this to read records from the database. It answers the question: how to read records with PDO?

Place the following code inside the index.php file.

<!DOCTYPE HTML>
<html>
<head>
	<title>PDO - Read Records - PHP CRUD Tutorial</title>
	
	<!-- Latest compiled and minified Bootstrap CSS -->
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
		
	<!-- custom css -->
	<style>
	.m-r-1em{ margin-right:1em; }
	.m-b-1em{ margin-bottom:1em; }
	.m-l-1em{ margin-left:1em; }
	.mt0{ margin-top:0; }
	</style>

</head>
<body>

    <!-- container -->
    <div class="container">
 
        <div class="page-header">
            <h1>Read Products</h1>
        </div>
	
        <!-- PHP code to read records will be here -->
		
    </div> <!-- end .container -->
	
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<!-- confirm delete record will be here -->

</body>
</html>

6.2 Read records from the database

This time we will read records from the database.

Replace <!-- PHP code to read records will be here --> comment of the previous section with the following code.

<?php
// include database connection
include 'config/database.php';

// delete message prompt will be here

// select all data
$query = "SELECT id, name, description, price FROM products ORDER BY id DESC";
$stmt = $con->prepare($query);
$stmt->execute();

// this is how to get number of rows returned
$num = $stmt->rowCount();

// link to create record form
echo "<a href='create.php' class='btn btn-primary m-b-1em'>Create New Product</a>";

//check if more than 0 record found
if($num>0){

	// data from database will be here
	
}

// if no records found
else{
	echo "<div class='alert alert-danger'>No records found.</div>";
}
?>

6.3 Add HTML table with heading

This is the HTML table that will hold and display data from the database.

Replace // data from database will be here comment of the previous section with the following code.

echo "<table class='table table-hover table-responsive table-bordered'>";//start table

	//creating our table heading
	echo "<tr>";
		echo "<th>ID</th>";
		echo "<th>Name</th>";
		echo "<th>Description</th>";
		echo "<th>Price</th>";
		echo "<th>Action</th>";
	echo "</tr>";
	
	// table body will be here

// end table
echo "</table>";

6.4 Add HTML table body

This part is where we will loop through the list of records from the database. This loop will create the rows of data on our HTML table.

Replace // table body will be here comment of the previous section with the following code.

// retrieve our table contents
// fetch() is faster than fetchAll()
// http://stackoverflow.com/questions/2770630/pdofetchall-vs-pdofetch-in-a-loop
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
	// extract row
	// this will make $row['firstname'] to
	// just $firstname only
	extract($row);
	
	// creating new table row per record
	echo "<tr>";
		echo "<td>{$id}</td>";
		echo "<td>{$name}</td>";
		echo "<td>{$description}</td>";
		echo "<td>&#36;{$price}</td>";
		echo "<td>";
			// read one record 
			echo "<a href='read_one.php?id={$id}' class='btn btn-info m-r-1em'>Read</a>";
			
			// we will use this links on next part of this post
			echo "<a href='update.php?id={$id}' class='btn btn-primary m-r-1em'>Edit</a>";

			// we will use this links on next part of this post
			echo "<a href='#' onclick='delete_user({$id});'  class='btn btn-danger'>Delete</a>";
		echo "</td>";
	echo "</tr>";
}

6.5 Output

Go to this URL http://localhost/php-beginner-crud-level-1/index.php to see the records retrieved from the database. It will look like the image below.

7.0 Read one record in PHP

7.1 Basic HTML code for read_one.php

Create new read_one.php file. This is where we will read and display the details of a single database record. Place the following code inside read_one.php file.

<!DOCTYPE HTML>
<html>
<head>
	<title>PDO - Read One Record - PHP CRUD Tutorial</title>

    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

</head>
<body>


    <!-- container -->
    <div class="container">
 
        <div class="page-header">
            <h1>Read Product</h1>
        </div>
		
        <!-- PHP read one record will be here -->

        <!-- HTML read one record table will be here -->

	</div> <!-- end .container -->
	
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</body>
</html>

7.2 Read one record from the database

The following code is how we retrieve a single database record.

Replace <!-- PHP read one record will be here --> comment of the previous section with the following code.

<?php
// get passed parameter value, in this case, the record ID
// isset() is a PHP function used to verify if a value is there or not
$id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');

//include database connection
include 'config/database.php';

// read current record's data
try {
	// prepare select query
	$query = "SELECT id, name, description, price FROM products WHERE id = ? LIMIT 0,1";
	$stmt = $con->prepare( $query );

	// this is the first question mark
	$stmt->bindParam(1, $id);

	// execute our query
	$stmt->execute();

	// store retrieved row to a variable
	$row = $stmt->fetch(PDO::FETCH_ASSOC);

	// values to fill up our form
	$name = $row['name'];
	$description = $row['description'];
	$price = $row['price'];
}

// show error
catch(PDOException $exception){
	die('ERROR: ' . $exception->getMessage());
}
?>

7.3 Display record details

The following HTML table will hold and display the details of a single database record. Open read_one.php file. Replace <!-- HTML read one record table will be here --> comment with the following code.

<!--we have our html table here where the record will be displayed-->
<table class='table table-hover table-responsive table-bordered'>
	<tr>
		<td>Name</td>
		<td><?php echo htmlspecialchars($name, ENT_QUOTES);  ?></td>
	</tr>
	<tr>
		<td>Description</td>
		<td><?php echo htmlspecialchars($description, ENT_QUOTES);  ?></td>
	</tr>
	<tr>
		<td>Price</td>
		<td><?php echo htmlspecialchars($price, ENT_QUOTES);  ?></td>
	</tr>
	<tr>
		<td></td>
		<td>
			<a href='index.php' class='btn btn-danger'>Back to read products</a>
		</td>
	</tr>
</table>

7.4 Output

To read one record from the database, try to click any "Read" button from our index.php file. You can also go to this URL http://localhost/php-beginner-crud-level-1/read_one.php?id=9 to see an output like the image below.

8.0 Update record in PHP

8.1 Basic HTML code for udpate.php

Create new "update.php" file. We are preparing to update a selected record from the database. This will answer the question: how to update a record with PDO?

Place the following code inside the new update.php file.

<!DOCTYPE HTML>
<html>
<head>
	<title>PDO - Update a Record - PHP CRUD Tutorial</title>
	
    <!-- Latest compiled and minified Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
		
</head>
<body>

    <!-- container -->
    <div class="container">
 
        <div class="page-header">
            <h1>Update Product</h1>
        </div>
	
        <!-- PHP read record by ID will be here -->

        <!-- HTML form to update record will be here -->
		
    </div> <!-- end .container -->
	
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</body>
</html>

8.2 Read a record by ID parameter

We have to get the record ID and store it in the $id variable. We access the $_GET['id'] variable to do it.

What we are trying to do here is to get the related data based on the given record ID. This is the way to auto-fill the HTML form with existing data from the database.

Replace <!-- PHP read record by ID will be here --> comment of the previous section with the following code.

<?php
// get passed parameter value, in this case, the record ID
// isset() is a PHP function used to verify if a value is there or not
$id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');

//include database connection
include 'config/database.php';

// read current record's data
try {
	// prepare select query
	$query = "SELECT id, name, description, price FROM products WHERE id = ? LIMIT 0,1";
	$stmt = $con->prepare( $query );
	
	// this is the first question mark
	$stmt->bindParam(1, $id);
	
	// execute our query
	$stmt->execute();
	
	// store retrieved row to a variable
	$row = $stmt->fetch(PDO::FETCH_ASSOC);
	
	// values to fill up our form
	$name = $row['name'];
	$description = $row['description'];
	$price = $row['price'];
}

// show error
catch(PDOException $exception){
	die('ERROR: ' . $exception->getMessage());
}
?>

8.3 HTML form to update a record

This form shows data retrieved using the previous section's code. We read a single record from the database, based on given ID parameter.

Open update.php file. Replace <!-- HTML form to update record will be here --> comment with the following code.

<!-- PHP post to update record will be here -->

<!--we have our html form here where new record information can be updated-->
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"] . "?id={$id}");?>" method="post">
	<table class='table table-hover table-responsive table-bordered'>
		<tr>
			<td>Name</td>
			<td><input type='text' name='name' value="<?php echo htmlspecialchars($name, ENT_QUOTES);  ?>" class='form-control' /></td>
		</tr>
		<tr>
			<td>Description</td>
			<td><textarea name='description' class='form-control'><?php echo htmlspecialchars($description, ENT_QUOTES);  ?></textarea></td>
		</tr>
		<tr>
			<td>Price</td>
			<td><input type='text' name='price' value="<?php echo htmlspecialchars($price, ENT_QUOTES);  ?>" class='form-control' /></td>
		</tr>
		<tr>
			<td></td>
			<td>
				<input type='submit' value='Save Changes' class='btn btn-primary' />
				<a href='index.php' class='btn btn-danger'>Back to read products</a>
			</td>
		</tr>
	</table>
</form>

8.4 Code to update the record

The following code will save the changes in the database. That is if the user change some value on the form and hit the "Save Changes" button.

Replace <!-- PHP post to update record will be here --> comment of the previous section with the following code.

<?php

// check if form was submitted
if($_POST){
	
	try{
	
		// write update query
		// in this case, it seemed like we have so many fields to pass and 
		// it is better to label them and not use question marks
		$query = "UPDATE products 
					SET name=:name, description=:description, price=:price 
					WHERE id = :id";

		// prepare query for excecution
		$stmt = $con->prepare($query);

		// posted values
		$name=htmlspecialchars(strip_tags($_POST['name']));
		$description=htmlspecialchars(strip_tags($_POST['description']));
		$price=htmlspecialchars(strip_tags($_POST['price']));

		// bind the parameters
		$stmt->bindParam(':name', $name);
		$stmt->bindParam(':description', $description);
		$stmt->bindParam(':price', $price);
		$stmt->bindParam(':id', $id);
		
		// Execute the query
		if($stmt->execute()){
			echo "<div class='alert alert-success'>Record was updated.</div>";
		}else{
			echo "<div class='alert alert-danger'>Unable to update record. Please try again.</div>";
		}
		
	}
	
	// show errors
	catch(PDOException $exception){
		die('ERROR: ' . $exception->getMessage());
	}
}
?>

8.5 Output

To update a database record, run index.php file and click any "Edit" button. Or go to this URL http://localhost/php-beginner-crud-level-1/update.php?id=9 to see the result like the images below.

Update record form.

Submitted form.

Changes in the database.

9.0 Delete record in PHP

9.1 Tell the user if record was deleted

This will tell the user if there is a deleted record after clicking the delete button and "ok" in the pop up.

Open index.php file. Replace // delete message prompt will be here comment with the following code.

$action = isset($_GET['action']) ? $_GET['action'] : "";

// if it was redirected from delete.php
if($action=='deleted'){
	echo "<div class='alert alert-success'>Record was deleted.</div>";
}

9.2 JavaScript to confirm record deletion

The user clicks on the "Delete" button in index.php. Next, he will verify the deletion by clicking "OK" on the pop up.

That user activity will execute the following JavaScript code.

Open index.php file. Replace <!-- confirm delete record will be here --> comment with the following code.

<script type='text/javascript'>
// confirm record deletion
function delete_user( id ){
	
	var answer = confirm('Are you sure?');
	if (answer){
		// if user clicked ok, 
		// pass the id to delete.php and execute the delete query
		window.location = 'delete.php?id=' + id;
	} 
}
</script>

9.3 Delete record from the database

The code below will delete a record from the database using the given ID parameter.

This answers the question: how to delete a record with PDO? Create new delete.php file, place the following code and save it.

<?php
// include database connection
include 'config/database.php';

try {
	
	// get record ID
	// isset() is a PHP function used to verify if a value is there or not
	$id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');

	// delete query
	$query = "DELETE FROM products WHERE id = ?";
	$stmt = $con->prepare($query);
	$stmt->bindParam(1, $id);
	
	if($stmt->execute()){
		// redirect to read records page and 
		// tell the user record was deleted
		header('Location: index.php?action=deleted');
	}else{
		die('Unable to delete record.');
	}
}

// show error
catch(PDOException $exception){
	die('ERROR: ' . $exception->getMessage());
}
?>

9.4 Output

Once user clicks any "Delete" button, it will show a confirmation pop up.

If user clicks the "OK" button, record will be deleted from the database. It will tell the user via message prompt that the record was deleted.

Record is gone in the database as well.

10.0 Pagination in PHP

Please note that this is a bonus section and is not included in the LEVEL 1 source code download. We will have to add or remove some codes we've done above so that pagination will work.

10.1 Set pagination variables

Place the following code below include 'config/database.php'; line of index.php file.

// PAGINATION VARIABLES
// page is the current page, if there's nothing set, default is page 1
$page = isset($_GET['page']) ? $_GET['page'] : 1;

// set records or rows of data per page
$records_per_page = 5;

// calculate for the query LIMIT clause
$from_record_num = ($records_per_page * $page) - $records_per_page;

10.2 Add LIMIT clause in SELECT query

This will enable paginated requests to database. Still on index.php file, change the following code from:

$query = "SELECT id, name, description, price FROM products ORDER BY id DESC";
$stmt = $con->prepare($query);
$stmt->execute();

to:

// select data for current page
$query = "SELECT id, name, description, price FROM products ORDER BY id DESC
	LIMIT :from_record_num, :records_per_page";

$stmt = $con->prepare($query);
$stmt->bindParam(":from_record_num", $from_record_num, PDO::PARAM_INT);
$stmt->bindParam(":records_per_page", $records_per_page, PDO::PARAM_INT);
$stmt->execute();

10.3 Count total number of records

Counting the total number of records will help calculate the correct pagination numbers. Below the closing 'table' tag in index.php file, add the following code.

// PAGINATION
// count total number of rows
$query = "SELECT COUNT(*) as total_rows FROM products";
$stmt = $con->prepare($query);

// execute query
$stmt->execute();

// get total rows
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$total_rows = $row['total_rows'];

10.4 Include paging file

Add the following code after the previous section's code.

// paginate records
$page_url="index.php?";
include_once "paging.php";

Why a $page_url variable is needed? Because we made paging.php re-usable. You can use it for other objects you want to paginate.

For example you're trying to paginate your read_categories.php, you do $page_url="read_categories.php?";

You will have to follow the code pattern of section 10.1 to 10.3 when you use paging.php file.

10.5 Create paging.php

Create new paging.php file. Place the following code and save it.

<?php
echo "<ul class='pagination pull-left margin-zero mt0'>";

// first page button will be here

// clickable page numbers will be here

// last page button will be here

echo "</ul>";
?>

10.6 Add first page button

Replace // first page button will be here comment of the previous section with the following code.

// first page button
if($page>1){

	$prev_page = $page - 1;
	echo "<li>";
		echo "<a href='{$page_url}page={$prev_page}'>";
			echo "<span style='margin:0 .5em;'>&laquo;</span>";
		echo "</a>";
	echo "</li>";
}

10.7 Add clickable page numbers

Open paging.php file. Replace // clickable page numbers will be here comment with the following code.

// clickable page numbers

// find out total pages
$total_pages = ceil($total_rows / $records_per_page);

// range of num links to show
$range = 1;

// display links to 'range of pages' around 'current page'
$initial_num = $page - $range;
$condition_limit_num = ($page + $range)  + 1;

for ($x=$initial_num; $x<$condition_limit_num; $x++) {

	// be sure '$x is greater than 0' AND 'less than or equal to the $total_pages'
	if (($x > 0) && ($x <= $total_pages)) {

		// current page
		if ($x == $page) {
			echo "<li class='active'>";
				echo "<a href='javascript::void();'>{$x}</a>";
			echo "</li>";
		}

		// not current page
		else {
			echo "<li>";
				echo " <a href='{$page_url}page={$x}'>{$x}</a> ";
			echo "</li>";
		}
	}
}

10.8 Add last page button

Open paging.php file. Replace // last page button will be here comment with the following code.

// last page button
if($page<$total_pages){
	$next_page = $page + 1;

	echo "<li>";
		echo "<a href='{$page_url}page={$next_page}'>";
			echo "<span style='margin:0 .5em;'>&raquo;</span>";
		echo "</a>";
	echo "</li>";
}

10.9 Output

Run index.php file on the browser http://localhost/php-beginner-crud-level-1/index.php. You should see the pagination buttons like the images below.

Read records page 1.

Read records page 2.

11.0 File upload in PHP

Now we are going to add a "file upload" feature when creating a record.

11.1 Add HTML "file" field

Open create.php file and scroll down to the form. Find the opening "form" tag and enable the file upload by changing it to:

<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post" enctype="multipart/form-data">

Find the closing "tr" tag of the "price" field. Once found, add the following code after it.

<tr>
	<td>Photo</td>
	<td><input type="file" name="image" /></td>
</tr>

11.2 Add "image" field

Still in create.php file. Scroll up and change the "insert" SQL query. It should look like the following code. The new "image" field will store the file name of the submitted file.

// insert query
$query = "INSERT INTO products
			SET name=:name, description=:description,
				price=:price, image=:image, created=:created";

// prepare query for execution
$stmt = $con->prepare($query);

$name=htmlspecialchars(strip_tags($_POST['name']));
$description=htmlspecialchars(strip_tags($_POST['description']));
$price=htmlspecialchars(strip_tags($_POST['price']));

// new 'image' field
$image=!empty($_FILES["image"]["name"])
		? sha1_file($_FILES['image']['tmp_name']) . "-" . basename($_FILES["image"]["name"])
		: "";
$image=htmlspecialchars(strip_tags($image));

// bind the parameters
$stmt->bindParam(':name', $name);
$stmt->bindParam(':description', $description);
$stmt->bindParam(':price', $price);
$stmt->bindParam(':image', $image);

// specify when this record was inserted to the database
$created=date('Y-m-d H:i:s');
$stmt->bindParam(':created', $created);

Using PhpMyAdmin, add an "image" field in the products table as well.

11.3 Set variables for file upload

We will start the code for the "file upload" feature. Find the following line in create.php file.

echo "<div class='alert alert-success'>Record was saved.</div>";

Under the code above, we will add the following code. The "if($image){" code will verify if there's an uploaded image. If there is, inside the "if" statement, we will set the initial variables needed for the file upload.

// now, if image is not empty, try to upload the image
if($image){

	// sha1_file() function is used to make a unique file name
	$target_directory = "uploads/";
	$target_file = $target_directory . $image;
	$file_type = pathinfo($target_file, PATHINFO_EXTENSION);

	// error message is empty
	$file_upload_error_messages="";

}

11.4 Make sure submitted file is a real image

Now we will start validating the submitted file. The code below will identify if the submitted file is a real or fake image.

Place the following code under $file_upload_error_messages=""; of the previous section.

// make sure that file is a real image
$check = getimagesize($_FILES["image"]["tmp_name"]);
if($check!==false){
	// submitted file is an image
}else{
	$file_upload_error_messages.="<div>Submitted file is not an image.</div>";
}

11.5 Make sure certain file types are allowed

The following code will limit the allowed file types. Place it under the code of the previous section.

// make sure certain file types are allowed
$allowed_file_types=array("jpg", "jpeg", "png", "gif");
if(!in_array($file_type, $allowed_file_types)){
	$file_upload_error_messages.="<div>Only JPG, JPEG, PNG, GIF files are allowed.</div>";
}

11.6 Make sure file does not exist

There's a very small chance that the submitted file name will be the same with the one that exists in the server. This is because of the sha1_file() method we used on section 10.2 above.

But just in case there's a file with the same name, tell the user. Place the following code after the previous section's code.

// make sure file does not exist
if(file_exists($target_file)){
	$file_upload_error_messages.="<div>Image already exists. Try to change file name.</div>";
}

11.7 Make sure submitted file is not too large

Uploading a very large photo is not recommended in this case. So we will set the file size limit to less than 1 MB. Place the following code after the code of the previous section.

// make sure submitted file is not too large, can't be larger than 1 MB
if($_FILES['image']['size'] > (1024000)){
	$file_upload_error_messages.="<div>Image must be less than 1 MB in size.</div>";
}

11.8 Make sure the 'uploads' folder exists

The "uploads" folder is where we will put the submitted file. Make sure it exists by using the following code. Place it under the code of the previous section.

// make sure the 'uploads' folder exists
// if not, create it
if(!is_dir($target_directory)){
	mkdir($target_directory, 0777, true);
}

11.9 Try to upload the file

The "move_uploaded_file" built in PHP function will place the uploaded file on the server directory. Place the following code under the previous section's code.

// if $file_upload_error_messages is still empty
if(empty($file_upload_error_messages)){
	// it means there are no errors, so try to upload the file
	if(move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)){
		// it means photo was uploaded
	}else{
		echo "<div class='alert alert-danger'>";
			echo "<div>Unable to upload photo.</div>";
			echo "<div>Update the record to upload photo.</div>";
		echo "</div>";
	}
}

// if $file_upload_error_messages is NOT empty
else{
	// it means there are some errors, so show them to user
	echo "<div class='alert alert-danger'>";
		echo "<div>{$file_upload_error_messages}</div>";
		echo "<div>Update the record to upload photo.</div>";
	echo "</div>";
}

11.10 Output

Form to create product with file upload field.

When form was submitted.

The "uploads" folder were created, with the uploaded file inside.

File name was saved in the database.

12.0 Show uploaded image in PHP

12.1 Add image field in query

Open read_one.php file and apply the following changes to the code.

Add 'image' field to the $query variable. It should look like the following.

$query = "SELECT id, name, description, price, image FROM products WHERE id = ? LIMIT 0,1";

Add '$image' variable after the '$price' variable.

$image = htmlspecialchars($row['image'], ENT_QUOTES);

12.2 Add HTML image tag

Find the closing 'tr' tag of the 'Price' field in the HTML table and put the following code after it. It will show the uploaded image or 'No image found.' if no image was uploaded.

<tr>
	<td>Image</td>
	<td>
	<?php echo $image ? "<img src='uploads/{$image}' style='width:300px;' />" : "No image found.";  ?>
	</td>
</tr>

12.3 Output

Click the "Read One" button of the record we created with a file upload. You should see something like the images below.

Record with an image.

Record without image.

13.0 How To Run The Source Code?

We highly recommend for you to follow and study our well-detailed, step-by-step tutorial above first. Nothing beats experience when it comes to learning.

But we believe you will learn faster if you’ll see the final source code as well. We consider it as your additional guide.

Imagine the value or skill upgrade it can bring you. The additional income you can get from your work, projects or business. The precious time you save. Isn’t that what you want?

By now, you need to download our source codes. To do it, use any download buttons in the next few sections below.

Once you downloaded the source codes, here’s how you can run it.

  1. Extract the files to your server directory.
  2. Create your database using PhpMyAdmin, database name is "php_beginner_crud_3" - if you downloaded our LEVEL 3 source code.
  3. Import the SQL file called "php_beginner_crud_3.sql" located in the "dev" folder.
  4. You run index.php on the browser.

14.0 Download LEVEL 1 Source Code

FEATURES LEVEL 1
PDO extension used YES
Create product YES
Read product YES
Update product YES
Delete product YES
Price display with dollar sign YES
SQL file in "dev" folder YES
Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

15.0 Download LEVEL 2 Source Code

FEATURES LEVEL 2
All features of LEVEL 1 above YES
HTML5 (font-end) validation for create product YES
HTML5 (font-end) validation for update product YES
Category selection for create and update product. YES
Bootstrap UI YES
Buttons with Glyphicons YES
Pagination YES
Search products by name or description YES
HTML5 (font-end) validation for search product YES
Pagination in search YES
Allow user to input page number (read and search list) YES
Export / download records to CSV YES
Price display with dollar sign, comma and decimal point YES
Multiple delete YES
Create & update record with file upload YES
Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

16.0 Download LEVEL 3 Source Code

FEATURES LEVEL 3
All features of LEVEL 1 and 2 above YES
Bootstrap navigation bar YES
Select category in navigation YES
Higlight category in navigation YES
Create category YES
Read category YES
Update category YES
Delete category YES
View products by category YES
Pagination for category YES
Search category YES
Pagination for category search YES
Server side validation for create product & category YES
Server side validation for update product & category YES
Sorting by fields YES
Pagination for sorting by fields YES
jQuery UI enabled YES
Search product by date range - record date created YES
Pagination for earch product by date range YES
jQuery UI calendar for picking date YES
Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

17.0 Download ALL LEVELS

This means you will download the LEVEL 1, 2 and 3 source codes in separate packages. Select "ALL LEVELS Source Code" below and then you click the "Download Now" button.

Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

Do you need more reasons to download it?

MORE REASONS TO DOWNLOAD THE CODE ALL
Use new skills for your multiple projects YES
Save huge amount of time learning Bootstrap and PHP YES
Code examples are direct to the point YES
Well explained and commented source code YES
Fast and friendly email support YES
Free source code updates YES

If you have any more questions, please feel free to contact me now. You can do it by sending a message on our official Facebook page, or via my email mike@codeofaninja.com

Thanks for supporting our website and projects here at codeofaninja.com!

18.0 Online Resources

19.0 What's Next?

After learning from this PHP CRUD tutorial, we can go one step higher. We can do this by learning object-oriented programming (OOP) in PHP.

Object-oriented programming (OOP) is a programming language model organized around objects rather than "actions" and data rather than logic. This is very exciting.

To learn more, we created the next tutorial just for you! Let's go and learn:
PHP, MySQL and OOP CRUD Tutorial - Step by Step Guide!

20.0 Related Tutorials

21.0 Notes

#1 Found An Issue?

If you found a problem with this code, we can solve it faster via Email or FB message, please send me a message via email mike@codeofaninja.com, or via our official Facebook page!

Please be more detailed about your issue. Best if you can provide an error message and your test or page URL. Thanks!

Please feel free to comment if you have any questions, suggestions, found something wrong or want to contribute to this code.

#2 Become a true Ninja!

We constantly add new tutorials and improve our existing tutorials and source codes. Be one of the first to know an update by subscribing to our FREE newsletter. Get a FREE EBOOK as well. CLICK HERE TO SUBSCRIBE FOR FREE!

#3 Thank You!

Please share this post if you think this is a useful PHP CRUD Tutorial. We hope you mastered how to create, read, update and delete database records and more. Thanks for learning here in codeofaninja.com!

Home PHP

How To Customize reCAPTCHA

Have you ever received unsolicited (Spam) messages, comments or notifications in your email, facebook account, or to other services you are using online? Probably yes. I think almost all people using the internet experienced it already. There are trillions of spam messages sent every year.

One effective way to prevent those spam messages to your form is using a “Completely Automated Public Turing test to tell Computers and Humans Apart” or CAPTCHA in short. Google, Facebook, Yahoo, and other big internet companies uses this method. So today we are going to do a script that uses Google reCAPTCHA for our form. This tool by Google is widely used in the internet, maybe you’re familiar with the red box image below:

Home>PHP How To Customize reCAPTCHA

Customizing your Google Recaptcha

DOWNLOAD SOURCE CODE LIVE DEMO

Step 1: Download the recaptcha library here.

Step 2: We’re going the have the following code on our index.php file.

<html>
<head>
<title>https://www.codeofaninja.com/ - Customized reCAPTCHA For Your Form using PHP</title>
<style type='text/css'>    
/*
the customization of our recaptcha field
recaptcha_widget id is what we're customizing
*/

#recaptcha_widget{
    magin: 0;
}

#recaptcha_widget a{
    color: #000;
    text-decoration: none;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: bold;
    margin: 15px 0 0 0;
    padding: 2px 4px 2px 4px;
    background-color: #F5DEB3;
}

#recaptcha_widget a:hover{
    background-color: #DEB887;
}

.text{
    margin: 0 0 5px 0;
}

/*
just some message box style
when form is submitted
*/
#error-box{
    border: 4px solid #FF0000; 
    background-color: #FA8072;
    color: #fff;
    font-family: Arial, Helvetica, sans-serif;
    width: 430px;
    margin: 0 0 5px 0;
    padding: 4px;
}

#success-box{
    border: 4px solid #32CD32; 
    background-color: #00FF7F;
    color: #000;
    font-family: Arial, Helvetica, sans-serif;
    width: 430px;
    margin: 0 0 5px 0;
    padding: 4px;
}
</style>
</head>
<body>
<?php
//defining indexes
isset( $_REQUEST['action'] ) ? $action = $_REQUEST['action'] : $action = '';
isset( $_REQUEST['email'] ) ? $email = $_REQUEST['email'] : $email = '';
isset( $_REQUEST['user_password'] ) ? $user_password = $_REQUEST['user_password'] : $user_password = '';
isset( $_REQUEST['recaptcha_challenge_field'] ) ? $recaptcha_challenge_field = $_REQUEST['recaptcha_challenge_field'] : $recaptcha_challenge_field='';
isset( $_REQUEST['recaptcha_response_field'] ) ? $recaptcha_response_field = $_REQUEST['recaptcha_response_field'] : $recaptcha_response_field='';

require 'recaptcha/recaptchalib.php'; 
/* ---------------------------recaptcha code----------------------- */
//use your own private key here
$privatekey = "6LdUOcYSAAAAAGT-EbCqOldQ54GJhqG3ZdMkwLBG";
$resp = recaptcha_check_answer ($privatekey,
                        $_SERVER["REMOTE_ADDR"],
                        $recaptcha_challenge_field,
                        $recaptcha_response_field);

if (!$resp->is_valid) {
    $recaptcha = 'wrong';
} else {
    $recaptcha = 'correct';
}
/* ---------------------------recaptcha code----------------------- */
    
//when the form is submitted
if( $action == "signup" ){

$error_msg = '';

//if( empty($email) || empty($user_password)){
if( $email == '' || $user_password == ''){
    $error_msg .= "<div>-{$email}{$user_password}Field cannot be empty.</div>";
}

if( $recaptcha == 'wrong' ){
    $error_msg .= "<div>-You should enter characters that match the word verification.</div>";
}

if( $error_msg != '' ){
    echo "<div id='error-box'>";
        echo $error_msg;
    echo "</div>";
}else{
    echo "<div id='success-box'>";
        echo "Form successfully submitted.";
    echo "</div>";
}

}

?>

<!-- 
-this script is needed since we
are customizing recaptcha 
-it comes first before the form tag - always
-->
<script type="text/javascript">
var RecaptchaOptions = {
    theme : 'custom',
    custom_theme_widget: 'recaptcha_widget'
};
</script>

<!-- form tag comes first before table tag - always. -->
<form action='#' method='post' class='form'>
<table>
    <tr>
        <td align='right'>Email:</td>    
        <td><input type='text' name='email' /></td>
    </tr>
    <tr>
        <td align='right'>Password:</td>
        <td><input type='text' name='user_password' /></td>
    </tr>
    <tr>
        <td valign='top'>Word Verification.: </td>
        <td>
        
<div style='margin: 0px auto; text-align: center; width: 360px;'>
    

        <div class="field-space" style='text-align: left;'>
        
<!-- the id recaptcha_widget is what we're customizing -->
<div id="recaptcha_widget" style="display:none">

    <div id="recaptcha_image"></div>
    <div class="recaptcha_only_if_incorrect_sol" style="color:red">Incorrect, please try again</div>

    <div class="recaptcha_only_if_image" style='margin-bottom: 10px;'>Enter the words above : </div>
    <span class="recaptcha_only_if_audio">Enter the numbers you hear:</span>

    <div><input type="text" id="recaptcha_response_field" name="recaptcha_response_field" size='30' class='text' /></div>
    
    <span><a href="javascript:Recaptcha.reload()">Get Another Challenge</a>  </span> 
    <span class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type('audio')">Try Audio</a>  </span>
    <span class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type('image')">Try Image</a>  </span>

    <span><a href="javascript:Recaptcha.showhelp()">Help</a></span>

</div>

<!-- user your own public key after "k="-->

<script type="text/javascript" src="http://www.google.com/recaptcha/api/challenge?k=6LdUOcYSAAAAALa38Uxegl8owzKXGomiSkV498n_"></script>
<noscript>
    <iframe src="http://www.google.com/recaptcha/api/noscript?k=6LdUOcYSAAAAALa38Uxegl8owzKXGomiSkV498n_" height="300" width="500" frameborder="0"></iframe>
    <br>
    <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
    <input type="hidden" name="recaptcha_response_field" value="manual_challenge">
</noscript>

        </td>
    </tr>
    <tr>
        <td></td>
        <td>
            
        <!-- our hidden field and submit button here -->
        <div class="submit" style='float: left;'>
                <input type='hidden' name='action' value='signup' />
                <input type='submit' value='Sign Up!' />
        </div>
        
        </td>
    </tr>
</table>
</form>

</body>
</html>

That’s it! :)