Codeigniter 3 (HMVC) - 404 on route even though controller exists - MX_Controller issue?

Hi I’m facing an issue during a technical challenge for a PHP internship using PHP 8.1 and CodeIgniter 3 (with HMVC structure using MX_Controller).

The company sent me the repository already set up — my only task is to add a login feature. However, when trying to access the login route http://localhost:8000/login or http://localhost:8000/index.php/login, it just loads the error page error_404.php. I keep getting the following error application->logs->log-2025-04-16.php:

ERROR - 2025-04-16 12:51:42 --> 404 Page Not Found:
../modules/acesso/controllers/Login/index

Even though the folder structure and files seem to be correct.

File Structure:

application/modules
├── acesso
│   ├── controllers
│   │   └── Login.php
│   ├── index.html
│   ├── models
│   │   └── Login_model.php
│   ├── README.md
│   └── views
│       └── login_view.php
├── framework
│   └── views
│       └── errors
│           └── cli
│               ├── error_404.php
│               └── ...
├── test
│   ├── controllers
│   │   └── Test.php
│   └── views
│       └── test.php
└── welcome
    ├── controllers
    │   └── Welcome.php
    └── views
        └── welcome_message.php

Login.php:

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

class Login extends MX_Controller {
    public function index() {
        echo 'Página de login';
    }
}

application/config/routes.php:

$route['login'] = 'acesso/login/index';
$route['default_controller'] = 'acesso/login';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;

Relevant .htaccess:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>

<IfModule !mod_rewrite.c>
    ErrorDocument 404 /index.php
</IfModule>

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin: "*"
</IfModule>

I’ve been trying to solve this for 3 days and since it’s a repository that was already set up I think it should be working. I’m almost set to start at another company, but I’d really like to figure this out — it’s a question of honor at this point.

From what I can tell, the structure is correct. The Login.php file exists, with the Login class extending MX_Controller and having the index() method.

I’ve checked the routing config, capitalization of filenames, .htaccess rules, mod_rewrite… everything seems right. Still, CodeIgniter returns a 404 when trying to access the login route.

Has anyone faced this kind of issue before or knows what might be missing? Any help would be greatly appreciated

You’re absolutely right to expect this should work — and based on everything you shared, your structure and code look mostly correct. But in CodeIgniter 3 with HMVC (using MX_Controller), there are a few common pitfalls that can cause 404 Page Not Found errors even when the controller exists.


Step-by-Step Debug Checklist

Let’s go through everything that could be wrong and help you resolve it once and for all.


1. Check Class and File Name Capitalization

CodeIgniter 3 is case-sensitive on Linux/macOS systems (and Docker), so:

  • Login.php must be exactly Login.php
  • Inside: class Login extends MX_Controller

If your file is called login.php (lowercase) on disk, it will 404.

Fix: Ensure exact match:

  • /modules/acesso/controllers/Login.php
  • Inside that file: class Login extends MX_Controller

2. Double-check Module Location

CodeIgniter must be able to find your HMVC module. Confirm:

application/modules/acesso/controllers/Login.php

If the folder is /application/modules/Acesso/ (with capital A), but you’re referencing 'acesso/login/index' in your route, it will fail.

Fix: Rename folder to lowercase:

mv application/modules/Acesso application/modules/acesso

3. Controller Class Must Extend MX_Controller

You already seem to be doing this, but triple-check the class header:

defined('BASEPATH') OR exit('No direct script access allowed');

class Login extends MX_Controller {
    public function index() {
        echo 'Página de login';
    }
}

Also make sure MX_Controller is loaded (see #5).


4. Autoload HMVC Modules (Optional but Recommended)

In application/config/config.php, ensure modules are loaded:

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

You can also try:

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

5. MX_Controller Must Be Loaded (Via HMVC Library)

If MX_Controller isn’t found, your class will silently fail to register, and CodeIgniter returns a 404.

Confirm you have this file:

application/third_party/MX/Controller.php

And that your MY_Controller.php isn’t interfering.


6. Routing Config — Confirm Routes Are Registered Properly

You’re using:

$route['login'] = 'acesso/login/index';
$route['default_controller'] = 'acesso/login';

That’s correct, assuming acesso is the exact name of the module folder. Try simplifying further by visiting:

If that works, it means routing alias login isn’t resolving properly.


7. Test Without Pretty URLs (Disable .htaccess Rewriting)

Temporarily bypass .htaccess:

Try:

http://localhost:8000/index.php/acesso/login/index

If this works but /login does not, your rewrite rules are not being applied. That means:

Check if mod_rewrite is really enabled:

apache2ctl -M | grep rewrite
# Or: sudo a2enmod rewrite && sudo service apache2 restart

8. Check Apache/Nginx Virtual Host Configuration (Docker or Native)

If you’re using php -S, Apache, or Docker, ensure:

  • Document root is pointing to public folder (if used)
  • .htaccess is being respected

Try adding a line inside .htaccess:

RewriteRule ^testrewrite$ testrewrite.php [L]

Then navigate to /testrewrite — if this fails, .htaccess is not active.


9. Turn on CI Debug Mode and Logging

In application/config/config.php, set:

$config['log_threshold'] = 4;
$config['log_path'] = '';
$config['log_file_extension'] = '';

Then tail the logs:

tail -f application/logs/log-2025-04-16.php

10. Enable Error Reporting Fully

In index.php:

error_reporting(E_ALL);
ini_set('display_errors', 1);

This might reveal subtle file/class loading issues that aren’t visible otherwise.


Final Test

Once you’ve checked all the above, try:

php spark serve

Or:

php -S localhost:8000 -t .

Summary of Common Fixes

Problem Fix
Wrong casing in folder/file names Rename files/folders to match exactly
MX_Controller not loaded Ensure application/third_party/MX/Controller.php exists
Wrong routing path Try /index.php/acesso/login/index directly
.htaccess not applied Verify mod_rewrite is enabled
Route misconfigured Simplify to base controller route and test again