Building a user registration system – Part 1: The New User Form

Almost every website will have some form of public and restricted area. WordPress for instance, has the admin side where you can create posts, manage plugins, install themes etc. For this tutorial, we are going to create a similar mechanism. One that will restrict users from accessing sections of the site. We will create a system that will allow them to create their own account, reset their password and even update their profile.

Update 9/5/2016: Updated flaw in token creation and token checking for better security. Thanks to comment by Mohammad and his findings.

Update 7/20/2016: Added index.php file to the views directory. This is the view that is being used once a successful login is processed.

View in Github

user-reg

I’m going to assume that you are familiar with CodeIgniter, or other MVC frameworks. You don’t have to be an expert – just know enough that you will be able to follow along without me having to explain too much. We are also going to utilize Bootstrap – so our pages will look nice. Finally, the focus of this tutorial is learning how the process works. We’re not really here to look at design patterns, performance or database design.

So ready to get started? Roll up your sleeves and let’s start writing.

Get things setup

So obviously we’re going to need to store data – so we need a database. We will need a table that will house our users. Below is the SQL code to get you up and running. I’m calling the database “user-registration” – which is a stupid name actually. Name yours anything you want.

We’re going to use CodeIgniter 3.0.1. Go ahead and install in your server and open config > database.php and add your database credentials, host and database name. Let’s autoload the following items in config > autoload.php: libraries > ‘session’, helper > ‘url’, ‘form’, ‘security’. Let’s change the default controller in config > routes.php to ‘main’ instead of the default ‘welcome’.

In config > config.php add the two lines below. I’ll explain these later.

Create a new controller named Main.php and a model, name it User_model.php. In the next sections, we will tie these things together.

But first let’s look at the workflow of our system:

process-user-reg

So our first step is the registration form. Users fill out this form which will only consist of their name and email. This will write a record to our database – but the account will only be in “pending” status. This will also trigger an email containing a token (which expires in a day), when clicked – will allow the user to finish the registration process. This form will have a password and password confirmation. This will update the record – and make the account “active”.

We will automatically login the user, but now that they have an account – they can actually utilize the login and reset password form.

It also makes sense for us to build the pages in this exact order. So we got: 1) register 2) complete 3) login 4) forgot password.

The Registration

So the very first thing we need is the HTML that contains our form. Let’s create a new file called “register.php” and put it in our “views” folder. Add the code below:

Note that I’m not going to go through what goes in our header and footer template because it’s irrelevant to this tutorial. Just know that it’s basic HTML, along with a link to Bootstrap CSS. Our markup above is a mix of PHP and HTML. This is using CodeIgniter’s Form Class – which makes it real easy to do validation and data filter and sanitation.

So in our Main controller, let’s add a constructor and include the necessary components for our class. We’ll also set up our status and roles arrays inside this constructor:

So we’re loading our model “User_model” by default, the “form_validation” library and setting some HTML for our form errors. You’ll also notice the 2 properties (status and roles) – which grabs it from “$this->config”. Remember in our config file – we created 2 arrays? We’re simply outputting it here for easy access.

Now I know you’re saying this is better if these entries was in their own table in the database. Again, this is not a tutorial on database design. We’re simply doing it this way because it is not our focus. Let’s continue with our “register” method:

Alright, plenty of going on up there. So the validation rules are setup initially. Our form contains 3 fields: Last name, First name and email. They’re all required fields, plus the email address must be in valid format.

You will notice in the block where our form is validated, we’re checking “isDuplicate()” from our model: $this->user_model. This is so that we won’t have duplicate records of the same email. Remember, we are using their email address as their username. So if it’s a duplicate – we simply use CodeIgniter’s set_flashdata() and redirect them to the login page (which is not built yet).

If the email address is good, we continue by cleaning up the $_POST array. Notice that we have 2 methods right after the cleaning: insertUser() and insertToken(). So we write the record to our database, then we create a new token (let’s quickly run this SQL so we have this token table).

Another thing, you will also see that we’re using a local method called “base64url_encode()” – which is a way of outputting base64 code – that is in a web safe format. So in our controller, you can add these two methods in the bottom. Think of them as local “helper” methods.

I am not putting them in a the “helpers” for CI – because these methods are only to be used in controllers – since they are “URL” related. And as you can see, we only have one controller. But as your application grows, and you have many controllers, it’s best to move this into a real CI Helper.

Finally, we create our final URL, to our “complete” action and echo it out. In production, this will be done through an email, in HTML format.

Some Back-end Stuffs

Our model “User_model” is empty. Let’s go ahead and fill it up. We need 3 methods for our register to work remember? It’s 1) isDuplicate(), 2) insertUser() and insertToken(). First let’s create a constructor with our roles and status arrays:

Now let’s go ahead and create our 3 methods:

So judging from the method names – they’re pretty self explanatory correct? Also, if you’ve worked with CodeIgniter before, you’ll notice the syntax of interacting with the database. It used to be called “active record”, which is now the Query Builder class. Makes it real easy for non DBA’s like me to write queries.

The three methods all return either an array or a string on success, and “false” on failure. The return values are handled accordingly in our controller methods discussed previously. Pay token is simply a random number that we create and insert into the database. This token has an accompanying user id and a time stamp in the same row. This makes it possible for us to fetch the user, and find if it’s a valid request, in the appropriate time frame.

Let’s break it here for now. We have plenty more to come in the next part(s).

46 Comments

  1. Hi sir. This is the result when i run the system. pls help me sir. Thanks

    Severity: Warning

    Message: mysqli::real_connect(): (HY000/1044): Access denied for user ”@’localhost’ to database ‘user-registration’

    Filename: mysqli/mysqli_driver.php

    Line Number: 201

    Backtrace:

    File: C:\xampp\htdocs\User\application\controllers\Main.php
    Line: 12
    Function: model

    File: C:\xampp\htdocs\User\index.php
    Line: 315
    Function: require_once

    Reply
  2. This is in continuation with Andi’s question.
    It did work for me but it doesn’t go through when you input correct credentials. It produces a ‘Trying to get property of non-object’. Looking at it, the updateLoginTime method is the culprit so I changed this line:
    $this->updateLoginTime($userInfo->id);
    to:
    $this->updateLoginTime($userInfo[‘id’]);
    …and it worked!
    Thanks!

    Reply
  3. Hi Michael, great work!

    I would like some help as I’m getting an error on the confirm page of the registration process.

    This is from the CI logs:

    ERROR – 2017-04-22 21:07:41 –> Severity: Notice –> Undefined index: user_id C:\xampp\htdocs\application\models\User_model.php 85
    ERROR – 2017-04-22 21:07:41 –> Severity: Notice –> Undefined index: user_id C:\xampp\htdocs\application\models\User_model.php 90

    This is the updateUserInfo($post) function, where $this->db->where(‘id’, $post[‘user_id’]); is executed.

    I’ve been stuck on this for a whole day, any pointers?

    Thanks in advance

    Reply
  4. i found this error
    Error Number: 1048

    Column ‘role’ cannot be null

    INSERT INTO users (first_name, last_name, email, role, status) VALUES (‘test’, ‘test’, ‘test@gmail.com’, NULL, NULL)

    how do i fix?

    Reply
  5. I have another CI app that I would like to merge with this one in order to protect some sensitive data. The other app uses ajax with datatables to list db contents with members addresses, phone numbers, etc. How do you merge the classes from to separate applications into one?

    Reply
  6. nice, another one registration system which I am using and its pretty cool is ArtDesignUI – artdesign-ui.com/php/registration-system/info . Its easy to use and comes with 27 js plugins.

    Reply
  7. I am getting this error. Any ideas what it possibly be?

    Fatal error: Call to a member function isDuplicate() on null in C:\xampp\htdocs\artisan\application\controllers\Main.php on line 47

    Reply
  8. Hi Michael. Thanks for doing this; it’s extremely helpful! So I’m a CI newbie and just finished their tutorial. Now I’m onto yours and I generally get what’s going on. Silly question but which URL one would call to to test the code after part 1? I am doing this local (localhost) …

    Reply
  9. Hello sir, thank you for this article. It’s very helping me to learn ci. I’ve got error when i fill email/password form with random text then submit it.
    Severity: Notice
    Message: Trying to get property of non-object
    Filename: models/User_model.php
    Line Number: 121

    Backtrace:
    File: /public_html/jogjalife/application/models/User_model.php
    Line: 121
    Function: _error_handler

    File: /public_html/jogjalife/application/controllers/Main.php
    Line: 154
    Function: checkLogin

    Reply
    • If i comment this code (/application/models/User_model.php) class checkLogin, error warning is gone :
      //if(!$this->password->validate_password($post[‘password’], $userInfo->password)){
      // error_log(‘Unsuccessful login attempt(‘.$post[’email’].’)’);
      // return false;
      //}
      //$this->updateLoginTime($userInfo->id);

      Reply
      • It solved yesterday.
        “I change $userInfo = $query->row_array();” instead “$userInfo = $query->row();” and also “if(!$this->password->validate_password($post[‘password’], $userInfo[‘password’])){” instead “if(!$this->password->validate_password($post[‘password’], $userInfo->password)){”

        And it works.

  10. in this >> So in our Main controller, let’s add a constructor and include the necessary components for our class. We’ll also set up our status and roles arrays inside this constructor:

    where it placed the above code ? What’s in register.php file ?

    Reply
  11. Hello Michael
    i am beginner for CI, and i was follow you code for signup.
    all process done successfully but when i login or enter 2 step confirm password i am getting a error below:

    An Error Was Encountered
    Unable to load the requested file: index.php

    please help me
    thanks

    Reply
    • Create a new website. Download CodeIgniter. Once that’s running, follow the steps above. If you want, you can also download the files from Github – simply add them to the right directories in CI.

      Reply
  12. Thank You so much for this explanation. But i wonder, can i use these codes for real application such as online store, or do you have other codes for your real registration system that you use for yours?

    Reply
  13. I am just getting my head around the MVC framework concept, and decided to use your user-registration system as my test. It has proven to have been a good choice.

    I pulled the updated version, added the password library, made a few tweaks to my system and then had it working as it should. I really appreciated the opportunity to do so, thank you for sharing.

    I had to read up on ‘sessions’ as I initially tried to get the $data(session) variable into my system front page, but could not find a way to do so, checking the changes from CI2 to CI3, I found the solution that worked for me was to use the global $_SESSION variable.

    Reply
  14. I’m using CodeIgniter 3.0.1 – I have downloaded the files and added everyone correctly – the form is enabled and I enter my name, email address but when the enter a password and click to continue, I get the message: Unable to load the requested class: Password

    I have also ensured that my autoload includes the ‘security’, but no luck – do you have any idea why this should be happening?

    Reply

Leave a Comment.