CodeIgniter…Meet Minify

As a followup to one of my previous posts I wanted to go through how I managed to get CodeIgniter and Minify to play nice with each other. Hopefully this will make someone else’s life easier. For those not using CodeIgniter this post might be either confusing or boring. Or both I guess.

My approach might seem code-heavy compared to other solutions but it has the virtue of requiring only a small change to single file that would be included by all pages on your site. That’s typically not a problem since the first thing I do when I’m working on a site is to break out the common elements such as the <html> and <head> tags to their own included header file.

In CodeIgniter I created a library called MY_Includes.php (/system/application/libraries/MY_Includes.php). This is the core class that contains the mappings between each controller and the JavaScript and CSS files required by the view that will be loaded by the controller that was invoked by the browser. Obviously this implies the extra step. If I create a new JavaScript or CSS file I can’t go into the globally included header file and add a <script> or <link> tag there - I have to edit MY_Includes.php to map the JavaScript or CSS file to that particular view. Yea, it seems weird to edit a PHP file to add a CSS or JavaScript file, but there are a couple of different factors at work here and this solution made the most sense to me. The big win was that it helped integrate Minify into my codebase with almost minimal effort.

You can see an edited version of MY_Includes.php here. I wanted to walk through this code a bit to highlight the important parts, but hopefully it’s readable on its own.

First, you’ll notice the constructor requires the name of the controller that was invoked. I’ll show you how I get that later on, but essentially the whole class relies on that piece of information. My application is fairly linear in the sense that once I know the controller’s name I know (barring exception cases) which view will be invoked.

This in turn allows me to map controllers directly to JS and CSS files, which is why you’ll see the init method set up 2 hashes containing the JS and CSS files that I have access to, jsFilesHave and cssFilesHave. The key in the hash is a logical name I will use when adding the file to a view. This will improve readability and reduce errors and maintenance. The value in the hash is a string that specifies where the corresponding source file can be found. This is relative to the web root and is of a form that Minify understands. Whenever I create a new JS or CSS file I have to first add it to one of these hashes so that I can refer to it later in the file.

One other note on the init - I’m not sure if I needed to, but I found it easiest to break with the CodeIgniter way of doing things and issue a PHP include statement to tell the class where to find the Minify source in the below snippet from that method.

//from minify examples:
//Add the location of Minify’s “lib” directory to the include_path.
ini_set(’include_path’, ‘/home/vdibart/minify/lib/.:’ . ini_get(’include_path’) );
require ‘Minify/Build.php’;
require ‘Minify.php’;

After init, the constructor will call compileTags. This is the heart of the logic. You can see it populate the cssFilesNeed and jsFilesNeed hashes, first with the files that are common to all views and then the ones depending on which controller was invoked.

Determining which controller was invoked is fairly straightforward. The following code is at the top of my globally included header file:

//for globally included header file
//so know which CSS or JS files to include
$pageName = $this->uri->segment(1, 0);
$pageName .= “/” . $this->uri->segment(2, “index”);
$this->load->library(”MY_Includes’, $pageName);

So if the controller was “http://www.mysite.com/member/register”, this code will pass “member/register” to the constructor of my class. Later on in the same header file I have the following 2 lines, which will extract the appropriate CSS and JS links:

<!– for globally included header file –>
<link rel=”stylesheet” href=”<?= $this->CI->my_includes->cssTag(); ?>” type=”text/css” media=”screen” />
<script src=”<?= $this->CI->my_includes->jsTag(); ?>” type=”text/javascript” charset=”utf-8″></script>

Switching back to the source code of MY_Includes.php, you can see those 2 methods invoke Minify to build the included files and then return a URL that can be used to retrieve the files. There’s a little bit of work in each of those to make the URL look like something that CodeIgniter will work with. So once the PHP executes the above tags will look like this in the final source code for the page:

<link rel=”stylesheet” href=”http://www.mysite.com/includetag/css/member-register/1222014216″ type=”text/css” media=”screen” />
<script src=”http://www.mysite.com/includetag/js/member-register/1222098068″ type=”text/javascript” charset=”utf-8″></script>

So each rendered page on my site has only 1 CSS file and 1 JS file included. And those files are minimized and cached. All of that is due to Minify. But you’ll notice there’s one piece of the puzzle still missing. The above <link> and script tags refer back to my site, and there has to be something that knows how to interpret that and return the appropriate CSS or JavaScript data. It turns out that “includetag” is a CodeIgniter controller that I created. I’ve included the source code here. There’s not a ton to mention here. The class loads the exact same helper class MY_Includes.php that interfaces with Minify to retrieve the CSS or JS file and return them to the client.

Hopefully there’s enough to get you through to a working version. To summarize the steps:

  1. Download MY_Includes.php (here) and put it in your /system/applications/libraries directory
  2. Edit the init method inside of MY_Includes.php to include the correct path to your Minify installation
  3. Edit the init method inside of MY_Includes.php to include your CSS and JS files
  4. Edit the compileTags method inside of MY_Includes.php to include the correct files for each controller
  5. Download includetags.php (here) and put it in /system/applications/controllers directory
  6. Add the two code fragments commented with “for globally included header file” above to the appropriate file in your application
  7. Fire it up
  8. Feel free to post a comment if you have troubles and I’ll walk you through it or edit the post to fix any errors as needed.

    These icons link to social bookmarking sites where readers can share and discover new web pages.
    • bodytext
    • Slashdot
    • del.icio.us
    • Facebook
    • StumbleUpon
    • Technorati
    • Reddit
    • NewsVine
    • Ma.gnolia
    • co.mments
    • Spurl
    • Furl

8 Comments so far

  1. Paul from Costa Rica on September 22nd, 2008

    Wow nice! I’ll dig in to this and let you know my results! Thank you!

  2. Padraig on September 29th, 2008

    Your link in step 5. links to your MY_Includes.php file instead of includetags.php

    The correct link is: http://www.nodroidsallowed.com/minify/includetags.php.txt

    Cheers for this though, I’m working on trying it out now.

    PK

  3. vdibart on October 1st, 2008

    Thanks Padraig! Fixed.

  4. Mathew on October 8th, 2008

    Oh my thankyou for this plugin. But when it comes to CI libs and plugins my question is where do I install so and so. So my question is after I downloaded the minify_2.1.0.zip where do I install the core files?

  5. Mathew on October 8th, 2008

    Oh another thing I did everything you instructed. But it seems I caught a snag in the process. I placed all the files in their respective directories but when I tried to load the library in my global header. CI spits an error saying that it cannot load the library. hmmm….

  6. vdibart on October 8th, 2008

    Mathew,

    Thanks for the question.

    I installed Minify outside of my web root. So, for instance, on my hosting account it was in /home/vdibart/minify. It actually doesn’t matter because of the line I pointed out towards the top of the post:

    ini_set(’include_path’, ‘/home/vdibart/minify/lib/.:’ . ini_get(’include_path’) );

    This is the absolute path to the Minify install directory, so effectively you can put Minify anywhere. I don’t have any opinion on the “right” place to put it, but others might.

    Hope this helped.

  7. vdibart on October 8th, 2008

    I’ll take this offline and report back once the issue is worked out so others know what was going on….

  8. Mathew on October 8th, 2008

    No it’s quite alright I just had to make a few adjustments. First off I think the version of CI I’m using does not allow loading of the library in the views(my suspicion actually). So I had to load the library the traditional OOP way. I change the the name of MY_Include.php to MinifyToo.php and it worked.

    But I haven’t found a way to output JS and CSS. It just outputs something like this…

    or

    href=”http://pleeperps.localhost/includetag/css/project-viewProject/0″

    I don’t know what that means but I’m more than willing to sit down with you and help you rewrite some parts of the library.

Leave a Reply