Skip to content

Instantly share code, notes, and snippets.

@michael-erasmus
Forked from fideloper/ci_style_guide.md
Created May 28, 2014 07:53
Show Gist options
  • Save michael-erasmus/7b72f36edae91b4d1135 to your computer and use it in GitHub Desktop.
Save michael-erasmus/7b72f36edae91b4d1135 to your computer and use it in GitHub Desktop.

CodeIgniter Style Guide

This is collectively being called a style guide, however it serves as a standard to enforce a stricter and more enforced methodology in how programming should be done in CodeIgniter.

Why

CodeIgniter is powerful. CodeIgniter is hugely popular. It's popular because it's easy. It's easy because there are many ways to accomplish a task.

CodeIgniter is terrible for the exact reasons which make it powerful. You can too easily place code in a confusing place, or not separate concerns, thus creating programming challenges down the line. It's noob-friendly, which means it's inherently easy to make noob mistakes.

This document serves to restrict coding practices within CodeIgniter with the purpose of making an application with more class (pun without-a-doubt, most-strongly intended).

Start Here

This style guide is good for spacing, variable names and documentation. These are important, but not the meat of this document.

Contents

  1. Controllers
  2. Models
  3. Libraries
  4. Views
  5. Helpers

1. Controllers

  • Controllers should be skinny.
  • Controller are the only files which should handle requests, including GET, POST and the other HTTP verbs.
  • Controllers should push GET/POST data to models/libraries as needed and have no idea what they do afterwards.
  • Controllers are the only classes which can redirect or decide what a user sees
  • If code is blowing up your controller (ahem Form Validation), wrap it in a model or read the docs on how to get that logic out of a controller.
// Example with flash data and success vs warn, etc
// Example with large If or Case logic (User, Filter Type, Page variables to get results)

2. Models

  • Models in CodeIgniter suck.
    • They tie you to the database, inferring that models are for database calls. This is inaccurate. Models are for anything that's not in a controller - business logic.
    • They don't lend themselves proper separation of concerns. Here's some examples, from least to most separation of concerns.
//Bad
class welcome extends CI_Controller {

    public function posts() {

        $this->load->model('post');
        $userPosts = $this->post->getUserPosts();

        $this->load->view('posts_list', array( 'user_posts' => $userPosts ));

    }

}

class Post extends CI_Model {

    public function getUserPosts() {
        
        $user_id = $this->session->user_data('user_id');

        $posts = $this->db->select()->from('posts')->where('author', $user_id)->get();

        return $posts->result();

    }

}

//Better
class welcome extends CI_Controller {

    public function posts() {

        $this->load->model('post');
        $userPosts = $this->post->getUserPosts($this->session->user_data('user_id'));

        $this->load->view('posts_list', array( 'user_posts' => $userPosts ));

    }

}

class Post extends CI_Model {

    public function getUserPosts($user_id) {

        $posts = $this->db->select()->from('posts')->where('author', $user_id)->get();

        return $posts->result();

    }

}

//Even Better
class welcome extends CI_Controller {

    public function posts() {

        $this->load->model('post');
        $userPosts = $this->post->getUserPosts($this->session->user_data('user_id'));

        $this->load->view('posts_list', array( 'user_posts' => $userPosts ));

    }

}

class Post {

    public function __construct() {

        $this->load->model('orm/posts', 'posts');

    }

    public function getUserPosts($user_id) {

        $posts = $this->posts->get_where( array( 'user_id' => $user_id ) );

        return $posts;

    }

}

class Posts extends CI_Model {

    private $_table = 'posts';

    public function get_where($where) {

        $query = $this->db->select()->from( $this->_table )->where( $where )->get();

        return $query->result();

    }

}

//Still more Better, or perhaps just different
class welcome extends CI_Controller {

    public function posts() {

        $this->load->model('orm/users', 'users');
        $userPosts = $this->users->get( $this->session->user_data('user_id') )->posts();

        $this->load->view('posts_list', array( 'user_posts' => $userPosts ));

    }

}

class Users extends SomeActiveRecordClassWithMagic {

    protected $_table = 'users'; //Table to get results from
    protected $_hasMany = 'posts'; //Table with relationship to user
    protected $_foreignKey = 'user_id'; //FK in posts table

}

  • CodeIgniter calls their database implementation active record, but it isn't.
  • Models don't have to extend CI_Model, and shouldn't in many cases. Models don't mean "database".
  • Models should have business logic, and include other models which communicate with the storage (databases). To do this, use a real Active Record implementation
<?php
//application/models/user
class User {
    
    public function __construct() {
        $this->CI =& get_instance();

        //Notice this is getting Users.php from /application/models/orm
        $this->users = $this->CI->load->model('orm/users', 'users');
    }

    public function getUserPosts($user_id) {
        /*
        * This implenentation is hard in CI, because it wants so badly for you to return
        * a result object instead of a chain-able $this.
        * There is no real Active Record implementation. It's dumbed down.
        * @link http://en.wikipedia.org/wiki/Active_record_pattern#PHP
        */
        $user = $this->users->get($user_id)->posts();

        

    }

}

3. Libraries

  • Ideally do not know about the CI global object
  • Ideally wrap third_party APIs or external data-sources
  • Are not models, but easily can be confused due to need of mixing in concerns (CI, database, configuration files)
  • Are hard in CI because they don't have an autoloading mechanism when more than one file/class is necessary.
  • Sparks is the way to go. Get separate "module" - library, config, model and helpers directories. See how.

4. Views

  • No logic in views.
  • Minimize need for flow logic
  • Loops are great
  • Template library - Don't need, but if you can't get away with just using it, there might be too much logic in your views
  • Use helpers for logic such as date formatting, text formatting, etc. Not to augment your models.
  • Use layouts instead of nesting $this->load->view() calls

5. Helpers

  • If you need database / CI object in helpers, you're doing it wrong
  • Normally used inside of Views
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment