Extending a CodeIgniter core class means a prefix, not a namespace

Every CodeIgniter 2 project reaches the point where four controllers need the same authentication check. The framework has no container and no interface to implement — the extension point is a file name. A class named with the configured subclass prefix, in application/core/, is loaded in place of the core one.

// application/config/config.php
$config['subclass_prefix'] = 'MY_';

// application/core/MY_Controller.php — found by file name, nothing else
class MY_Controller extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->helper('url');
    }
}

// a second base class goes in the same file: only one is ever loaded
class Admin_Controller extends MY_Controller
{
    public function __construct()
    {
        parent::__construct();

        if (!$this->session->userdata('staff_id')) {
            redirect('login');
        }
    }
}

The loader includes exactly one file per core class, so an intermediate base class has to share the file or be required by hand — which is why so many CodeIgniter projects have a single MY_Controller.php holding three classes and a comment apologising for it. Namespacing any of them breaks the mechanism outright: the framework builds a path from the bare class name and then instantiates that name, so AppHttpMY_Controller is never found. The consequence worth planning around is that a Composer-installed package can never be a controller base class here; it has to be composed into one. Forgetting parent::__construct() is the other recurring bug, and it presents as $this->load being null rather than as anything that names the cause.