dotMobimobiThinkingmobiForgemobiReadyDeviceAtlasgoMobi
background image

A Simple Mobile Site with CodeIgniter

Edson Martins
Posted by atrasatti - 26 Jan 2009
Twitter share icon Facebook share icon Google Plus share icon

In the words of the developers "CodeIgniter is an Application Development Framework - a toolkit - for people who build web sites using PHP. Its goal is to enable you to develop projects much faster than you could if you were writing code from scratch, by providing a rich set of libraries for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. CodeIgniter lets you creatively focus on your project by minimizing the amount of code needed for a given task."
While CodeIgniter can be considered a small framework compared to competitors such as Zend Framework, it comes with all the basic libraries that we are all using in every single project we develop. The community also provides a number of extra libraries for some more specific tasks. At the bottom of the article you will find a number of links to the official website, documentation forums, etc.

In this short tutorial I will show you how to get started with the development of a simple site to display mobiForge's RSS feed on a PC or on a generic mobile device. This will allow us to focus on how CodeIgniter applications are developed and how its basic device detection can be implemented. Basic PHP knowledge is required, especially if you want to enhance the application beyond this guide; knowledge of RSS is not required. Basic knowledge of XHTML and CSS are also recommended, but not required.

The reasons why I immediately like CodeIgniter is the simplicity of the approach and the provision of a number of very common features such as clean, semantic URLs, MVC (Model-View-Controller) approach and extensibility.

I will not go into the details of installing as the process is so simple and well explained on the official site. For the sake of this article, all you need to do is unzip CodeIgniter in your Document Root and edit the file system/application/config/config.php and change the value of base_url to http://mobilefeed.local/.

I want to point out, though, that CodeIgniter assumes one install for every application that you want to develop. Make sure you fill the appropriate parameters as described in the installation guide, in this case setting only the base URL should be enough, in my case I used "makefeed.local" as I am developing on my Mac. If you intend to move your application to a public server then you will have to use the appropriate address, of course.

Getting started

To get started we will create a new controller called feed.php in the system/application/controllers directory, in fact all files that belong to our application will be in a subdirectory of system/application/ as per the CodeIgniter defaults. Paste the following code in your new file using your favourite text editor:

<?php
 
class Feed extends Controller {
  function index() {
    $this->feed_list();
  }
 
  function feed_list() {
    $this->load->view('feed_basic');
  }
}
 
?>

This way we have created a very basic controller that does nothing but show the content of the view called feed_basic. The function index.php is executed by default when no other parameters are called and this will invoke our default method feed_list that will show the list of articles in the feed.

We now need to create the view file. Note the line that initialises the view, $this->load->view('feed_basic');, this is a standard CodeIgniter call and will load a file called feed_basic.php in the views subdirectory. Let's create the file and paste this simple markup:

<?php echo "<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC '-//WAPFORUM//DTD XHTML Mobile 1.0//EN' 
  'http://www.wapforum.org/DTD/xhtml-mobile10.dtd'>" ?>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<title>mobiForge mobile RSS</title>
</head>
<body>
<p>Welcome to a mobile-friendly version of the mobiForge RSS.</p>
</body>
</html>

We can see the first result visiting http://makefeed.local/index.php/feed, this is a standard CodeIgniter URL which make it call the feed.php controller. The framework documentation also explains how you can configure rewrites so that index.php is not required and how you can make a controller the default action. These steps are out of scope for this article, but they are very well explained in the documentation and only take just a few steps.


Loading some content from RSS

So far, not very exciting and not even of any use. We need an RSS feed parser and we surely do not want to do everything from scratch, in fact already developed a very nice library called SimplePie. As example of how easily you can extend CodeIgniter, just go and download SimplePie, and unzip it in system/application/libraries. That's it, now we can instantiate it. Let's see a few changes I made to feed.php, a small helper function to initiate the SimplePie:

<?php
   function _feed_init() {
    $this->load->library('simplepie');  //This is all you need to initialise a library in CodeIgniter
    $this->simplepie->set_cache_location('/tmp/');  //Change this to any temp directory that works for you
    $this->simplepie->set_feed_url('mobiforge.com/rss.xml');
    $this->simplepie->init();
  }

Nothing special here, but if we want to pass dynamic parameters at a later stage it might be useful, for example to manage different feeds or specific values for caching, encoding and so on.

Then a little loop to cycle through the elements, this is particularly useful to manage parameters for the items that we want to load:

  function _get_items($offset, $amount) {
    $this->load->helper('url'); // useful to check, parse and clean URLs
    $blog_items = $this->simplepie->get_items($offset, $amount);  //load $amount RSS items starting from $offset
    $count = 0;
    //Loop through the RSS items to create a nice associative array for display in a view
    foreach($blog_items as $item) {
      $data['blog_items'][$count]['title'] = $item->get_title();
      $data['blog_items'][$count]['author'] = $item->get_author()->get_name();
      $data['blog_items'][$count]['local_date'] = $item->get_local_date();
      $data['blog_items'][$count]['content'] = $item->get_content();
      $data['blog_items'][$count]['permalink'] = $item->get_permalink();
      $count++;
    }
    return $data;
  }

This was an important step because the view engine in CodeIgniter is not very powerful, but it is very efficient; preparing the right variables in the right way will make it much easier and speedier to print. I will not go into the detail of each SimplePie method, the name should be self-explanatory, you are welcome to read the official documentation for more details.

Let's update the view to display some dynamic values. All the information loaded from SimplePie was stacked up in an associative array called $data and passed to the view as the second parameter, this is the standard way of doing this in CodeIgniter. By magic of the framework, the array will not be available in the view, but all of the keys of the array will be variable names. When creating a more complex structure such as the blog_items we will have to cycle them with a loop. Let's see how the new view should look like:

<div class="articles">
<?php foreach($blog_items as $item) : ?>
  <h1><a href="<?php echo $item['permalink'] ?>"><?php echo $item['title'] ?></a></h1>
  <p><em>Author: <?php echo $item['author'] ?> On <?php echo $item['local_date'] ?></em></p>
  <p><?php echo $item['content'] ?></p>
<?php endforeach; ?>
</div>

You may now reload http://makefeed.local/index.php/feed and you will magically see the latest 5 articles that were published here on mobiForge, woohoo!

To display the blog articles we had to use the alternative syntax for the foreach loop, this is a requirement of CodeIgniter. You can read more about this on the official PHP documentation.

As you might have noticed with the method _get_items() we have already laid down the stepping-stones for pagination. While this might not be an issue in RSS readers and on your PC or Mac, it might be an issue on mobile devices; in fact, even if we listed only the titles of each articles that might easily be simply too long and not very comfortable on some devices. Paginating at a reasonable number of articles per page will make it much easier to use and faster to load.

Since mobiForge only provides the excerpt of articles we do not have to worry too much about the size of the page, as long as we keep a small number of articles per page, of course. Also, the RSS feed already provides the "Read more" link, so it's a much easier job for us.

Making it more mobile friendly

Let's add some mobile specific stuff, now. We will use the nice and simple User Agent class that comes with CodeIgniter.

We are now going to add a check to see if the user is on a mobile device or a desktop computer, add icons to switch to an alternative presentation and pagination. It seems like a lot of stuff, but it's not complicated. If you want to see some icons that we designed you should see Mobile and Desktop Switching Icons and I also recommend you read A Very Modern Mobile Switching Algorithm - Part I and Part II, if you haven't done so, yet.

So here is the updated feed.php:

<?php
  function feed_list($page=1) {
    $this->load->library('user_agent');
    $this->load->helper('url'); // useful to check, parse and clean URLs
    $this->_feed_init();  //Init SimplePie
 
    $amount = 5;  //show only 5 items, we do not want to overflow the device
    $offset = ($page-1)*$amount;  // Manage pages, arrays start from 0
    $data = $this->_get_items($offset, $amount);
 
    // check if it's mobile
    $data['alternate_icon'] = 'http://www.mobiforge.com/files/switching_icons/gray/set_02_desktop_icon_16x16.png';
    $data['alternate_url'] = 'http://mobiforge.com/tracker';  // See all the latest messages on mobiForge in a nice HTML page
    if ($this->agent->is_mobile()) {
      // This is a mobile device
      $data['is_mobile'] = true;
    } else if ($this->agent->is_robot()) {
      // This is a robot, treat it like a mobile device so that our content is indexed
      $data['is_mobile'] = true;
    } else {
      // We will show a message to ask the user if he wants to switch to an alternative presentation
      $data['is_mobile'] = false;
    }

Since this is a mobile device and we have limited to 5 items per page, let's manage pagination and get some details about the RSS feed so that we can display them on the final page:

    // We are still editing feed_list()
 
    // Some default stuff
    $data['blog_title'] = $this->simplepie->get_title();
    $data['blog_item_count'] = $this->simplepie->get_item_quantity(); // total articles in feed
    $data['current_page'] = $page;  // where we are now
    $data['total_pages'] = ceil($data['blog_item_count']/$amount);  // total number of pages
    if ($data['total_pages'] > $page) {
      $data['last_page'] = site_url('/feed/page/'.$data['total_pages']);  // jump to a given page using the site_url function to define a proper full URL
    } else {
      $data['last_page'] = false;
    }
    if ($page < $data['total_pages']) {
      $next_page = $page+1;
      $data['next_page'] = site_url('/feed/page/'.$next_page);
    } else {
      $data['next_page'] = false;
    }
    if ($page>1) {
      $prev_page = $page-1;
      $data['prev_page'] = site_url('/feed/page/'.$prev_page);
    } else {
      $data['prev_page'] = false;
    }
    $data['start'] = $offset;
    $data['length'] = $amount;

In order to be able to use nice URLs such as /feed/page/2 we need to create a function, in fact each element of the URL is passed to the code and automatically turned into a specific call, the feed calls the class, page is the function and 2 is the parameter. See on the CodeIgniter site to learn how to pass further parameters or how you can call classes and methods in sub-directories.

  /*
   * Helper function to make the URLs nicer. Get the $page number and pass to feed_list
   */
  function page($page=1) {
    // make sure $page IS an integer and 1 or more
    $page = intval($page);
    if (intval($page)<=1) {$page=1;}
    $this->feed_list($page);
  }

And then...

  function _get_items($offset, $amount) {
    $blog_items = $this->simplepie->get_items($offset, $amount);  //load $amount RSS items starting from $offset
    $count = 0;
    //Loop through the RSS items to create a nice associative array for display in a view
    foreach($blog_items as $item) {
      $data['blog_items'][$count]['title'] = $item->get_title();
      $data['blog_items'][$count]['author'] = $item->get_author()->get_name();
      $data['blog_items'][$count]['local_date'] = date("Y-m-d", strtotime($item->get_local_date()));
      if ($this->agent->is_mobile() || $this->agent->is_robot()) {
        // if it's a mobile or a robot replace .com with .mobi so that clicking on "Read more" will go to the mobile site
        $data['blog_items'][$count]['permalink'] = str_replace('mobiforge.com', 'mobiforge.mobi', $item->get_permalink());
        $data['blog_items'][$count]['content'] = str_replace('mobiforge.com', 'mobiforge.mobi', $item->get_content());
      } else {
        $data['blog_items'][$count]['permalink'] = $item->get_permalink();
        $data['blog_items'][$count]['content'] = $item->get_content();
      }
      $count++;
    }
    return $data;
  }

Notice how I "hacked" the permalink so that it points to the .mobi instead of the .com. I know that mobiForge has specific presentation for .mobi domain that is mobile-friendly (of course!) and even if the User_Agent class of CodeIgniter was wrong, it would still offer to switch to a desktop presentation, so this is the safest approach.

And the new view:

<p>Welcome to a mobile-friendly version of the mobiForge RSS. You are seeing page <?php echo $current_page ?> of <?php echo $total_pages ?>.</p>
<?php if ($is_mobile === false ): ?>
<!-- this is not a mobile device -->
<p>You requested the mobile site, but you appear to have a desktop browser.
<img src="<?php echo $alternate_icon ?>" alt="desktop icon"/><a href="<?php echo "$alternate_url" ?>">Revert to the desktop site</a></p>
<?php endif; ?>
<div class="articles">
<?php foreach($blog_items as $item) : ?>
  <h1><a href="<?php echo $item['permalink'] ?>"><?php echo $item['title'] ?></a></h1>
  <p><em>Author: <?php echo $item['author'] ?> On <?php echo $item['local_date'] ?></em></p>
  <p><?php echo $item['content'] ?></p>
<?php endforeach; ?>
</div>
<div class="page_links">
<?php if ($total_pages > 1): ?>
<p>Go to page:<br />
<?php if ($current_page > 1 ): ?>
<a href="1">First</a>
 
<?php endif; ?>
<?php if ($prev_page !== false): ?>
<a href="<?php echo $prev_page ?>">&lt;</a>
<?php endif; ?>
<?php if ($next_page !== false): ?>
<a href="<?php echo $next_page ?>">&gt;</a>
<?php endif; ?>
<?php if ($last_page !== false): ?>
<a href="<?php echo $last_page ?>">Last</a>
<?php endif; ?>
</p>
<?php endif; ?>
</div>
<?php if ($is_mobile === true ): ?>
<div class="mobile_switch">
<!-- this is a mobile device, but we still offer to the user the opportunity to switch -->
<p><img src="<?php echo $alternate_icon ?>" alt="desktop icon"/><a href="<?php echo "$alternate_url" ?>">Visit the desktop site</a></p>
</div>
<?php endif; ?>
</body>
</html>

In this final step, as I said, I used the existing User_Agent class; it's based on simple keywords, but this makes it good enough to detect standard mobile devices, desktop browsers and even robots. Being based on simple text it's quite easy to extend: if a new super-cool device comes out, you can add it straight (or better extend the basic class with your own). If you look at the class you will noticed that the iPhone and the iPod touch have special entries and it is as easy as adding a key and a value to an array.

I also tried to keep the links to jump to the other pages as small as possible, but you it is up to you what you want to provide to your users, for example for an RSS feed I would be surprised if visitors went beyond the second page.

If the browser is not mobile I provided the link to switch up at the top, well visible, while if it's mobile I provided it down at the bottom, just to make sure it would be available as an option, but not eating up useful space. For this article I did not want to go into the trouble of the interstitial page as per James' tutorial, but this should not stop you from aiming to perfection!

Conclusions

CodeIgniter is a very good framework to get started, the learning curve is really low and provides all the basic functions you will need and that are needed in modern web development such as nice URLs, templating system and of course database abstraction, etc. The pre-installer User_Agent class is very basic, but provides the minimum requirements to make a basic detection and it can be VERY EASILY enhanced and customised. All in all it's a perfect compendium to get started with a mobile site very quickly.

Make sure you download the attached package to get the final files, also referencing our mobiForge mobile-specific CSS.

Useful links and references:

AttachmentSize
CI_simple_mobile.zip2.65 KB

Posted by atrasatti - 26 Jan 2009

atrasatti's picture

Andrea Trasatti is Director of Technology Strategy at dotMobi where among the other things he is leading the design and development of DeviceAtlas.
Prior to this Andrea has been a system administrator and a software developer for more than 10 years and a consultant for more than 5 years.
In Italy Andrea started developing the first WAP sites in late 1999 when the first WAP phone was about to be released. Since then he has been developing some of the most innovative services for mobile devices.
Andrea has also actively participated to W3C work first as an invited expert and later as author of one of the documents that was published by the Device Descriptions Working Group.

Posted by Intertox 1 year ago

CodeIgniter PHP framework is the best of today

[url=http://www.intertox.com.br]Toxicologia[/url]