About Jamie on Software

Jamie on Software is Jamie Rumbelow's online journal. An opinionated, charismatic teenager's views on web development, business, programming, education, technology and journalism.

Sparkplugs

We build ExpressionEngine and MojoMotor add-ons to help web professionals build better sites.

http://getsparkplugs.com/

Tags
Tweets
Feeds
We Love
Powered by Squarespace

Entries in codeigniter (9)

Thursday
Feb232012

The CodeIgniter Handbook - Volume 1 - Available!

I am utterly thrilled to announce that my new book, The CodeIgniter Handbook Volume 1, is now available for order!

Volume 1, Who Needs Ruby? is a pragmatic, succinct guide to improving your efficiency and the cleanness of your code. Attractive to amateurs and professionals alike, The CodeIgniter Handbook isn't your usual programming book. It's short, useful and easy to read, and covers how to improve the quality of your code and the speed of your development time.

It's available to buy as a print book or an eBook. It's also much cheaper than most programming books, at only £12 (roughly $18) for the print book and £6 ($10) for the eBook.

I've had some great feedback already -- everyone appears to be enjoying it! Thanks for your support.

Purchase the CodeIgniter Handbook today!

Saturday
Jan072012

Syntax Sugar #5 - A Quick CodeIgniter Caching Helper Function

Caching your data in CodeIgniter? Good. You should be.

I use memcached lots. CI has a fantastic caching driver built in (as of 2.0). Normally, the code you'll write looks like this:

$accounts = $this->cache->memcached->get('user.' . $user_id . '.accounts');

if (!$accounts)
{
    $accounts = $this->db->where('user_id', $user_id)->get('accounts')->results();
    $this->cache->memcached->save('user.' . $user_id . '.accounts', $accounts);
}

$this->load->view('accounts/index', array( 'accounts' => $accounts ));

However this quickly becomes repetitive, boring and cluttering. With a bit of PHP5.3 magic, we can create a really nice little caching helper function that cleans this code up in no time:

function cache($key, $data) {
    $CI =& get_instance();
    $cache = $CI->cache->memcached->get($key);

    if (!$cache) {
        // There's been a miss, so run our data function and store it
        $cache = $data($CI);
        $CI->cache->memcached->save($key, $cache);
    }

    return $cache;
}

Now, our cluttered caching code becomes a commendable concoction of coding culinary craft:

$accounts = cache('user.' . $user_id . '.accounts', function(&$ci){
    return $ci->db->where('user_id', $user_id)->get('accounts')->results();
});

The anonymous method you pass through will only be executed if the cache misses (i.e. there's no data under that key, or it has expired). It will be saved into the cache and return. Delicious.

Monday
Dec262011

CodeIgniter View Presenters

Whenever building applications with CodeIgniter, I always try my best to follow the Model-View-Controller design pattern as much as possible. MVC tells us that views are the presentational filter of the model's data. Over the course of an application's development, it can be very common for views to grow and accumulate cruft. I find that presenters can be a really sleek way of hiding presentational logic away in a class.

Let's look at a simple view that displays some information about a user's bank account:

<div id="account">
    <h1><?= $this->bank->get($account->bank_id)->name ?> - <?= $account->title ?></h1>

    <p class="information">
        <strong>Name:</strong> <?php if ($account->name): ?><?= $account->name ?><?php else: ?>N/A<?php endif; ?><br />
        <strong>Number:</strong> <?php if ($account->number): ?><?= $account->number ?><?php else: ?>N/A<?php endif; ?><br />
        <strong>Sort Code:</strong> <?php if ($account->sort_code): ?><?= substr($account->sort_code, 0, 2) . "-" . substr($account->sort_code, 2, 2) . "-" . substr($account->sort_code, 4, 2) ?><?php else: ?>N/A<?php endif; ?>
    </p>

    <p class="balances">
        <strong>Total Balance:</strong> <?php if ($account->total_balance): ?><?= "&pound;" . number_format($account->total_balance) ?><?php else: ?>N/A<?php endif; ?>
        <strong>Available Balance:</strong> <?php if ($account->available_balance): ?><?= "&pound;" . number_format($account->available_balance) ?><?php else: ?>N/A<?php endif; ?>
    </p>

    <p class="statements">
        <?php if ($this->statements->get_by('account_id', $account->id)): ?>
            <?= anchor('/statements/' . $account->id, 'View Statements') ?>
        <?php else: ?>
            Statements Not Currently Available
        <?php endif; ?>
    </p>
</div>

This is a rather typical view; it's displaying bits of content from an object, checking for a value's existence and pulling in bits from other database tables. It's fine, but it's all a bit messy, and we're duplicating a fair bit of code. Ideally, we want our view to look something like this:

<div id="account">
    <h1><?= $account->title() ?></h1>

    <p class="information">
        <strong>Name:</strong> <?= $account->name() ?><br />
        <strong>Number:</strong> <?= $account->number() ?><br />
        <strong>Sort Code:</strong> <?= $account->sort_code() ?>
    </p>

    <p class="balances">
        <strong>Total Balance:</strong> <?= $account->total_balance() ?>
        <strong>Available Balance:</strong> <?= $account->available_balance() ?>
    </p>

    <p class="statements"><?= $account->statements_link() ?></p>
</div>

This clears up our view considerably and removes a bunch of the duplication. It also strips out as much logic as possible from the views, and can make for some very succinct code.

We're going to create an application/presenters directory, and inside there an account_presenter.php file. This file will contain the presenter class for our account object. Let's start by extracting the title:

<?php

class Account_Presenter {

    public function __construct($account) {
        $this->account = $account;
        $this->ci =& get_instance();
    }

    public function title() {
        return $this->ci->bank->get($this->account->bank_id)->name . "-" . $account->title;
    }
}

We make sure that we can access the CodeIgniter superobject in $this->ci and the account object that we're presenting in $this->account. We can then port the logic that was previously in the view into a title() method.

We can now go ahead and tidy up the information section:

public function name() {
    return $this->account->name ?: "N/A";
}

public function number() {
    return $this->account->number ?: "N/A";
}

public function sort_code() {
    if ($sc = $this->account->sort_code) {
        return substr($sc, 0, 2) . "-" . substr($sc, 2, 2) . "-" . substr($sc, 4, 2);
    } else {
        return "N/A";
    }
}

Similarly, we can tidy up the balances section:

public function total_balance() {
    return ($this->account->total_balance) ? "&pound;" . number_format($this->account->total_balance) : "N/A";
}

public function available_balance() {
    return ($this->account->available_balance) ? "&pound;" . number_format($this->account->available_balance) : "N/A";
}

And finally, the statements link:

public function statements_link() {
    if ($this->ci->statements->get_by('account_id', $this->account->id)) {
        return anchor('/statements/' . $this->account->id, 'View Statements');
    } else {
        return "Statements Not Currently Available";
    }
}

Fantastic. Finally, in our controller, we need to pass through an instance of the presenter rather than the account object itself.

public function show($account_id) {
    $account = $this->account->get($account_id);
    $this->data['account'] = new Account_Presenter($account);

    $this->load->view('account/show', $this->data);
}

...and don't forget to load the presenter at the top of your controller:

require_once APPPATH . 'presenters/account_presenter.php';

...and we are done!

As I'm sure you can see, using presenters allows you to tidy up your views in a really object-oriented way. It'd be great to hear your thoughts about presenters and whether or not you plan on using them.

Friday
Apr152011

RESTful CodeIgniter Routes

I love Ruby on Rails’ resourceful routing patterns. The ability to map specific HTTP verbs to actions is a beautifully clean way of implementing a common RESTful pattern.

While it would be difficult and counterintuitive to re-implement Rails’ router in PHP, we can use CodeIgniter’s routing system to good effect and get some similar RESTful route patterns.

/* --------------------------------------------------------------
 * PRODUCTS
 * ------------------------------------------------------------ */
$route['products'] = ($_SERVER['REQUEST_METHOD'] == 'GET') ? 'products/get_index' : 'products/post_create';
$route['products/new'] = 'products/get_new';
$route['products/(:any)'] = ($_SERVER['REQUEST_METHOD'] == 'GET') ? 'products/get_show/$1' : 'products/post_update/$1';
$route['products/(:any)/edit'] = 'products/get_edit/$1';
$route['products/(:any)/confirm_delete'] = 'products/post_confirm_delete/$1';
$route['products/(:any)/delete'] = 'products/post_delete/$1';

This will give us the following URL to controller function mappings:

GET /products                   -> get_index
GET /products/new               -> get_new
GET /products/1                 -> get_show(1)
GET /products/1/edit            -> get_edit(1)
POST /products                  -> post_create
POST /products/1                -> post_update(1)
POST /products/1/confirm_delete -> post_confirm_delete(1)
POST /products/1/delete         -> post_delete(1)

The beauty of this is that not only do you get a common URL pattern, but the method names match up with both functionality and HTTP method.

This isn’t entirely RESTful; if we were building a properly RESTful API we’d be using the PUT and DELETE methods instead. When you’re doing something like this, Phil Sturgeon’s REST Controller is your best bet.

For simple RESTful solutions, I absolutely love this reusable snippet of routing code.

Saturday
Apr092011

EllisLab CEO Reports

I’m absolutely thrilled to see that the brilliant Leslie Camacho, former President and newly inaugurated CEO of EllisLab, is taking yet another step forward to get in touch with the community. He has written the first of what will be quarterly reports on the inner goings on at EllisLab.

I have a lot of time for Les, so it has been intriguing to read about his plans for EllisLab and the way he sees the company heading forward.

This quarter he’s discussed the growth of EllisLab - even some figures, 35% growth is impressive! - as well as discussed what he is hoping to do with the company over the coming year. This includes changes and updates to their core set of products, as well as updates to internal services.

I’m guessing ‘internal services’ means the support system and forum, bug tracker, shop and downloads centre. It would also be great to see an update to the product release and update mechanisms; these are at the heart of their products and frankly, decompressing .zip files and moving files is getting archaic.

Needless to say, It’s an interesting read and one I’d be sure you check out if you’ve got anything to do with ExpressionEngine, CodeIgniter or MojoMotor. Stay subscribed to these reports as they’re bound to be informative.

Read the new CEO report over at the EllisLab blog.