Kevin Phillips » Codeigniter http://kevinphillips.co.nz Who is dollar dad? Sat, 24 Sep 2011 20:48:47 +0000 en hourly 1 http://wordpress.org/?v=3.2.1 Codeigniter Drivers Tutorial http://kevinphillips.co.nz/news/codeigniter-drivers-tutorial/ http://kevinphillips.co.nz/news/codeigniter-drivers-tutorial/#comments Fri, 02 Sep 2011 11:07:12 +0000 kevin http://localhost/?p=91 Continue reading ]]> Codeigniter 2 has just keeps getting better. I’ve been having a play around with the new “Drivers” library that comes with Codeigniter 2 and it really has impressed me so much that I’ve started converting all my libraries into “Drivers”.

Ok what are Drivers

Drivers are a special type of Library that has a parent class and any number of potential child classes. Child classes have access to the parent class, but not their siblings. Drivers provide an elegant syntax in your controllers for libraries that benefit from or require being broken down into discrete classes.

Drivers are found in the system/libraries folder, in their own folder which is identically named to the parent library class. Also inside that folder is a subfolder named drivers, which contains all of the possible child class files.

 

In Basic English they are a collection of PHP Classes under one directory which aware of each other.

So lets build a driver called Honey.

Note the convention of using Capitals.

Create a folder called Honey

..application/libraries/Honey

Add your master class

..application/libraries/Honey/Honey.php

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

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
    }

}

You’ll notice that this master class extends CI_Driver_Library.

you must have the variable $valid_drivers. This tells Codigniter which sub-classes to load. We don’t have any at the moment but we’ll be building them later.

We’ve made our $CI variable an instance of the codeigniter object by reference.  Anything you make public or protected in this master class will be available to all the sub-classes.

One of the great things about using the Driver Library is you can build all you logic here but use either a database or config file to get variable data which makes this such a sweet drop in application.

so for this example I’m going to use a config file for this application’s setting.

..application/config/honey.php

<?php

$config['modules'] = array('honey_queenbee', 'honey_workerbee');

 

I’ve called them modules but you can call them anything you like. Lets initialise them.

..application/libraries/Honey/Honey.php

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

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

}

 

Firstly we’re using codeigniter to load our config file – see the user guide for details. I’m using the TRUE param so as to avoid name collision.

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

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

}

You don’t have to use a config file, you could just as easily use a database or hardcode into the class (although hard coding into the class makes it hard to port from one app to another). This needs to be an array.

Now for the two sub-classes. You must create a new folder called drivers. Note the naming convention.

..application/libraries/Honey/drivers

..application/libraries/Honey/drivers/Honey_queenbee.php

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

class Honey_queenbee extends CI_Driver {

    function pardon()

    {

        return 'You are forgiven';

    }

}

Note that this sub-class extends CI_Driver NOT CI_Driver_Library.

I’ve created an example function here that just returns a string but you can easily now run a db query using the $this->CI.

..application/libraries/Honey/drivers/Honey_workerbee.php

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

class Honey_workerbee extends CI_Driver {

    function busybee()

    {

        return $this->_pot_honey();

    }

    function _pot_honey()

    {

        return 'Here is a pot of honey';

    }

}

The Honey_workerbee class has two function, just for example sake.

Here is our controller

..application/controller/site.php

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

class Site extends CI_Controller {

    private $data = array();

    function __construct()
    {

        parent::__construct();

    }

    function call_honey()

    {

        $this->load->driver('honey');

        print $this->honey->queenbee('pardon');

    }

}

I’m only printing to the screen for demo purposes;

You can see that we are calling a method directly from a sub-class

But it would be much better to use our master class to control these calls as it has access to all the sub classes.

..application/controller/site.php

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

class Site extends CI_Controller {

    private $data = array();

    function __construct()
    {

        parent::__construct();

    }

    function call_honey()

    {

        $this->load->driver('honey');

        print $this->honey->naughty_bee();

    }

}

..application/libraries/Honey/Honey.php

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

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

    function naughty_bee()
    {
        return $this->queenbee->pardon();
    }
}

We’ve added a new method in the master class that calls the queenbee for a pardon.

Master Class can talk to all of the sub-classes. Sub-classes can talk to the master class. Sub classes cannot talk to each other. They must go through the master class.

..application/controller/site.php

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

class Site extends CI_Controller {

    private $data = array();

    function __construct()
    {

        parent::__construct();

    }

    function naughty()

    {

        $this->load->driver('honey');

        print $this->honey->naughty_bee();

    }

    function get_honey()
    {

        $this->load->driver('honey');
        $money = 10;
        if($this->honey->buy_honey($money)
        {
            print "eat the honey";
        }
        else
        {
            print "I do not have enough money";
        }
}

..application/libraries/Honey/Honey.php

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

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

    function naughty_bee()
    {
        return $this->queenbee->pardon();
    }

    function buy_honey($money = 0)
    {
        if($this->workerbee->busybee($money))
        {
            return TRUE;
        }
    }
}

A call to the master class which then calls the sub class

..application/libraries/Honey/drivers/Honey_workerbee.php

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

class Honey_workerbee extends CI_Driver {

    function busybee($money)

    {
 if($this->check_money($money)
 { return $this->_pot_honey();
 }

    }

    function _pot_honey()

    {

        return 'Here is a pot of honey';

    }

}

The worker bee can only sell the honey if the money is right.  The queen bee needs to check the money but we can’t go directly to the queen bee we must go through the master controller.

A little over the top I know but is shows what we can do.

 

..application/libraries/Honey/Honey.php

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

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

    function naughty_bee()
    {
        return $this->queenbee->pardon();
    }

    function buy_honey($money = 0)
    {
        if($this->workerbee->busybee($money))
        {
            return TRUE;
        }
    }

    function check_money($money)
    {
        return $this->queenbee->can_we_sell($money);
    }
}

 

..application/libraries/Honey/drivers/Honey_queenbee.php

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

class Honey_queenbee extends CI_Driver {

    function pardon()

    {

        return 'You are forgiven';

    }

    function can_we_sell($money)

    {

        if($money > 5)

        {

            return TRUE;

        }

    }
}

This should now return TRUE back to the controller.

The value is hard coded which is not good.  Lets improve that by adding the value to the config file.

..application/libraries/Honey/drivers/Honey_queenbee.php

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

class Honey_queenbee extends CI_Driver {

    function pardon()

    {

        return 'You are forgiven';

    }

    function can_we_sell($money)

    {

        if($money > $this->config->item('honey_pot_value', 'honey');

        {

            return TRUE;

        }

    }
}

..application/config/honey.php

<?php

$config['modules'] = array('honey_queenbee', 'honey_workerbee');
$config['honey_pot_value'] = 5;

 

 

A very simple example but you can see how we can make very useful apps that can easily be dropped into new projects.

]]>
http://kevinphillips.co.nz/news/codeigniter-drivers-tutorial/feed/ 1
Codeigniter Views http://kevinphillips.co.nz/news/codeigniter-views/ http://kevinphillips.co.nz/news/codeigniter-views/#comments Sat, 27 Aug 2011 11:05:13 +0000 kevin http://localhost/?p=89 Continue reading ]]> Great news about the very latest versions of Codeigniter 2.

As of today’s date the latest version on github has a new feature which allows you to move the views folder outside of the application folder.

The setting is inside the main index.php.

This means, at least to me I don’t have to give permissions to anyone else to access the application folder (i.e. the designers !!!)

Here’s my new structure layout.

webroot/

            application/

            public/

                     index.php

                     .htaccess

                     css/

                     js/

                     images/

             system/

             views/

                      template.php
]]>
http://kevinphillips.co.nz/news/codeigniter-views/feed/ 0
Access Control Levels http://kevinphillips.co.nz/news/access-control-levels/ http://kevinphillips.co.nz/news/access-control-levels/#comments Sat, 27 Aug 2011 11:02:30 +0000 kevin http://localhost/?p=86 Continue reading ]]> One of the things missing from codeigniter is access control levels ACL or access control libraries as some might say. Drupal has an excellent ACL out of the box so I decided to make one for regular use on Codeigniter.

Now I want to make sure that this ACL can be used either through roles or individual basis. Groups for me is a collection container of people that are linked together. Individuals still have a role within their group(s) which is why I think it’s important to set access against individual members. However you can still use roles as a way to set individual’s permissions.

The key is to seperate the login functionality from the access function. This allows the ability of the programmer to decide how to setup the permissions.

Each content type has a set of access rules. Each user has a set of permissions. How the user gets the permissions is down to you as long as they’re stored in the users session in the correct format.

$data = array(
is_logged_in => true/false,
uid => true/false,
is_admin => true/false,
permissions = array(
‘content type or group’ => array(
‘add’ => true/false,
‘view own’ => true/false,
‘view all’ => true/false,
‘update all’ => true/false,
‘update own’ => true/false,
‘delete own’ => true/false,
‘delete all’ => true/false,
),
);

$this->session->set_userdata($data);

Personally I would save the permissions as a serialized array in a field in the users table called permissions.

Setting it is easy. Once you’ve checked the user login just add it to the session array.

$query = $this->db->select('uid, is_admin, permissions 'whatever else....')
      ->where->('username', $this->input->post('username'))
      ->where('password', whateverhash($this->input->post('password'))
      ->get('users');

if($query->num_rows()== 1) {

   $rs = $query->row();

   $data['is_logged_in'] = TRUE;

   $data['uid'] = $row->uid;

   $data['is_admin'] = $row->is_admin;

   $data['permissions'] = unserialize($row->permissions);

   $this->session->set_userdata[$data];

}

The controller method needs this. The uid is only needed for individual content entries

function edit_post($post_id = null)  {
    $this->load->library('acl');
// You MUST VALIDATE user input easy if it's an id number just use is_numeric();
 $access = $this->acl->check_permission(array('name' => 'post', 'action' => 'update', 'uid' => $post_id); 

    if(!$access) {

        //kick them out or what ever

    }

}

 

]]>
http://kevinphillips.co.nz/news/access-control-levels/feed/ 0
Better password hashing for Codeigniter http://kevinphillips.co.nz/news/better-password-hashing-codeigniteriter/ http://kevinphillips.co.nz/news/better-password-hashing-codeigniteriter/#comments Fri, 19 Aug 2011 11:00:01 +0000 kevin http://localhost/?p=83 Continue reading ]]> I’ve been looking for a more secure way to encrypt (well hash because it’s one way) passwords.

This is my adaptation of Openwall‘s phpass. What I’ve done is stripped out all the backward php compatible code to make this a super slim files.

Note that this will only work on php 5.3+

in application/library create a new file auth.php

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

class Auth {

    public function hash($password, $work_factor = 6) {
        if (version_compare(PHP_VERSION, '5.3') < 0) {
            throw new Exception('Auth Library requires PHP 5.3 or above');
        }
        return crypt($password, self::generate_blowfish_salt($work_factor));
    }

    public function check($password, $stored_hash) {
        if (version_compare(PHP_VERSION, '5.3') < 0) {
            throw new Exception('Auth Library requires PHP 5.3 or above');
        }

        return crypt($password, $stored_hash) == $stored_hash;
    }

    private function generate_blowfish_salt($work_factor) {

        $random = openssl_random_pseudo_bytes(16);

        $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

        $output =  '$2a$';
        $output .= chr(ord('0') + $work_factor / 10);
        $output .= chr(ord('0') + $work_factor % 10);
        $output .= '$';

        $i = 0;
        do {
            $c1 = ord($random[$i++]);
            $output .= $itoa64[$c1 >> 2];
            $c1 = ($c1 & 0x03) << 4;
            if ($i >= 16) {
                $output .= $itoa64[$c1];
                break;
            }

            $c2 = ord($random[$i++]);
            $c1 |= $c2 >> 4;
            $output .= $itoa64[$c1];
            $c1 = ($c2 & 0x0f) << 2;

            $c2 = ord($random[$i++]);
            $c1 |= $c2 >> 6;
            $output .= $itoa64[$c1];
            $output .= $itoa64[$c2 & 0x3f];
        } while (1);

        return $output;
    }

}

You can now call this library just like any other library in codeigniter from your controller.

$this->load->library('auth');

function login() {

  $this->load->library('form_validation');

  $this->form_validation->set_rules('username', 'Username', 'required|min_length[4]|max_length[20]|xss_clean');

  $this->form_validation->set_rules('password', 'Password', 'required|min_length[4]|max_length[20]|strip_tags');

  if($this->form_validation->run() == FALSE) {

    $this->login_form();

  } else {

    // Just for the purpose of this demo I'm running the database call here but normally I would run this in a model

    $result = $this->db->select('password')->get_where('users', array('username' => $this->input->post('username'))->row();

    // Now call the check function from the Auth Library

    if($has_passed = $this->auth->check($this->input->post('password'), $result->password)) {

      //Do your stuff here for authenticated users like sessions

    } else {

      $this->session->set_flashdata('error_message', 'Incorrect username or password');

      redirect('/ "to the login page"); // Use redirect so you flash message will show

}

If you want to know why I’ve used strip_tags on the password not xss_clean read this.

]]>
http://kevinphillips.co.nz/news/better-password-hashing-codeigniteriter/feed/ 0
Ion Auth Multigroups http://kevinphillips.co.nz/news/ion-auth-multigroups/ http://kevinphillips.co.nz/news/ion-auth-multigroups/#comments Thu, 18 Aug 2011 10:54:59 +0000 kevin http://localhost/?p=78 Continue reading ]]> The more I use codeigniter the better I like it – I’ve already changed some sites from Drupal to CI.

Anyway a small problem, that I’ve mentioned in the forum

http://codeigniter.com/forums/viewthread/145263/P1030/

Using Ion 2

Small problem, first the function $this->ion_auth->is_group($group) should be in_group().
I think I remember seeing this elsewhere. However a problem exists if you pass an array of groups.

Currently is_group returns in_array($check_group, $groups) which won’t work if check_group is an array.

Solution:
application/libraries/Icon_auth.php

Add condition to check if $check_groups is an array and if it is then walk through the array checking for a match.

public function in_group($check_group) {
$this->ci->ion_auth_model->trigger_events('is_group');
$users_groups = $this->ci->ion_auth_model->get_users_groups();
$groups = array(); foreach ($users_groups as $group) {
 $groups[] = $group->name;
}
 $permission = false;
if(is_array($check_group)) {
foreach($check_group $key => $value){
 if(in_array($value, $groups)) {
  $permission = true;
 }
 }
 } else { 
if(in_array($check_group, $groups)) {
$permission = true;
}
}
return $permission;
}   

 

]]>
http://kevinphillips.co.nz/news/ion-auth-multigroups/feed/ 0
jQuery axaj for Codeigniter 2 http://kevinphillips.co.nz/news/jquery-axaj-for-codeigniter-2/ http://kevinphillips.co.nz/news/jquery-axaj-for-codeigniter-2/#comments Sun, 31 Jul 2011 10:51:52 +0000 kevin http://localhost/?p=76 Continue reading ]]> A simple AJAX tutorial for use with Codeigniter 2 with CSRF enabled.

The original tutorial was taken from Andrew Rowland’s website but I’ve updated it so that it works with Codeigniter 2 with csrf enabled.

I’m using Codeigniter 2.02, jQuery 1.6.2 and jQuery.cookie.js

Everything else is a normal install.

This simple demo app will show you how to create an AJAX request to add an unordered list to an list item, with fallback if javascript has been disabled.

Create a controller called world.php.  Also autoload (or mannually)

$autoload['helper'] = array('url', 'html');

in the config/autoload.php

and set the csrf to TRUE in the config/config.php

$config['csrf_protection'] = TRUE;

also (which I always do) set the encryption key. You can get auto generated keys from http://randomkeygen.com/

$config['encryption_key'] = 'c83d2mQ2N43P11BoyziaJY5o99gWi7Xo';
Naturally this data would be stored in a database but to keep it simple I'm using hard coded arrays
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class World extends CI_Controller {

    private $data = array();

    function __construct() {
        parent::__construct();
    }

    function index($continent = null) {

        $this->data['continents'] = array(
            1 => 'Europe',
            2 => 'Africa',
            3 => 'North America',
            4 => 'The moon',
        );
        if(isset($continent)) {
            $this->data['countries'] = $this->list_countries($continent);
        }
        $this->load->view('template',$this->data);
    }

    function list_countries($continent) {
        $continents = array(
            1 => array('UK', 'France', 'Spain', 'Germany'),
            2 => array('South Africa', 'Zimbabwe', 'Cameroon'),
            3 => array('USA', 'Canada'),
            4 => array(),
        );

        if(isset($_POST['ajax'])) {
            echo json_encode($continents[$continent]);
        } else {
            return $continents[$continent];
        }
    }

}

Next create the html page template.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>World</title>
</head>
<body>
<?php print heading('The World Goes Here',1) ?>
<ul id="continents">
    <?php foreach($continents as $id => $continent) : ?>
        <li id="id_<?php print $id?>"><a href="/world/index/<?php print $id ?>" title="<?php print $continent ?>"><?php print $continent ?></a></li>
        <?php if($id == $this->uri->segment(3)) : ?>
            <?php print ul($countries); ?>
        <?php endif; ?>
    <?php endforeach; ?>
</ul>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js" ></script>
    <script src="/js/jquery.cookie.js" ></script>
    <script src="/js/main.js" ></script>
</body>
</html>

You’ll notice that I’m using the helper url and html. I just love them and they can save so much time particularly if you’re getting arrays back from the database.

Now for the js

 

$(function() {

    $('#continents li').click(function(){
        This splits out the id number from the id
        var cont_id = this.id.split('_');
        Important - This gets the cookie value which is passed through to the controller.
        Codeigniter 2 checks this value automatically so you don't need to do anything else
        var cct = $.cookie('ci_csrf_token') ? $.cookie('ci_csrf_token') : null;
        Simple fall back to a normal page reload if the user has cookies switched off, otherwise the page will not display the countries and you'll get a 500 error
        if(!cct) {
            return true;
        }

        $('#continents > ul').slideUp('slow');
        if($('#id_' + cont_id[1]).children('ul').length == 0) {
            $.post('/world/list_countries/' + cont_id[1],
                {ajax:'true', 'ci_csrf_token':cct},
                function(data) {
                    unorderedlist = $('<ul/>').css({display : 'none'});
                    $.each(data, function(i, country){
                        $('<li/>').text(country).appendTo(unorderedlist);
                    });
                    unorderedlist.appendTo('#id_'+cont_id[1]);
                    unorderedlist.slideDown('slow');
                }, 'json');
        } else {
            if($('#id_' + cont_id[1]).children('ul').length > 0) {
                $('#id_' + cont_id[1] + ' ul').slideDown('slow');
            }
        }
        return false;
    });
});

 

]]>
http://kevinphillips.co.nz/news/jquery-axaj-for-codeigniter-2/feed/ 0
Codeigniter XSS http://kevinphillips.co.nz/news/codeigniter-xss/ http://kevinphillips.co.nz/news/codeigniter-xss/#comments Thu, 21 Jul 2011 10:50:32 +0000 kevin http://localhost/?p=72 Continue reading ]]> Codeigniter adds semi-colon when you use an ampersand in an input field

When a user had an ampersand character in their password they couldn’t login to the website. This took me several hours to figure out what was happening.

Using codeigniter 2.02 on php 5.3.

In the config file you have the option of turning XSS Filtering on site wide, which on the outset looks like a good idea. However it has some side effects that can cause a few problems.

application/config/config.php

$config['global_xss_filtering'] = TRUE;

I’ve been implementing a new login system which uses

$username = htmlspecialchars($this->input->post('username'));

$password = hash('sha512', $salt . $this->input->post('password') . $pepper);

Now here comes the problem.

The input form goes through the form_validation->run() to check that the fields are not empty or too long etc

but if the password contains the ampersand such as

Tyu9&fgQnb

then the output becomes

Tyu9&fgQnb;

(note the semi-colon)

I for one want to encourage my users to have strong passwords.

The answer is of course not to have XSS on site wide.

$config['global_xss_filtering'] = FALSE;

and add xss_clean on a individual basis in the validation rules. It’s probably important to add that I normally add strip_tags to these input types.

$this->form_validation->set_rules('username', 'Username', 'required|strip_tags|max_length[20]');

$this->form_validation->set_rules('password', 'Password', 'required|strip_tags|max_length[20]');

 

 

]]>
http://kevinphillips.co.nz/news/codeigniter-xss/feed/ 0
Codeigniter Multiple Sites with HMVC and Packages http://kevinphillips.co.nz/news/codeigniter-multiple-sites-hmvc-and-packages/ http://kevinphillips.co.nz/news/codeigniter-multiple-sites-hmvc-and-packages/#comments Sat, 11 Jun 2011 10:24:02 +0000 kevin http://localhost/?p=58 Continue reading ]]> Building multiple websites with a single Codeigniter base using HMVC and Packages that share the same custom libraries across all sites.

I thought I’d document this as I haven’t been able to find this solution in any one single blog.

I’ve a number of clients that have similar website functions but different layouts but maintaining modules/classes/libraries etc with bug-fixes and new functions, across all these sites is a nightmare. I could use some form of version control but it still means going into each site to update them. What I wanted was a single point for all my custom classes. libraries, js scripts and layout css files.

So this is my solution:

PHP 5.2

Codeigniter 2.02

Wiredesignz’s Modular Extensions – HMVC (as of 11th June 2011).  Download here and the install instructions here.

Here is the file structure (with notes):

wwwroot/

system/  (standard system folder with no changes – Golden Rule “NEVER HACK CORE” )

              custom/  (modules, libraries and classes that will be shared across all websites)

libraries/  (shared libraries and third party stuff like tinymce)

modules/ (HMVC modules shared across all websites, like login, register etc)

models/ (models that don’t belong to HMVC)

views/ (views that don’t belong to modules)

js/

css/

website01/

.htaccess (see here for details on this file)

index.php (main index)

application/  (standard application folder)

/cache

/config

/controllers

/core

/errors

/helpers

/hooks

/language

/libraries

/logs

/models

/modules

/third_party

/views

assets/ (Just a place to store psd and things)

uploads/ (clients’ uploads)

js/ (site specific js)

css/

images/

 

With the file structure out of the way, which of course you can have your own setup, lets begin.

We’re going to need some constants across all sites so in the webroot/custom directory create a file called custom_config.php. add the following code.

<?php
define('CUSTOM_PATH', dirname(__FILE__));

 

At the top of the webroot/website01/index.php (replace website01 for your website name)

Just below the opening php tag

<?php
include('../custom/custom_config.php');

 

You can test this by adding

<?php
include('../custom/custom_config.php');
print CUSTOM_PATH;

Don’t forget to remove it !!!

You will also need to change the path of the system folder inside this index.php file

$system_path = 'system';

to

$system_path = '../system';

 

Assuming you followed Wiredesignz‘s installation guide you should now have your welcome controller welcome.php inside /webroot/website01/application/modules/welcome/controllers/

Make these changes

class Welcome extends CI_Controller {

to

class Welcome extends MX_Controller {

    function __construct() {
        parent::__construct();
        $this->load->add_package_path(CUSTOM_PATH . '/');
    }

 

OK lets make a separate module that we can share

in the webroot/custom/modules/ create a new “Triad”

I’m just going to call mine dog for fun

webroot/custom/modules/dog/

controllers/

models/

views/

create a file called dog.php in webroot/custom/modules/dog/controllers/

ad add the following code.

<?php

class Dog extends MX_Controller {

    function __construct() {
        parent::__construct();
    }

    function index() {
        print 'Hello I am a dog';
    }

}

 

OK if you navigate to the url /dog you well get an error.  HMVC doesn’t know about the custom folder so we need to add this information in

webroot/website01/application/config/config.php

at the top of the file add this code

<?php

config['modules_locations'] = array(   APPPATH.'modules/' => '../modules/',
  CUSTOM_PATH .'/modules/'  => '../../../custom/modules/'
);

And providing you have the same directory setup as me then go back to your browser and voila you should now see the contents of the dog controller.

A Multiple website, single core Codeigniter with packages that allow you to share apps across all sites.

Happy programming

]]>
http://kevinphillips.co.nz/news/codeigniter-multiple-sites-hmvc-and-packages/feed/ 1
Codeigniter 2 Pretty URLs http://kevinphillips.co.nz/news/codeigniter-2-pretty-urls/ http://kevinphillips.co.nz/news/codeigniter-2-pretty-urls/#comments Fri, 10 Jun 2011 10:14:02 +0000 kevin http://localhost/?p=55 Continue reading ]]> To change Codigniters default setting for urls which current shows http://www.domain.com/index.php to pretty urls like http://www.domain.co.nz/page/contact you need to do two things.

Firstly in the application/config/config.php on line 33 change

$config['index_page'] = 'index.php';

to

$config['index_page'] = '';

 

And in the same directory as your main index.php file add a new file .htaccess and add this code

RewriteEngine On
RewriteCond $1 !^(index.php|images|captcha|css|js|robots.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

 

]]>
http://kevinphillips.co.nz/news/codeigniter-2-pretty-urls/feed/ 0
Codeigniter String Helper http://kevinphillips.co.nz/news/codeigniter-string-helper/ http://kevinphillips.co.nz/news/codeigniter-string-helper/#comments Sat, 09 Apr 2011 10:08:01 +0000 kevin http://localhost/?p=51 Continue reading ]]> One of the great strengths of Codeigniter is the Helper Libraries and one which I use quite lot is the Text Helper, in particular the word and character limiter function.

Recently whilst working on a project I created a river of news type page, pretty much the same as you would find on Drupal.

However I kept seeing some very strange behaviours, the style would break a different points.

After much head banging and hair pulling I worked out the problem. This was one of those “Can’t see the trees for the wood”.

Some of the text that was being feed into the “River of News” was coming from logged in users that of course had access to the WYSIWYG editor. Here lies the problem the editor was of course inserting <p> tags.  When the codeigniter word limiter function ran and cut off the text at the required length it of course also cut off the ending </p> tag.

Simple I know but it took me hours to debug that.

so here is the correct way

foreach ($posts as $post) {

$string = strip_tags($post->body); //$post being the array from the controller

print word_limiter($string, 50);

}

Happy Coding

]]>
http://kevinphillips.co.nz/news/codeigniter-string-helper/feed/ 0