Xataface 0.7.4 includes built-in support for user registration. This document explains how to activate it along with some usage examples.
If you are building an application that is meant for public use, you will likely need to provide some mechanism for users to sign up for an account on your application. Conceptually this is an easy matter. All you need to do is allow users to enter new records in your users table. Using Xataface, this is quite easy to do. Just give the 'new' permission to anonymous users. If we really sit down and think about this, however, we probably want something more for our registration. Some nice features of a registration system include:
- Checking for duplicate usernames
- Email verification
- auto login after registration
- A forgot password function.
Xataface 0.7.4 provides the first 3 features listed above and future versions will likely add the 4th feature.
Prerequisites
In order to enable registration, you must have authentication turned on. For more information about Xataface's authentication and permissions features, see http://framework.weblite.ca/documentation/tutorial/getting_started/permissions
Enabling Registration
Registration in Xataface applications is turned off by default. You can turn it on by adding allow_register=1 to the [_auth] section of your conf.ini file as follows:
[_auth]
users_table = users
username_column = username
password_column = "password"
allow_register=1
Now, when a user sees the login prompt, he will see a
Register link.
How it works
When the user clicks the Register link, they are taken to a registration page, which is essentially a new record form for the users table, as specified in the [_auth] section of the conf.ini file. It will look something like:
To see this form in action on a demo web auction application see
http://demo.weblite.ca/apps/webauction/index.php?-action=registerAfter the user fills in this form and clicks the Save button, an email will be sent to the email address he specified on the registration form with a link to activate the account. The email will look something like:
Thank you for registering for an account on Plant Sale Auction . In order to complete your registration,
please visit http://demo.weblite.ca/apps/webauction/index.php?-action=activate&code=4d52caea78dc8e964c50ed43a61fb22b .
If you have not registered for an account on this web site and believe that you have received
this email eroneously, please report this to Postmaster@weblite.ca .
-----------------------------------------------------------
This message was sent by Plant Sale Auction which is powered by a Xataface Application version 0.1 dev 3
a Xataface Application built using Xataface version 0.7.3 (http://framework.weblite.ca).
If the user clicks on the link in the email, he will see a message informing him that the registration succeeded and that he is now logged in.
Under the hood
If you set up registration on your own application and then look at your database, you'll notice that Xataface has created a new table, dataface__registrations. This table is automatically created to store the temporary registration information until an account is activated. When the user activates his account, the data in the dataface__registrations table will be copied to the user table.
How to turn off email verification
Email verification is a good feature for preventing spam and forcing users to use valid email addresses. If you still, however want to turn it off, you can do so by adding the following to your application's actions.ini file:
[register > register]
email_validation=0
What this does is extends the register action that is defined in Xataface's actions.ini file and overrides the email_validation property to be 0 (instead of 1 which is the default).
Once email validation is disabled, users will be automatically registered and logged in as soon as they complete the registration form. If you do this, it is a good idea give the new user accounts only minimal permissions. Read further in this document to find out how to do this.
Permissions Considerations
In order for registration to work properly, you must make it so that anonymous users (users who haven't logged in) have 'new' permissions on the users table. Some common permission settings for applications are:
- Anonymous users can create new user records, but not edit existing ones.
- Registered users can edit their own record, but nobody elses.
- Administrators can edit all user records.
- Registered users cannot modify their username or any field pertaining to his access level.
Here is a snippet from the Web Auction users table delegate class to show how the permissions are defined:
/**
* Permissions for records of the user table.
*/
function getPermissions(&$record){
if ( isAdmin() or ( $record and ($record->strval('username') == getUsername()))) {
$perms = Dataface_PermissionsTool::ALL();
} else {
$perms = Dataface_PermissionsTool::READ_ONLY();
}
$perms['new'] = 1; // Everyone gets the 'new' permission or registration won't work
return $perms;
}
/**
* Permissions for the username field.
*/
function username__permissions(&$record){
$perms = $this->role__permissions(&$record);
$perms['new'] = 1; // Everyone gets the 'new' permission
return $perms;
}
/**
* Permissions for the role field. The role field pertains to the user's
* access privileges so nobody should be able to change this except
* administrators.
*/
function role__permissions(&$record){
if ( isAdmin() ){
return Dataface_PermissionsTool::ALL();
} else {
return Dataface_PermissionsTool::READ_ONLY();
}
}
Please note that the isAdmin() and getUsername() functions were defined elsewhere and are convience functions wrapping calls to the Dataface_AuthenticationTool object.
Customizing the Registration Action
Using custom templates and delegate classes you can customize almost every aspect of the registration process. You can modify the field labels and descriptions using the fields.ini file for the users table. You can control which fields appear on the form using standard permissions in the delegate class. You can modify the registration templates to show extra information or a license agreement. Using the delegate class you can even provide a custom validation email message or add your own custom event handlers to be called before or after registration.
Customizing Templates
The registration action uses the Dataface_Registration.html template to display the registration page. To modify the registration page simply copy this template (located in the Dataface/templates directory) into your application's templates directory, and make modifications as you desire.
Adding content to the registration page
One way to add content to the registration page is to override the Dataface_Registration.html template as described above. However you may find it easier just to insert content into some of the predefined slots and blocks in the template using your delegate classes. For an introduction to blocks and slots see http://framework.weblite.ca/documentation/tutorial/customizing-the-dataface-look-and-feel/customizing.
Some of the slots and blocks that are included on the registration page are as follows:
- before_registration_form
- This block occurs immediately before the registration form. This may be an appropriate place to insert a license agreement or a blurb about the registration process. e.g. If you implement a method named block__before_registration_form() in your delegate class whatever you print in this method will be displayed immediately preceeding the registration form.
Example
class conf_ApplicationDelegate {
...
function block__before_registration_form(){
echo '<h2>My Xataface Application Registration Form</h2>';
echo '<div>Please fill in the registration for below in order to join my site.
By completing this form, you agree to all of the terms and conditions.</div>';
return true;
}
...
}
- registration_form
- If you implement this slot, it will override the registration form itself. I.e whatever you place in this slot will replace the registration form. e.g. implement the block__registration_form() method in your delegate class.
Example
class conf_ApplicationDelegate {
...
// This will replace the registration form so that user's can no longer register
function block__registration_form(){
echo '<div>I am replacing the registration form with my own form.
If you want to sign up for this site, just send me an email, and I'll give
you an account.</div>';
return true;
}
...
}
- after_registration_form
- Whatever you place in this block will be displayed immediately following the registration form. e.g. implement the block__after_registration_form() method in your delegate class.
Example
class conf_ApplicationDelegate {
...
function block__after_registration_form(){
echo '<a href="terms.php">Click here to read the terms and conditions</a>';
return true;
}
...
}
Sending a custom email validation message
Xataface allows you to override all aspects of the email validation process using delegate classes. You can implement the following methods to alter the email behavior:
- sendRegistrationActivationEmail
- Sends the activation email. This overrides Xataface so that you can control how the email is sent. This can be useful if you want to use an alternative mail server.
Signature | function sendRegistrationActivationEmail( Dataface_Record &$record, string $activation_url ) returns mixed
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
$activation_url
|
The URL that the user has to visit in order to activate his account.
|
returns
|
True if the email is sent successfully. A PEAR_Error object if it fails.
|
Example
class conf_ApplicationDelegate {
...
function sendRegistrationActivationEmail( &$record, $activation_url ){
$res = mail(
$record->val('email'),
'Activation instructions',
'Please activate your account by visiting '.$activation_url,
'From: webmaster@example.com' . "\r\n" .
'Reply-To: webmaster@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion()
);
if ( !$res ){
return PEAR::raiseError("Failed to send email to ".$record->val('email'), DATAFACE_E_ERROR);
} else {
return true;
}
}
...
}
- getRegistrationActivationEmailInfo
- Returns an associative array containing information about the email including the subject, message body, headers, and parameters. This can be useful if you want to override the default activation email subject or body with your own message.
Signature | function getRegistrationActivationEmailInfo( Dataface_Record &$record, string $activation_url ) returns array
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
$activation_url
|
The URL that the user has to visit in order to activate his account.
|
returns
|
An associative array containing the aspects of the validation email that you want to override.
The array can contain the following keys:
- subject - The subject of the email
- message - The message body of the email
- headers - The email headers (e.g. Reply-to, From, etc..)
- parameters - Optional email parameters.
These parameters are designed to be able to be passed directly to the PHP mail function (http://php.net/manual/en/function.mail.php)
|
Example
class conf_ApplicationDelegate {
...
function getRegistrationActivationEmailInfo( &$record, $activation_url ){
return array(
'subject' => 'Activation instructions',
'message' => 'Please activate your account by visiting '.$activation_url,
'headers' => 'From: webmaster@example.com' . "\r\n" .
'Reply-To: webmaster@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion(),
'parameters' => '-fwebmaster@example.com'
);
}
...
}
- getRegistrationActivationEmailSubject
- Returns a subject for the activation email. Use this method if you just want to override the subject of the activation email, and nothing else. If you use this in conjunction with the getRegistrationActivationEmailInfo method, then this will take precedent with respect to the subject.
Signature | function getRegistrationActivationEmailSubject( Dataface_Record &$record, string $activation_url ) returns string
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
$activation_url
|
The URL that the user has to visit in order to activate his account.
|
returns
|
A string containing the subject to be used in the activation email.
|
Example
class conf_ApplicationDelegate {
...
function getRegistrationActivationEmailSubject( &$record, $activation_url ){
return 'Activation instructions';
}
...
}
- getRegistrationActivationEmailMessage
- Returns a message body for the activation email. Use this method if you just want to override the message body of the activation email and nothing else. If you use this in conjunction with the getRegistrationActivationEmailInfo method, then this will take precedent with respect to the message body.
Signature | function getRegistrationActivationEmailMessage( Dataface_Record &$record, string $activation_url ) returns string
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
$activation_url
|
The URL that the user has to visit in order to activate his account.
|
returns
|
A string containing the message body to be used in the activation email.
|
Example
class conf_ApplicationDelegate {
...
function getRegistrationActivationEmailMessage( &$record, $activation_url ){
return 'Please activate your account by visiting '.$activation_url
}
...
}
- getRegistrationActivationEmailHeaders
- Returns headers to be used in the activation email. Use this method if you just want to override the headers for the activation email and nothing else. If you use this in conjunction with the getRegistrationActivationEmailInfo method, then this will take precedent with respect to the headers.
Signature | function getRegistrationActivationEmailHeaders( Dataface_Record &$record, string $activation_url ) returns string
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
$activation_url
|
The URL that the user has to visit in order to activate his account.
|
returns
|
A string containing the headers to be used in the activation email.
|
Example
class conf_ApplicationDelegate {
...
function getRegistrationActivationEmailHeaders( &$record, $activation_url ){
return 'From: webmaster@example.com' . "\r\n" .
'Reply-To: webmaster@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
}
...
}
- getRegistrationActivationEmailParameters
- Returns the parameters to be used in the activation email. Use this method if you just want to override the parameters for the activation email and nothing else. If you use this in conjunction with the getRegistrationActivationEmailInfo method, then this will take precedent with respect to the parameters.
Signature | function getRegistrationActivationEmailParameters( Dataface_Record &$record, string $activation_url ) returns string
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
$activation_url
|
The URL that the user has to visit in order to activate his account.
|
returns
|
A string containing the parameters (for the 4th parameter of the PHP mail function) to be used in the activation email.
|
Example
class conf_ApplicationDelegate {
...
function getRegistrationActivationEmailParameters( &$record, $activation_url ){
return '-fwebmaster@example.com';
}
...
}
-
Custom Validation
Xataface runs the registration form through the standard validation checks, including:
- Checks to make sure that the username is not already in use.
- Checks that a password has been supplied
- Checks that the email address is valid.
If you want to run additional checks on the registration data, you can implement your own validation method in the application delegate class as follows:
class conf_ApplicationDelegate {
...
function validateRegistrationForm($values){
// make sure the username is longer than 10 characters
if ( strlen($values['username']) < 10 )
return PEAR::raiseError("The username has to be at least 10 characters",
DATAFACE_E_ERROR
);
else return true;
}
...
}
In the above example we check to make sure that the supplied username is at least 10 characters in length. If not, we return an error which will be displayed on the registration form for the user to make corrections.
Note that the $values parameter is an associative array of the values that the user has submitted to the registration form. This is usually just the resulting $_POST array from submitting the form.
-
Events & Triggers
If you want to be able to perform some tasks before or after user registration (e.g. send the site administrator an email to inform him of the registration), you can implement one of the triggers available in the register action:
- beforeRegister
- This trigger is called before the registration form is processed. Please do not use this method for performing form validation. Use the validateRegistrationForm() method for validation. This method is useful if you want to perform some task before the registration is processed.
Signature | function beforeRegister( Dataface_Record &$record ) returns mixed
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
returns
|
PEAR_Error object if there is a problem that should cause the registration to fail.
|
Example
Here is a beforeRegister trigger that saves the IP address of the registrant in a log file.
class conf_ApplicationDelegate {
...
function beforeRegister( &$record ){
$fh = fopen('log.txt','a');
$res = fwrite($fh, $record->val('username').
' trying to register at '.date('Y-m-d H:i:s').
' from IP address '.$_SERVER['REMOTE_ADDR']."\n");
}
...
}
- afterRegister
- This trigger is called after the registration is processed. This may be an appropriate place to send the administrator an email to inform him of the registration.
Signature | function afterRegister( Dataface_Record &$record ) returns mixed
|
Parameters |
|
&$record
|
A Dataface_Record object
encapsulating the user record that has been created by the registration
form. You can use this record to extract information about the
registrant including his name and email address.
|
returns
|
A PEAR_Error if there was a problem.
|
Example
class conf_ApplicationDelegate {
...
function afterRegister( &$record ){
mail('admin@example.com',
'New registration',
'The user '.$record->val('username').' has registered for an account.'
);
}
...
}