I recently worked on a free form application like this myself. It’s not intense but it’ll do the trick. If you want to take the code to make it more efficient and into a module that’s fine by me.
What I did was create 2 db tables that are identical, one user and the other validate. The only difference is validate has a session field. The relation between these two is a 1 to none setup. User doesn’t access validate, but validate will transfer data to user (once validated).
A user controller was made to handle all user actions, register and validate being among them. The register action is just a simple form setup, the typical instantiate the class, isset condition, false show form, true set attributes then before I validate I assign these three parameters, IP isn’t a big concern but time and the session are needed.
This is in the user/register action
$form->ip = $_SERVER['REMOTE_ADDR'];
$form->time = time();
$form->session = md5($form->time.rand(100000,999999));
Now all you do is append the session to a link like so:
$form->sessionLink = $this->createAbsoluteUrl('user/validate', array('code'=>$form->session));
Then validate and save - which saves to the validate table not the user table. Within the validate model, make an after save function that creates and sends your email. Now if you want to go a step further, you can insure that the email is sent by uploading the message, subject, email and header information to a table (called mail) in the event the mail function fails. Then elsewhere set a script to send all unsent emails.
The user gets their email with the absolute link in it that includes the session hashed via $_GET.
Then you just follow the link which takes you to the user/validate action and then you check if the session they clicked on and you retrieved with $_GET is located in the validate database. If it is, then transfer all values over to the user database and registration is complete - you can even send another email with an after save override for the user model which will contain the information details of their registration.
The way I implemented it I use the time field to compare if the user validated within a 7 day period or else the validation session is no longer valid meaning they have to re-register. This will be setup to prune with a script later.
Another small note, when you save to the validate table, don’t hash any passwords, that way when they confirm their registration, you can email the plaint text password (storing it in another class private variable before hashing it and saving to the user table).
$code = $_GET['code'];
$validate = new Validate;
// find hash
$validate = Validate::model()->find('session=?', array($code));
if($validate == NULL)
{
$validate->sessionValid = "Not Valid";
$this->render('validate',array('validate'=>$validate));
}
else
{
$user = new User;
// Define how long until the session expires
// 7 is the number of days.
$valid = 3600*24*7;
$time = time();
$timeElasped = $time - $valid;
if($validate->time < $timeElasped)
{
// Took to long to confirm registration
$validate->sessionValid = "Not Valid";
// Delete the record
$validate->delete();
}
else
{
// Session is valid, transfer data to user table
$validate->sessionValid = "Valid";
// Set all the column values
$user->username = $validate->username;
$user->password = $validate->password;
$user->email = $validate->email;
$user->ip = $_SERVER['REMOTE_ADDR'];
$user->time = time();
$user->question = $validate->question;
$user->answer = $validate->answer;
if($user->validate())
{
// Save to the user table
$user->save();
// Delete the record
$validate->delete();
}
It’s pretty basic but works like a charm. This isn’t all the code so if you’re having trouble give me a shout. But what I got is messy with so many if conditions (because of the desire to store the message if it’s not sent).
Now I’m going to explore Jonah’s skeleton application and see what I can add or change there .
Also as you can see the hash used for the session is nothing fancy and certainly different than what’s used throughout the site for other things like the password or cookies or w/e. Thus in the event some script kiddy tries to crack it, they crack a hash that’s useless to the site and has random information about time lol.