PHP Tutorial: A n00b’s Guide To Making A Signup Form with PHP and WordPress

Ray Wenderlich
I made a beta signup form and all I got was this Muppet!

I made a beta signup form and all I got was this Muppet!

I hosted a beta test for my latest app, Battle Map for iPad, and recently wrote an article with knowledge I learned along the way.

But there’s one thing I didn’t cover in that article – how to implement the actual beta signup form!

If you are a web developer, this should be a trivial matter for you, but if you’re new to web development as I am there’s a bit of a learning curve in this.

So in this post, I will cover how I implemented the beta signup form for my latest app. You may find this PHP tutorial useful if you need to create a similar beta signup form, or if you’re interested in learning about writing WordPress plugins or PHP in general.

Caveat: This guide is good if you want to learn how to make a signup form yourself or have your own database on your web site, but if you don’t care about all that and want to just get something working ASAP, Jindrich from the comments section recommends using Google Docs forms, which looks like a quick & easy way to go!

This PHP tutorial assumes some basic familiarity with PHP and SQL. If you are not familiar with PHP, this tutorial from php.net is a good start, and if you’re not familiar with SQL, check out this MySQL tutorial.

Which Technology To Use?

There are tons of possible ways to implement the back end for beta signup form. The first question is one of language – maybe Ruby, Java, Python, C#, or PHP?

In my case, I chose PHP mainly because that’s what I’m learning at the moment and already had set up on my web server. There are a ton of frameworks on top of PHP that probably would have been useful for this, such as CodeIgniter or CakePHP, but I opted to go with straight PHP to learn the basics first.

Since my site uses the WordPress software which allows you to create plugins, I also decided to make the beta signup form a WordPress plugin, again mainly as a learning experience. I didn’t go all the way with a configuration menu and everything, but I learned some basics about WordPress plugin development along the way.

Also, there very well may be some kind of existing plugin for beta signup forms. I wouldn’t be surprised as there’s a plugin for almost everything else under the sun. But I still wanted to make it myself as a learning exercise and for ultimate control! :]

Ok so a PHP backend implemented as a WordPress plugin – check! Let’s get started!

WordPress and Shortcodes

Ok as we all know, the best way to get started with something unfamiliar is by just getting the damn thing to print “Hello, World!” So let’s start with that.

But before we get started, a bit of background on a feature of WordPress called “shortcodes”. If you’ve used WordPress much, you’ve probably downloaded some plugins that require you to insert a special code in your page where you want something to show up.

For example, I use Yoast’s Enhanced WordPress contact form, so to use it my Contact page contains the code [wpcf] where I want the contact form to appear.

So for this Hello World plugin, let’s do the same thing. The goal is we put a code like [my-beta-signup] somewhere in a WordPress page, and it should print out “Hello, World!”

We can do this with the Shortcode API provided by Wordpres. All we have to do is write a function that returns the string “Hello, World!”, then register it with the following call:

add_shortcode('my-beta-signup', 'my-beta-signup-handler');

Except I wanted to make things a little more complicated and call a method in a class rather than a plain functoin. Luckily, PHP provides a built-in way to handle this!

Instead of using the string ‘my-beta-signup-handler’, we can provide an array with the first parameter being the object, and the second parameter being the name of the method to call on the object, like the following:

add_shortcode('my-beta-signup', array($myBetaSignup, 'showSignupForm'));

Ok, enough talk, let’s put this together!

Hello, WordPress Plugin!

Create a new directory called my-beta-signup in your WordPress plugins directory, and inside that new directory create a file named my-beta-signup.php. Add the following to the file:

<?php
/*
Plugin Name: My Beta Signup
Plugin URI: http://www.raywenderlich.com
Description: A plugin to allow signing up for beta testing my awesome app.
Version: 1.0
Author: Ray Wenderlich
Author URI: http://www.raywenderlich.com
License: MIT
*/
 
class MyBetaSignup {
 
	function showSignupForm($atts) {
		return "Hello, World!";
	}
 
}
 
$myBetaSignup = new MyBetaSignup();
 
add_shortcode('my-beta-signup', array($myBetaSignup, 'showSignupForm'));
 
?>

At the beginning, we have to include a standard plugin information header clause. The info in this section is used by WordPress so it can detect your plugin and show it up in your list of plugins, and is also useful if you ever plan on submittting your plugin to the WordPress Plugin Directory.

It’s all pretty simple stuff though – you can just replace the above with your own URL/name.

Next, we create a class that will contain the methods we’ll be implementing in the rest of this PHP tutorial called MyBetaSignup. For now it just has a single method called showSignupForm, that actually doesn’t show a form at all – it just returns Hello, World! It’s so hard to get help around here these days.

Finally, we create a instance of our class, and use the add_shortcode method to register the callback for our shortcode as we discussed above.

That’s it! Save the file, then go to the admin section of your blog and you should see the new plugin listed:

Beta Signup WordPress Plugin

Click activate and your shortcode is ready to use. You can then test it by creating a new test page in WordPress and adding your shortcode somewhere on the page:

Creating a WordPress Test Page

Then check out your new page, and if all goes well you should see the Hello, World output!

Hello World WordPress Plugin

Creating the Beta Signup Database: Background

The next step is to create a table structure for our beta signup database. For the sake of this PHP tutorial, we’ll just record their name, email, and whether they’d like to be notified when the app launches. We’ll also add a few other columns to the table to make manual bookkeeping on the beta testers easier later.

Of course, we could just manually create our database using the mysql command line tool, but since we’re making this a WordPress plugin we may as well do things the WordPress standard way, which is to create the database tables upon initial plugin activation.

Again, WordPress makes doing this easy by providing a function we can call to register a callback for when the plugin gets activated. We can use it like the following:

register_activation_hook(__FILE__, array($battleMapBetaSignup, 'createDb'));

The first parameter is the path of the main plugin file. Well we only have one plugin file, so we just return __FILE__, which is the magic PHP constant for the pull path and filename of the current file.

One last piece of background we need to know before we get started. We all know that when you create database tables, it’s easy the first time: you just issue a CREATE TABLE statement.

But the tricky bit happens when you want to make changes to your database structure later. You can either drop the table and recreate it (hence losing any existing data inside), or make ALTER TABLE statements to modify your table and add the new rows, putting default values for any existing data.

Well, for WordPress plugins, in theory they can be upgraded by users at any time, so WordPress needed some kind of recommended solution for plugin developers for how to handle their table updates over time. They actually came up with a neat solution, by providing a function you can use named dbDelta.

dbDelta takes a CREATE TABLE statement, but rather than running the SQL statement directly, it takes a look at any existing table structure first. If there’s already a table there, it will alter the table automatically so it looks like the final desired structure, rather than dropping/recreating it. Cool eh?

So now that we have the background knowledge, let’s try it out!

Creating the Beta Signup Database: Implementation

Add the following code to the top of your MyBetaSignup class:

// Db version 
public $dbVersion = "1.0";
 
function createDb() {
 
	$installed_ver = get_option( "my_beta_version" );
 
	if ($installed_ver != $this->dbVersion ) {
 
		require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
 
		$tableName = $wpdb->prefix . "my_beta_user";
		$sql = "CREATE TABLE " . $tableName . " (
			id mediumint NOT NULL AUTO_INCREMENT PRIMARY KEY,
			name varchar(255) NOT NULL,
			email varchar(255) NOT NULL,
			notify tinyint(1) NOT NULL,
			selected mediumint NOT NULL DEFAULT 0,
			responded mediumint NOT NULL DEFAULT 0,
			udid varchar(255) NOT NULL DEFAULT \"\"
		);";						
	    dbDelta($sql);
 
	    add_option("my_beta_version", $this->dbVersion);
 
	}
 
}

At the beginning, we make a variable to keep track of the current version of the database. This isn’t strictly necessary because dbDelta will take care of the upgrades, but this is a good practice that will make some upgrades in the future easier because we know where we’re coming from.

So we only bother creating/updating the database tables if the current version doesn’t match the version for this plugin. We then include upgrade.php, which is required to use the dbDelta function.

We create our table name by prepending the database prefix the user set up to our desired table name.

Then, we construct the create table SQL for our table. Note we keep track of the user the info will input (name, email, whether to notify) as well as some space for bookkeeping information we can use ourselves (whether they are selected, whether they responded with feedback, and what their UDID is). And of course we add an id to the table as well!

Finally we call the dbDelta function to run the SQL, and record the current version of our database.

To call this, just add the following to the bottom of your file:

register_activation_hook(__FILE__, array($myBetaSignup, 'createDb'));

Ok, let’s try it out! Go back to your plugins list in WordPress and deactivate and reactivate the plugin. If all went well, you should have a new database table in your WordPress database! You can check it out by checking out your new database tables with the mysql command line tool or an alternate method:

My Beta User SQL structure

Creating the Signup Form

It’s about time to stop printing out Hello, World and start replacing it with an actual login form. To do this, replace your showSignupForm method with the following:

function showSignupForm($atts) {
 
	if ($this->checkInput()) {
 
		return "Coming soon!";		
 
	} else {
 
		$form = '
			<div class="my-form">
				<form action="'.get_permalink().'" method="post">
					<h3>Sign up for My Awesome Beta!</h3>
					<p>
						<label for="tester_name">Name:'.$this->required($this->testerNameError).'</label>
						<input type="text" name="tester_name" id="tester_name" size="30"'.$this->getValue($this->testerName).'/>
					</p>
					<p>
						<label for="tester_email">Email:'.$this->required($this->testerEmailError).'</label>
						<input type="tester_email" name="tester_email" id="tester_email" size="30"'.$this->getValue($this->testerEmail).'/>
					</p>
					<p>
						<input type="checkbox" name="notify" id="notify" value="True"/>
						<label for="notify">Notify me when My Awesome App launches!</label>
					</p>
					<p>
						'.$this->errorLabel().'
						<input type="hidden" name="my-form-data" value="process"/>
						<input type="hidden" name="notify" value="True"/>
						<input type="submit" id="submit" name="Submit" value="Submit"/>
					</p>						
				</form>
			</div>';
 
		return $form;
 
 
	}
 
}

Sorry for the HTML/PHP gobbledigook, I can see why PHP templating frameworks are so popular ;]

But anyway – we call a function here at the start to check if this is a form submission or not (we’ll write a placeholder for this in a minute). Then we just return the HTML to display for the form.

Most of this is pretty straightforward and just creating a form with HTML. You’ll notice that we have some placeholder code in there to add some extra HTML if the user doesn’t fill out a required field, populate a field with a previous value if there was an error signing up, and actually display the error if there was one at the bottom.

Next add the missing placeholder functions to your class:

function checkInput() {				
	// Bail right away if our hidden form value isn't there
	if (!(isset($_POST['my-form-data']))) { return false; }
 
	// Rest is coming soon!	
	return true;
}
 
function required($error) {
	if ($error) {
		return '<span class="required"> *</span>';
	}
}
 
function getValue($var) {
	if (empty($var)) {
		return ' value=""';
	} else {
		return ' value="'.esc_html($var).'"';
	}
}
 
function errorLabel() {
	if ($this->testerNameError || $this->testerEmailError || $this->rpgTypeError) {
		return '<span class="required">* = Required</span>';
	}
}

In the check input function, we just check if the hidden my-form-data field is contained in the POST data, and bail otherwise.

The others are just simple helper functions to print out errors and previous values if they exist.

So – save your plugin and reload the page, and if all works well you should have a beta signup form – that just doesn’t do anything yet!

Kermit Signs Up To My Beta

Checking User Input

The next step we need to do is check the user input. We need to make sure that the user actually filled in their username and email, and figure out whether they’ve checked the notify checkbox or not.

So replace the checkInput method with the following:

function checkInput() {
 
	// Bail right away if our hidden form value isn't there
	if (!(isset($_POST['my-form-data']))) { return false; }
 
	// Initialize errors
	$this->testerNameError = false;
	$this->testerEmailError = false;
 
	// Set variables from post
	$this->testerName = $_POST['tester_name'];
	$this->testerEmail = $_POST['tester_email'];
	$this->notify = $_POST['notify'];
 
	// Check tester name
	if (empty($this->testerName)) { $this->testerNameError = true; }
 
	// Check tester email		
	if (empty($this->testerEmail)) { $this->testerEmailError = true; }
 
	// Bail on errors
	if ($this->testerNameError || $this->testerEmailError) return false;		
 
	if (empty($this->notify)) {
		$this->notifyInt = false;
	} else {
		$this->notifyInt = true;
	}			
 
	return true;
}

Here we first read in what the user has set for tester_name, tester_email, and notify. If either tester_name or tester_email is empty, we set the appropriate error variable and bail. Remember from the earlier code that if these error variables are set, we’ll output some extra HTML that will warn the user that these fields are required.

Finally, HTML has this weird property where if a checkbox isn’t checked, it doesn’t send the post variable at all. So we account for that and set a variable to true or false to indicate whether it was checked or not here as well.

Refresh your web page again and try logging in, but this time leave your name and/or email blank. If all works well, it should present a warning to that effect:

Displaying Validation Error

Inserting the Beta Signup

Now for the moment we’ve been waiting for – actually inserting the user’s signup into our database!

But to do that we need to know is how to access the database. Well, in WordPress provides a global variable that is already set up to talk to the WordPress database called $wpdb. So we can just use that rather than having to connect manually.

And once we know that, the code is rather simple! Add this function to your MyBetaSignup class:

function insertUser() {
 
	global $wpdb;
 
	$wpdb->hide_errors();
 
	$tableName = $wpdb->prefix . "my_beta_user";
 
	return $wpdb->query($wpdb->prepare("
			INSERT INTO ".$tableName."
			(id, name, email, notify)
			VALUES ( 0, %s, %s, %d)",
			$this->testerName, $this->testerEmail, $this->notifyInt));
 
}

Here we create our table name, then prepare and execute our insert statement. Note that we use prepare to create our statement to make sure that the values from the user are escaped.

So just modify the showSignupForm to wrap this up:

function showSignupForm($atts) {
 
	if ($this->checkInput()) {
 
		$success = $this->insertUser();
 
		if ($success) {
			$form = '
				<div class="my-form">
					<h3>Successfully signed up!</h3>
					<p>You have successfully signed up for notification when My Awesome App launches.</p>
					<p>Thank you very much for your interest, and wishing you many exciting adventures ahead!</p>
				</div>';
			return $form;
		} else {
			$form = '
				<div class="my-form">
					<h3>Error signing up :[</h3>
					<p>It seems like there was a problem signing you up for the beta.  Please try again later or contact us to let us know about the problem.  Sorry for the inconvenience!</p>
				</div>';
			return $form;
		}		
 
	} else {
 
		// Rest of code...

And that’s it! Save your plugin, and try out your signup form, and you should be able to sign up successfully!

Successful Beta Signup

Where To Go From Here?

Here is a zip file with the plugin we developed in the above PHP tutorial.

For your beta, you may wish to add additional fields to your database or signup form – you can just extend the above to do so.

And for all of you web dev pros out there – let me know if I messed up with anything here, I’m pretty new to this! :]

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

User Comments

1 Comment

  • Hi,
    I know this subject is a bit old but found it very helpful. My question is if I wanted to take this a bit further and make this a sign-up form with a password what would I need to do. I do know that you would have to add the password box to the form and all that fun stuff but I am kind of a noob and want to ensure the passwords are encrypted properly.

    Thanks in advance!
    juanstg

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in September: iOS 8 App Extensions!

Sign Up - September

RWDevCon Conference?

We are considering having an official raywenderlich.com conference called RWDevCon in DC in early 2015.

The conference would be focused on high quality Swift/iOS 8 technical content, and connecting as a community.

Would this be something you'd be interested in?

    Loading ... Loading ...

Our Books

Our Team

Tutorial Team

  • Tammy Coron
  • Kirill Muzykov

... 49 total!

Update Team

Editorial Team

... 23 total!

Code Team

  • Orta Therox

... 3 total!

Translation Team

  • Heejun Han
  • Jesus Guerra
  • David Xie

... 33 total!

Subject Matter Experts

... 4 total!