Sei sulla pagina 1di 10

A Sample CodeIgniter Application with Login

And Session
MARCH 24, 2013 / ETERPS / 49 COMMENTS

CODE | DEMO
UPDATE: This is the third of a three part series on CodeIgniter, Redis, and Socket.IO integration. Please be sure to
read the other posts as well.
Part 1: You are here.
Part 2: Use Redis instead of MySQL for CodeIgniter Session Data
Part 3: Live Updates in CodeIgniter with Socket.IO and Redis
I was assigned to work on a PHP project a few weeks back that utilized the CodeIgniter framework. Ive used MVC
frameworks in the past in other languages, and because CodeIgniter does not deviate too far from common MVC
patterns, it was pretty easy to pick up. To get myself up to speed, I put together a sample project based of what I
learned from the documentation and a few tutorials. Its a small microblogging app with very basic user auth and
CRUD functionality. The basics of it go like this

User login screen with basic password authentication.

Each user is assigned a team number. Users can only view posts from their teammates.

An admin can view all posts from all users.

Each user has a tagline.

The tagline can be edited by clicking on it and typing something new (modern browsers only, as it uses
contenteditable)

Hovering over a users avatar reveals the username and tagline for that user.

Admins can create new user accounts.

A users own messages appear below their profile. This is limited by 5 posts, currently.

Careful, there is not much form validation going on at the moment.

Building it gave me a good feel for the basic mechanics of CodeIgniter and allowed me to brush up on some PHP.
The real motivation behind this project, however, is to eventually work in a Socket.IO implementation to allow real
time updates for the user. Ive been eyeing NodeJS for quite some time now, but never really had cause to use it.
Fortunately, the project I was working on needed a more robust and scalable real time framework to replace a
rudimentary long-polling system. Socket.IO would have been a pretty good solution, in my opinion. Unfortunately,
the project was cancelled before I could get started. But since Ive already got the ball rolling on this sample
application, I figure I might as well finish, and learn a few things in case a situation like this arises again. You never
know

The Setup
The front end of the application uses Twitter Bootstrap for styling and layout, jQuery for client-side interactivity, PHP
and CodeIgniter for most of the functionality, and MySQL for data storage. This is a fairly common toolset that runs
on most L/W/M/AMP-style environment stacks. The code available on GitHub has everything you need to run the app
yourself, provided you have a web server, MySQL, and PHP 5.3 or greater.

Youll need to create a database (preferably called cisock), and then import cisock.sql in the root of the partOne
folder in the repository. You can do this with the following command from the command line (be sure to change
yourusername and /path/to/ to match your local setup):
mysql -u yourusername -p -h localhost cisock < /path/to/cisock.sql

Once youve gotten the code checked out into your web root and the SQL imported, youll need to do some slight
configuration before getting started. In part_one/application/config/config.php you will need to change line 17 to
reflect your local URL. If you simply cloned the project directly into your localhost web root, then no changes will
likely be needed. A similar fix is necessary in part_one/assets/js/main.js line 6. The context root of your application
goes here. Again, if you cloned to your web root, the default value should be fine. Ideally, the context root should
only have to be configured in one place, but it is what it is for now.
Secondly, the settings in part_one/application/config/database.php must be set to reflect your local database
configuration. The following entries are specific to your local environment:
$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'yourdatabaseusernamehere';
$db['default']['password'] = 'yourdatabasepasswordhere';
$db['default']['database'] = 'cisock'; //or use the database name you chose, if it is different

Once that is done, you should be able to navigate your browser to the /part_one/ directory and see the login screen.

To recap:
1.

Clone the repo

2.

Set up the database and import the tables from cisock.sql

3.

Edit database.php and also config.php and main.js if necessary

The Code
I tried to follow suggested CodeIgniter conventions as closely as possible. As such, the file and directory structure is
pretty much as it is out of the box. I altered /application/config/routes.php to set the login controller as the entry
point for the application like so:
$route['default_controller'] = "login";

The index method in /application/controllers/login.php checks to see if the user is logged in, and if not will redirect to
the login screen by calling the show_login function. The code immediately below is login/index which will run when
applications url is loaded in the browser.
function index() {
if( $this->session->userdata('isLoggedIn') ) {
redirect('/main/show_main');
} else {

$this->show_login(false);
}
}

Because the isLoggedIn session variable starts out as false, the show_login() function is called. The false
argument indicates that an error message is not to be shown.
function show_login( $show_error = false ) {
$data['error'] = $show_error;
$this->load->helper('form');
$this->load->view('login',$data);
}

That last line there:

$this->load->view('login',$data);

is what opens up the login view ( /application/views/login.php ). When

the user types in credentials and clicks the sign-in button, the login_user function is called through a normal form
POST as indicated by this line of code in /application/views/login.php:

<?php echoform_open('login/login_user') ?>.

The

form_open function is part of CodeIgniters Form Helper, which generates the forms HTML for you.
The login/login_user function gives us our first taste of a CodeIgniter model. It loads up an instance of a user model
and calls the validate_user method on that model, passing it the email and password typed in by the user. Take a
look at the code below for the entire sequence.
function login_user() {
// Create an instance of the user model
$this->load->model('user_m');

// Grab the email and password from the form POST


$email = $this->input->post('email');
$pass = $this->input->post('password');
//Ensure values exist for email and pass, and validate the user's credentials
if( $email && $pass && $this->user_m->validate_user($email,$pass)) {
// If the user is valid, redirect to the main view
redirect('/main/show_main');
} else {
// Otherwise show the login screen with an error message.
$this->show_login(true);
}
}

In the user model, a couple of interesting things happen. First, a query is built using CodeIgniters ActiveRecord
implementation. The username and password entered by the user are compared to the user table in the database to
see if the credentials exist. If so, the corresponding record in the database will be retrieved. If that happens, the
data retrieved from the database will be used to set session variables using the set_session function of
CodeIgniters Session class. All the code for this is in /application/model/user_m.php and can be seen below.
var $details;
function validate_user( $email, $password ) {
// Build a query to retrieve the user's details
// based on the received username and password

$this->db->from('user');
$this->db->where('email',$email );
$this->db->where( 'password', sha1($password) );
$login = $this->db->get()->result();
// The results of the query are stored in $login.
// If a value exists, then the user account exists and is validated
if ( is_array($login) && count($login) == 1 ) {
// Set the users details into the $details property of this class
$this->details = $login[0];
// Call set_session to set the user's session vars via CodeIgniter
$this->set_session();
return true;
}
return false;
}
function set_session() {
// session->set_userdata is a CodeIgniter function that
// stores data in a cookie in the user's browser. Some of the values are built in
// to CodeIgniter, others are added (like the IP address). See CodeIgniter's documentation for details.
$this->session->set_userdata( array(
'id'=>$this->details->id,
'name'=> $this->details->firstName . ' ' . $this->details->lastName,
'email'=>$this->details->email,
'avatar'=>$this->details->avatar,

'tagline'=>$this->details->tagline,
'isAdmin'=>$this->details->isAdmin,
'teamId'=>$this->details->teamId,
'isLoggedIn'=>true
)
);
}

So now that the user is authenticated and their session info is set in a cookie, CodeIgniter will take an extra step
and store the users IP address, session ID, user agent string and last activity timestamp in the database. So when
the user logs out, closes the browser, or is idle for too long, the session will expire and be cleared from the
database. If someone with a cookie containing the same session ID then tries to connect to the application, it will be
invalid because it wont match any of the sessions stored in the database. Check out the Session class
documentation for a more thorough explanation.

So now that the user is logged in, the main controller can do its thing. The show_main function runs just before
loading the main view, and does a number of things to prepare for displaying the view to the user. The users details
are used to change certain parts of the view, such as which posts to display (team only, or everyone) and the admin
controls.
The show_main function grabs some data from the users session, retrieves all the users posted messages, counts
the total number of messages posted by the user, and retrieves the messages from other users. All of this info is
placed into the $data object and passed to the main view (/application/views/main.php). Much of the heavy lifting
is taken care of by ActiveRecord commands in the Post model (/application/model/post_m).

Thats about it, as far as logging in goes. Now that everything is set up using conventional CodeIgniter practices, I
can begin the process of converting the server side session data to be stored in Redis, rather than in a MySQL
table

Potrebbero piacerti anche