Mar 282013
 

UPDATE: This is the second of a three part series on CodeIgniter, Redis, and Socket.IO integration. Please be sure to read the other posts as well.
Part 1: A Sample CodeIgniter Application with Login And Session
Part 2: You are here.
Part 3: Live Updates in CodeIgniter with Socket.IO and Redis

In my effort to add awesome real-time live updates to a plain ol’ CodeIgniter application, I decided to move the session information usually stored in a database table to a key-value store – namely, Redis. Not only does this alleviate some load from the MySQL database, but it also provides an easy way to expose user session data to a NodeJS server. This will be important in the future when adding Socket.IO.

The process for converting my existing application to use Redis rather than MySQL was painfully simple. It was pretty much just a handful of step-by-step instructions via the command line, and voila! PHP and Redis! BFFs 4Ever!

Here were the basic steps I followed:

1. Install Redis

Simply follow the instructions on in the Redis quickstart guide. These instructions were written for linux, and should work on most distributions. It might work on a Mac, but I’m not sure. Windows… you’re on your own. Below is the tl;dr version with just the commands.

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make

cd src
sudo cp redis-server /usr/local/bin/
sudo cp redis-cli /usr/local/bin/

sudo mkdir /etc/redis
sudo mkdir /var/redis

sudo cp utils/redis_init_script /etc/init.d/redis_6379
sudo cp redis.conf /etc/redis/6379.conf
sudo mkdir /var/redis/6379

From the Redis Quickstart Guide:

Edit the configuration file, making sure to perform the following changes:
Set daemonize to yes (by default it is set to no).
Set the pidfile to /var/run/redis_6379.pid (modify the port if needed).
Change the port accordingly. In our example it is not needed as the default port is already 6379.
Set your preferred loglevel.
Set the logfile to /var/log/redis_6379.log
Set the dir to /var/redis/6379 (very important step!)

sudo update-rc.d redis_6379 defaults
/etc/init.d/redis_6379 start

Boom. Done.

2. Install phpredis

PHP needs an extension to talk to Redis. There are a few options for this listed on the Redis site. I went with phpredis by Nicolas Favre-Felix mainly because it is required for the My_Session class used below. It’s also a great project that is still updated frequently.

To install, follow the directions in the README for your system. The default directions worked just fine for me.

git clone https://github.com/nicolasff/phpredis.git
phpize
./configure [--enable-redis-igbinary]
make && make install

Then add extension=redis.so to /etc/php5/apache2/php.ini and /etc/php5/cli/php.ini (if you are using Apache on linux). Finally, restart Apache.

Done, son.

3. Configure CodeIgniter to use Redis for session data storage

Finally, we just drop one class into the application’s library folder, and add a couple of lines to the config file to get everything working.

Really. That’s it. I’m not joking. It’s that easy.

Grab the MY_Session.php class from Ming Zhou’s gist: https://gist.github.com/zhouming/3672207 and drop it into /application/libraries. CodeIgniter will automatically use it as a subclass of Session. Most of the essential functions are overridden by My_Session so that Redis is used to store session data that will be used to authenticate user sessions while the application is running. The only thing left is to add the following two lines to /application/config/config.php:

$config['redis_host'] = 'localhost';
$config['redis_port'] = '6379';

Obvously you will need to change ‘localhost’ to the IP address of your Redis server if it is on a different machine from your application.

And that’s it! The application is Redis ready!

Note: I’ve added the MY_Session class and some installation notes to the ci_sock project in my GitHub repo, just in case the links become broken or you want an easy reference.

Mar 242013
 

Code Igniter App Screenshot

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. I’ve 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. It’s 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 user’s avatar reveals the username and tagline for that user.
  • Admins can create new user accounts.
  • A user’s 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. I’ve 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 I’ve 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.

You’ll 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 you’ve gotten the code checked out into your web root and the SQL imported, you’ll 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 application’s 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 echo form_open('login/login_user') ?>. The form_open function is part of CodeIgniter’s Form Helper, which generates the form’s 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 CodeIgniter’s 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 CodeIgniter’s 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 user’s 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 won’t 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 user’s 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 user’s session, retrieves all the user’s 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).

That’s 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…

UPDATE:
See Part 2: Use Redis instead of MySQL for CodeIgniter Session Data
and Part 3: Live Updates in CodeIgniter with Socket.IO and Redis

Mar 092013
 

VintageTxt<br />
Default

DEMO | SOURCE

Ever hearken back to the good ol’ days of the Apple II, with its monochrome screen and visible scanlines? No? Me either, really. I don’t even know what hearken means. But I do know that vintage looking stuff is cool, and people love it when all that is old is new again. So here is a jQuery plugin (new) that injects a green monochromatic scanlined fake computer screen (old) right onto any webpage. You can even make it type out a bunch of text, one character at a time – like that stupid computer from Wargames. No annoying voice-over though. And of course there is an input prompt, so you can bang away at your keyboard while pretending to break through 8 levels of top secret encryption to re-route the protocols through the mainframe and unleash your most advanced viruses… all while chanting, “enhance.”

Why make this? Fun, naturally. Plus I’ve been wondering lately what it would be like to make a jQuery plugin. I know I’m a little late to the jQuery party, and all the cool kids have move on bigger and better things, but the ability to whip up a jQuery plugin seems like one of those skills a self-respecting web developer should acquire at some point. Two helpful guides stocked the pot, and I threw in a bit of my own spicy sauce as I went along. I’m fairly satisfied with the end result, and the knowledge gained. To play around with a fully functional demo, click the link or image above. But to have some real fun, go grab the source from GitHub and VintageTxt your face off!