EllisLab text mark
Advanced Search
     
Extended Controller class not found - stumped!
Posted: 16 November 2008 03:19 PM
Joined: 2008-10-10
6 posts

I’m developing a billing software (it’s more of an experiment to get familiar with CI) and I was doing so under Windows XP with no problems.

I recently switched to Linux and I started getting a “class not found” error, I thought it might have been because of incorrect filenaming (linux is case sensitive) but after a code review I found no such errors.

So I downloaded CI again and setup a clean install.

Then I proceeded to extend the controller class with only a constructor to keep it simple:

<?php
/* FILE 'application/libraries/my_controller.php' */

class MY_Controller extends Controller
{
    
public function __construct()
    
{
        parent
::__construct();
    
}
}
?> 

Then in the ‘application/controllers/welcome.php’ controller I changed the name of the “Controller” class it extends to my new extended class “MY_Controller”

<?php

class Welcome extends MY_Controller
{
    
public function Welcome()
    
{
        parent
::__construct();    
    
}

    
public function index()
    
{
        $this
->load->view('welcome_message');
    
}
}

/* End of file welcome.php */
/* Location: ./system/application/controllers/welcome.php */ 

Then I run the site and I get

Fatal error: Class ‘MY_Controller’ not found in /home/joseph/public_html/samp/system/application/controllers/welcome.php on line 4

But if I add this to the beginning of the welcome.php file, it will work.

require_once(APPPATH.'libraries/my_controller.php'); 

So CI is not being able to see the extension file. Maybe it’s a path problem since I didn’t have this problem under Windows, but I ran out of ideas.

What am I doing wrong??? I hope you can help me :(

Thank you!

 
Posted: 16 November 2008 04:00 PM   [ # 1 ]   [ Rating: 0 ]
Joined: 2007-09-09
306 posts

A couple of things.

In MY_Controller, I think it should be

parent::Controller(); 

Not

parent::__construct(); 

because the constructor in the CI controller lib is called Controller.

Second, your file should be named “MY_Controller” with a Capital “MY_C”.

Let us know if that fixes it.

 Signature 

UberSignal |
Zenedy | Anyvite | Tweetvite

 
Posted: 16 November 2008 04:10 PM   [ # 2 ]   [ Rating: 0 ]
Joined: 2008-10-10
6 posts

You… Sir… Are… God…

smile

 
Posted: 16 November 2008 04:22 PM   [ # 3 ]   [ Rating: 0 ]
Joined: 2007-09-09
306 posts

Glad to hear it works.

 Signature 

UberSignal |
Zenedy | Anyvite | Tweetvite

 
Posted: 04 August 2009 05:52 PM   [ # 4 ]   [ Rating: 0 ]
Joined: 2008-09-22
12 posts

What if we want to name the extended controller differently?

For example, I like a name: Admin_controller for controllers with restricted session access.

 
Posted: 20 October 2009 05:35 PM   [ # 5 ]   [ Rating: 0 ]
Joined: 2009-10-16
9 posts
dmorin - 16 November 2008 09:00 PM

In MY_Controller, I think it should be

parent::Controller(); 

Not

parent::__construct(); 

because the constructor in the CI controller lib is called Controller.

It shouldn’t matter—__construct() is the “old” PHP way of doing it, but IMHO it’s a better way than ClassName::ClassName(), because it saves work (and potential screw-ups) if you ever have to change a class name.

That one has bitten me on the backside on more than one occasion…

 
Posted: 20 October 2009 05:50 PM   [ # 6 ]   [ Rating: 0 ]
Joined: 2007-09-09
306 posts

I believe it does matter in this case.  “__construct” is not the OLD way, it is the NEW way.  CI uses the OLD way of using the class name for the constructor so it’s supported in PHP4.  Either are acceptable for naming the constructor method.

However, in that example, we aren’t talking about naming the constructor method, we’re talking about calling it from an extending class, in which case, I believe you must use the name of the method in the parent class, not either/or.

Edit:
I stand corrected.  You can call the parent constructor using either method. I didn’t know that.  I still think I’m correct with __construct being the new and preferred way though.

 Signature 

UberSignal |
Zenedy | Anyvite | Tweetvite

 
Posted: 20 October 2009 08:10 PM   [ # 7 ]   [ Rating: 0 ]
Joined: 2009-10-16
9 posts
dmorin - 20 October 2009 09:50 PM

I believe it does matter in this case.  “__construct” is not the OLD way, it is the NEW way.  CI uses the OLD way of using the class name for the constructor so it’s supported in PHP4.  Either are acceptable for naming the constructor method.

Mea culpa. You’re absolutely right…

From http://uk.php.net/__construct:

“For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.”

So I guess you lose compatibility with PHP4 (just trying to see if I care about that….. nope, I don’t think I do), but gain the ease of refactoring. You still have to add a call to the parent constructor though:

“Note:  Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.”

dmorin - 20 October 2009 09:50 PM

Edit:
I stand corrected.  You can call the parent constructor using either method. I didn’t know that.  I still think I’m correct with __construct being the new and preferred way though.

See above.

 
Posted: 21 October 2009 12:45 AM   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2009-06-19
6588 posts

You can name the MY_Controller Class anything you want, but it must be saved in
application/libraries/MY_Controller

Just make sure you save it as MY_Controller…

Example MY_Controller:

class Auth extends Controller {

    
function Auth()
    
{
        parent
::Controller();
    
}
}


// Then extend your new Controller like this:

class Admin extends Auth {

    
function Admin()
    
{
        parent
::Auth();
    
}

Enjoy
InsiteFX

 Signature 

Certified State of CT Computer Programming Teacher.
Custom Designed Icons, eBook Covers Software Boxes. CD, DVD Etc. New iPhone® Tab Bar Icons and iPhone® Applications Icons.

Skype: insitfx

STOP! Before posting your questions, remember the WWW Golden rule:
What did you try? What did you get? What did you expect to get?

Input -> Controller | Processing -> Model | Output -> View

 
Posted: 21 October 2009 09:56 AM   [ # 9 ]   [ Rating: 0 ]
Joined: 2007-09-09
306 posts

Having different file names and class names is a sure way to confuse yourself or anyone else who may have to maintain it down the road.  Is that really better than just including the file at the top, or better yet, adding an autoloaded? The answer to this will be different for everyone, but I wouldn’t mix names; the potential for confusion is just too high.

 Signature 

UberSignal |
Zenedy | Anyvite | Tweetvite

 
Posted: 21 October 2009 10:04 AM   [ # 10 ]   [ Rating: 0 ]
Joined: 2009-10-16
9 posts
dmorin - 21 October 2009 01:56 PM

Having different file names and class names is a sure way to confuse yourself or anyone else who may have to maintain it down the road.  Is that really better than just including the file at the top, or better yet, adding an autoloaded? The answer to this will be different for everyone, but I wouldn’t mix names; the potential for confusion is just too high.

For some reason, autoloads don’t seem to work for user/application libraries (specifically, MY_ class libraries). Maybe I’m doing something wrong, but just adding “MY_FoobarController” to $autoload[‘libraries’] (in /application/config) doesn’t seem to work…

I have moved the ‘application’ directory out of ‘system’, i.e. my directory tree has gone from this:
- system
  - application
      - config
      - controllers
      - ...
- user_guide

to:
- application
  - config
  - controllers
  - ...
- system
  - cache
  - codeigniter
  - database
  - ...
- user_guide

Is it possible that this might be causing issues with class loading? “MY_Controller” seems to load fine from /application/libraries…

 
Posted: 21 October 2009 10:16 AM   [ # 11 ]   [ Rating: 0 ]
Joined: 2007-09-09
306 posts

Sorry, I wasn’t clear.  MY_Controller loads fine because CI looks for any extending classes using the “MY_” (or other configured prefix) before loading the base class.

When I said autoloading, I didn’t mean CI’s autoloading, I meant PHP’s autoloading.  See http://php.net/manual/en/function.spl-autoload-register.php

It’s only available in PHP5 and while there are some downsides, it’s also hugely convenient in certain cases.

 Signature 

UberSignal |
Zenedy | Anyvite | Tweetvite

 
Posted: 24 October 2009 02:02 PM   [ # 12 ]   [ Rating: 0 ]
Avatar
Joined: 2007-06-11
2987 posts

I think philpem & dmorin are argueing at cross purposes here.

dmorin: You are right, I always use __construct when I can instead of Classname but there is a problem. __construct is a method, and if that method is not used when the class is written then you cannot call it. The only way you can use both is if you do the following when writing classes:

<?php
class Something {

   
function __construct()
   
{
      
// do your main construct code
   


   
function Something()
   
{
      $this
->__construct();
   

   
}
?> 

Sadly CodeIgniter doesnt have this so you cannot call __construct with any CodeIgniter code you have not written yourself.

Make sense? grin

Also, instead of writing several classed in one file, I do something like this:

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

// Code here is run before ALL controllers
class MY_Controller extends Controller
{    
    
function MY_Controller()
    
{
        parent
::Controller();
        
                
// shared logic for ALL controllers
        
}
}

include(APPPATH 'libraries/Public_Controller'.EXT);
include(
APPPATH 'libraries/Admin_Controller'.EXT); 

I hope some of that can help you.

 Signature 

————————
Blog | Twitter | GitHub | BitBucket
————————-
PyroCMS - open source modular CMS built with CodeIgniter
PancakeApp - Simple, hosted invoicing/w project management

 
Posted: 24 October 2009 02:46 PM   [ # 13 ]   [ Rating: 0 ]
Joined: 2007-09-09
306 posts

@Phil Sturgeon

Sadly CodeIgniter doesnt have this so you cannot call __construct with any CodeIgniter code you have not written yourself.

That’s what I thought also, but it’s not correct.  parent::__construct doesn’t only call a method named __construct, it calls the constructor regardless of which naming convention it uses.  Try it, I didn’t realize that was the case either until I tried it.

 Signature 

UberSignal |
Zenedy | Anyvite | Tweetvite

 
Posted: 18 March 2011 08:18 AM   [ # 14 ]   [ Rating: 0 ]
Joined: 2011-03-18
1 posts

The information here is stale. MY_Controller class must be saved in Applications Core folder for it to work in CodeIgniter 2.O not in Libraries folder

 
Posted: 03 November 2011 06:13 PM   [ # 15 ]   [ Rating: 0 ]
Joined: 2011-09-15
4 posts
Uber - 18 March 2011 08:18 AM

The information here is stale. MY_Controller class must be saved in Applications Core folder for it to work in CodeIgniter 2.O not in Libraries folder

Thanks for updating this. Was beating my head against the wall!

 Signature 

~B