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 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 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 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:
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:
Then check out your new page, and if all goes well you should see the Hello, World output!
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 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:
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!
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:
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!
Where To Go From Here?
Here is a zip file with the plugin we developed in the above 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! :]
Category: Web Development













Hi Ray, a great tut! I’m using WP for various project but always just code everything myself, though packing a couple of plugins to reuse might be a great idea! Thanks
Now – there’s 1 thing, where you have this code:
add_shortcode(‘my-beta-signup’, array($myBetaSignup, ‘showSignupForm’));
you say: “we can provide an array with the first parameter being the name of the object, and the second parameter being the name of the method to call on the object”
and judging from your code, I think the 1st param is the object itself, not its name :)
best, Marin
@Marin: Nice catch! I’ve updated the article with the fix.
Hi Ray. You crack me up! I was having a rough start this morning until I noticed a new RSS feed from you in my reader. “Potato Bugs!” haha This “teaser” was then followed by a great article!
Nice job. Of all my years programming you have made my transition to iOS development painless and with articles like this the concepts you present are very easy to follow. I wish to have known you when I started out learning COBOL!
Keep up the great work effort!!
Chris
@Chris: Ha ha I’m glad you liked the article (and Potato Bugs!) :] Thanks so much for the kind words, and nice to meet you!
Hi Ray,
First of all, great work !!. I have been looking all over the place for code using WordPress $wpdb class, to create and insert records from a form in my database table. Finally, found your code, which is exactly what I am looking for.
Ray, I put the code as you indicate in your tutorial, however, once I add the form part and go and try to see how is going inside my site I get the following error:
Fatal error: Call to undefined method MyBetaSignup::checkInput() in /home/relojbin/public_html/wp-content/plugins/my-beta-signup.php on line 45
The code, in my site looks like 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);
}
}
function showSignupForm($atts) {
if ($this->checkInput()) {
return “Coming soon!”;
} else {
$form = ‘
Sign up for My Awesome Beta!
Name:’.$this->required($this->testerNameError).’
getValue($this->testerName).’/>
Email:’.$this->required($this->testerEmailError).’
getValue($this->testerEmail).’/>
Notify me when My Awesome App launches!
‘.$this->errorLabel().’
‘;
return $form;
}
}
}
$myBetaSignup = new MyBetaSignup();
add_shortcode(‘my-beta-signup’, array($myBetaSignup, ‘showSignupForm’));
register_activation_hook(__FILE__, array($myBetaSignup, ‘createDb’));
?>
I would appreciate if you could look at it and see what could be causing this error.
Once again,
Thank you,
Ricardo Cerda de Groote
Hi Ray,
I was able to resolve the error. However, I get a different one now addressing the required() function as not defined.
Fatal error: Call to undefined method MyBetaSignup::required() in /home/relojbin/public_html/wp-content/plugins/my-beta-signup.php on line 74
for=”tester_name”>Name:’.$this->required($this->testerNameError).’
getValue($this->testerName).’/>
Email:’.$this->required($this->testerEmailError).’
getValue($this->testerEmail).’/>
Notify me when My Awesome App launches!
‘.$this->errorLabel().’
‘;
return $form;
Have no idea what could be causing that particular error.
I would appreciate your input.
Thank you,
Ricardo Cerda de Groote
Ray,
I resolved all the issues. They were all created by me, but like they say, live and learn.
Thank you so much and let’s keep in touch,
Ricardo
@Ricardo: Lol glad you got it all working, and that this came in handy. Yeah definitely, nice to meet you!
Hi again Ray,
Why do you use the line:
.
In other words, I am curious about the get_permalink as your form action. Usually, I associated form_action to either code to a CGI to have a mail sent or interact with the database. I think of get_permalink as getting a post and when you do not send the $id parameter, usually gets the last post in the loop.
Another thing, is how could I add in the form action, that apart from what is already doing, which is to update the database, it would also send me a mail that someone signed. Should I make an array, which indicates to udate and then to go to the CGI??.
Thank you kindly for your reply,
Ricardo
@Ricardo: Did you mean to reference a line of code, all I see is a period…?
But regarding your question on get_permalink, after reading the documentation (http://codex.wordpress.org/Function_Reference/get_permalink) my understanding is get_permalink does return the permalink for the current post if it is inside the WordPress Loop. Which in our case it is, because we are inserting the short tag inside a Page body, so we should be OK.
As for getting it to mail as well, you can just use PHP’s mail function for the actual sending of the email, and just put that code at the beginning of the showSignupForm function.