Advertisement
PHP

Advanced CodeIgniter Techniques and Tricks

by

CodeIgniter is a widely used PHP framework that aims to help developers write better structured code and remove boilerplate tasks from the workflow.

In this article, I'm going to explain some incredibly useful techniques to use when developing applications using CodeIgniter.


1. Easier Configuration Parameters

When creating libraries (or anything that requires configuration values) for our applications, we often need to use configuration parameters in order for it to be able to perform its tasks. When doing so, we can use the snippet shown below to obtain the configuration values.

$value	= $this->config->item( 'some_item' );

This is fine, if we have just a couple of configuration parameters, but when we need to extract a dozen configuration parameters or so, loading values this way can be very annoying. Wouldn't it be great to load every parameter like the array we use in the configuration file? In order to do just that you need to load it in the following way.

$this->load->config( 'config_file', true );
$options	= $this->config->item( 'config_file' );
// $options['some_item'];

And with that single line, our entire configuration file will be placed in the $options array. And to further sweeten the deal, using this technique also makes sure you avoid the name collision problem in configuration files. This way, your parameters can be named anything you'd like without worrying about other configuration files.


2. Allowing Optional Configuration Options

Building up on our earlier point, imagine a scenario where we'd like to pass parameters to our library from either a configuration file or an options array when loading it. Maybe we're using the same library in different parts of our application and the config options cannot be the same for each use case.

To be able to do this, place a private _options member in you library and use a constructor like the following.

private $_options	= array();

public function __construct( $options = array() ) {
	if ( is_empty( $options ) ) {
		$this->load->config( 'config_file', true );
		$options	= $this->config->item( 'config_file' );
	}
	
	$this->_options	= $options;
}

After this, you can access your parameters through the private _options array within your library, and, just like the previous example, you've avoided name collision problems with the keys in your configuration files.


3. Leveraging HTML Emails

The need to send HTML emails through your app is omnipresent, be it a newsletter or some automatic welcome message. Usually, you'd do this by hand coding the corresponding HTML in the message parameter of our email object (been there, done that).

Well, it's no secret that the above method is pretty ugly. The following tip is not quite a trick but merely a way to take advantage of some CodeIgniter functionality where it makes sense.

Personally, I prefer this approach as I manage a few sites where I need to send newsletters, and several other HTML emails, and using templates will significantly ease up the process.

In your application's views folder, create a folder called emails and place any HTML email you'd like to send inside it, with the corresponding structure to be rendered by email clients. And now, in the method where you shoot off the emails, you can use the following code:

public function send_mail() {
	$this->load->library( 'email' );
	$this->email->from( 'jdoe@gmail.com', 'John Doe' );
	$this->email->to( 'jane_doe@gmail.com' );
	$this->email->subject( 'Some subject' );
	$this->email->message( $this->load->view( 'emails/message', $data, true ) );
	$this->email->send();
}

A couple of important things to keep in mind when using this technique:

  • The email library must be set up to be able to send HTML emails
  • The data object used when loading the view should contain the options used in the view
  • With this approach, we're using the built-in functionality of retrieving the content of a view file instead of sending it to the output class by setting the third parameter to true when loading the view.

4. Managing Application Versions

Let's face it: almost every recent PHP application is a backend service or an API. If you have used the Google Maps API, you've probably noticed that Google allows us to pass a version parameter for us to tell it which version we're going to make use of.

Wouldn't it be nice if we can do this in our CodeIgniter applications? This way, we can create new versions of our software while supporting legacy versions to ensure backwards compatibility.

With this technique, we'll be able to use a single CodeIgniter installation to handle multiple versions of our application using the same index file. We'll be able to choose the version by passing a v parameter in the request.

There are a couple of things in order for this to work. First off, I'm going to rename my application folder. Since this is the first version of my API, I'll simply name it 1.0.0. After this, I'm going to rename my index.php file, call it 1.0.0.php and change the application_folder line in it. Replace line 75 with:

$application_folder	= '1.0.0';

Cool, now our application version is 1.0.0. Are we going to call that 1.0.0.php file instead of index? Absolutely not! Let's create a new index.php file and add the following code to it.

define( 'API_VER', 'v' );

array_key_exists( API_VER, $_REQUEST ) ? $v	= $_REQUEST[ API_VER ] : $v = '1.0.0';

if ( file_exists( "{$v}.php" ) ) {
	if ( is_dir( dirname( __FILE__ ) . "/{$v}" ) ) {
		require dirname( __FILE__ ) . "/{$v}.php";
	} else {
		$error	= new stdClass();
		$error->error		= true;
		$error->description	= 'INVALID_API_VERSION';
		echo json_encode( $error );
		exit;
	}
} else {
	$error	= new stdClass();
	$error->error		= true;
	$error->description	= 'INVALID_API_VERSION';
	echo json_encode( $error );
	exit;
}

Here, we're defining the parameter that we'll use to choose the version. If no version is passed, we use the 1.0.0 version. If a version is passed, we make sure there's a corresponding file and folder for that version. Otherwise, we throw an error.

To add more versions, we'd simply have to copy our 1.0.0 folder and the 1.0.0.php file, rename them according to the version we're going to create, change the application_folder variable in the file and start working on the next version of our API. When we feel comfortable enough with it, we can make it the version by modifying the index.php file.


5. Serving Separate Response Formats

Dot notation? No, I'm not talking about Objective-C messages. If you have used the Twitter API or something similar, you'll remember that at the end of the method call, you can specify the format you want the response in. As I really like to create RESTful services using CodeIgniter, I like to add this functionality to them even though I've always use JSON.

In order to do this, we need to take advantage of CodeIgniter hooks to preprocess our URI. We'll use two hooks for this process, and we'll set a config item to set the response format accordingly.

First off, what are hooks? According to the CodeIgniter user guide,

CodeIgniter Hooks feature provides a means to tap into and modify the inner workings of the framework without hacking the core files

In plain English, they're a way to change the normal execution flow of an application. Although we don't want to do precisely that here, we do want to preprocess our URI before the CodeIgniter Router class has a chance to inspect it. With that in mind, we're going to make use of the "pre_system" hook.

In order for us to use hooks we have to enable them. To do that, open the config.php file under the config and set the enable_hooks item to true.

$config['enable_hooks']	= TRUE;

We now need to add the hook that will take care of the pre-routing process. Inside the config folder in your application folder, open the hooks.php file and add the following code:

$hook['pre_system']	= array(
	'class'		=> 'Router',
	'function'	=> 'route',
	'filename'	=> 'router.php',
	'filepath'	=> 'hooks'
);

What this code does is that it tells our application to run the route method of our Router class inside our hooks folder. A quick note here: the filepath parameter is the path to the file that has the method you want to call, and it MUST be relative to your application folder WITHOUT a trailing slash.

Now we need to create the class and method that this hook is going to call. In your hooks folder (if it's not there, create it) inside your application folder, create a new file, name it router.php and place the following code in it.

if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class Router {
	
	private static $_format	= '';
	
	public function route() {
		$request				= strstr( $_SERVER['REQUEST_URI'], '?', true );
		if ( !$request ) {
			$request			= $_SERVER['REQUEST_URI'];
		}
		$parts					= explode( '.', $request );
		self::$_format			= $parts[ sizeof($parts) - 1 ];
		
		if ( self::$_format == 'json' || self::$_format == 'xml' || self::$_format == 'rss' || self::$_format == 'atom' ) {
			$_SERVER['REQUEST_URI']	= substr( $request, 0, ( strlen( $request ) - strlen( self::$_format ) - 1 ) );
		} else {
			self::$_format	= '';
		}
	}
}

CodeIgniter Hooks feature provides a means to tap into and modify the inner workings of the framework without hacking the core files

A couple of things to note here. First off, you'll notice that I'm using an static class member to store the type of the request. That's because we're getting the response format correctly, but we cannot tell the rest of the application about it. At this early point of the application execution, the config class is not yet loaded so we need to use another hook. With that in mind, we'll need to make it static so it's not overridden when we call the next hook.

Right at the beginning, I'm checking for an ? symbol, so the rerouting here won't conflict with any parameters passed through the URL. The strstr method will return the string BEFORE that character as the third parameter is set to true. Do keep in mind that this behavior was added in PHP 5.3.0, so if you're using a previous version, you'll need another way to obtain the part of the string before the ? symbol.

Because of the way we're retrieving the requested response format from the URI and then setting the REQUEST_URI key manually for the CodeIgniter Router, we need to check that the output requested is valid. If not, we let the application handle the request without interfering.

Now we have identified the requested response format but our controllers doesn't know about it. I think that a clean way to inform this is with a config parameter. In order to set it we need to use another hook. The first two hooks are pre_system and pre_controller.

However, at this point we cannot use the get_instance method, meaning we can't set a config item, so we'll use the post_controller_constructor hook. As long as you don't intend to use the response format config item in the controllers constructors this technique will work.

After the pre_system hook in the hooks.php file add the following code.

$hook['post_controller_constructor'] = array(
	'class'		=> 'Router',
	'function'	=> 'config',
	'filename'	=> 'router.php',
	'filepath'	=> 'hooks'						
);

As you can tell, this hook is calling another method in the same class that we use to retrieve the requested response format. In the Router class after (or before) the route method, add the following code.

public function config() {
	$CI		=& get_instance();
	$CI->config->set_item( 'response_format', self::$_format );
}

In this method, we're setting a configuration option called response_format with the format retrieved on the route method.

Finally, to use this response format in your controllers (or anywhere in your application) use the following code.

$format	= $this->config->item( 'response_format' );

And with that, you can retrieve the requested format and parse the result accordingly. As to parsing the response, I leave it as an exercise to the reader.


Conclusion

I hope you've found some of these tips useful. As you may have noticed, I've focused on RESTful services since, in my opinion, they are what we as PHP developers should be focusing on.

I look forward to your comments and thank you so much for reading.

Related Posts
  • Code
    Web Development
    Laravel Unwrapped: Session, Auth and CacheLaravel wide retina preview
    Join me as we learn how to use Laravel's component-based system, Illuminate. Additionally, we'll see how to utilize service providers, Laravel's manager system, the Session, Auth, and Cache components, and the Store, Guard, and Repository libraries.Read More…
  • Code
    PHP
    Setting Up a Local Mirror for Composer Packages With SatisComposer retina preview
    Installing all your PHP libraries with Composer is a great way to save time. But larger projects automatically tested and run at each commit to your software version control (SVC) system will take a long time to install all the required packages from the Internet. You want to run your tests as soon as possible through your continuous integration (CI) system so that you have fast feedback and quick reactions on failure. In this tutorial we will set up a local mirror to proxy all your packages required in your project's composer.json file. This will make our CI work much faster, install the packages over the local network or even hosted on the same machine, and make sure we have the specific versions of the packages always available.Read More…
  • Code
    PHP
    Building a Customer Management App Using AngularJS and LaravelLaravel 4 auth retina preview
    When creating a single-page app we should use some kind of framework to do some of the job for us, so we can focus on the actual functionality. AngularJS fits here perfectly, because features like dynamic dependency injection and bi-directional data binding are just great. Sometimes we also require some kind of server. If you've chosen PHP then Laravel may be your best option, as it's easy to work with and pretty powerful.Read More…
  • Code
    PHP
    25 Laravel Tips and TricksCode
    There was a period of time, not too long ago, when PHP and its community were, for lack of better words, hated. Seemingly, the headline joke of every day was one that related to how terrible PHP was. Let's see, what new PHP-slamming blog article will be posted today?Read More…
  • Code
    JavaScript & AJAX
    Introduction to Sails.jsSails preview 400 2
    Sails is a Javascript framework designed to resemble the MVC architecture from frameworks like Ruby on Rails. It makes the process of building Node.js apps easier, especially APIs, single page apps and realtime features, like chat.Read More…
  • Code
    PHP
    Building a CodeIgniter Web Application From Scratch - Part 1Web app retina preview
    In this series we're going to build a web billboard application from scratch, we're going to use CodeIgniter to handle the back-end service and BackboneJS for the web client. In the first two parts of the series we'll create the back-end service and then the client application in the last two.Read More…