I have this error controller in my Codeigniter 2.1.0 application:
<?php
class Error extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
set_status_header(404);
$data->menuItems = Main::_menu();
$data->title = "404 error !";
$data->pageview = 'templates/404';
$this->load->view('templates/main', $data);
}
public function facebook()
{
set_status_header(404);
$data->menuItems = Main::_menu();
$data->title = "Facebook error !";
$data->pageview = "templates/facebook_error";
$this->load->view('templates/main', $data);
}
}
?>
The Maincontroller _menu:
<?php
class Main extends CI_Controller
{
// ... a lot of methods here ...
public static function _menu()
{
static $menuItems = array( //just a simple array
);
}
}
?>
facebook() method is totally the same as the index(), however index works fine, facebook() throw this message:
Fatal error: Class 'Main' not found in /var/www/MYApplicationName/application/controllers/error.php on line 22
How the earth is that possible ? How can I reach Main::_menu()
from facebook() method ?
A static method can call only other static methods; it cannot call a non-static method.
The only way to access a non-static variable from a static method is by creating an object of the class the variable belongs. This confusion is the main reason why you see this question on core Java interview as well as on core Java certifications e.g. OCAJP and OCPJP exam.
Address the non-static variable with the object name. In a simple way, we have to create an object of the class to refer to a non-static variable from a static context. You also need to use @isTest to denote a unit test method. @testSetup is only for creating test data (if necessary).
You can't call a non static or instance method from a static method because it wouldn't know which instance or object to operate on.
Calling functions from another controller breaks MVC and puts you in the HMVC realm.
Please take a look at this thread, and also CodeIgniter's Modular Extensions (HMVC) Plugin if you really need to do this.
Why don't you create MY_Controller which extends the CI_Controller where you put your reusable code?
Actually - you are mistaken. Your "index" code does not work either.
I just pasted all your code above into a clean version of CI 2.1.2 and the index function ALSO returns the same error.
So perhaps your computer has something cached, or you have some other code elsewhere that is making you think it is working. But it does not work.
Anyway - the real question is why are you trying to call a controller from another controller? That is not a good MVC approach. Your "_menu()" function should be located in a library - that is where it belongs.
Or put the _menu() code into "MY_Controller" and have both controllers extend MY_Controller.
Or put the _menu() code into a helper.
Basically there are three better ways you could approach this.
Based on @TheShiftExchange's answer, I was able to track down that a route setting caused this behaviour. My config/routes.php
looks like this:
$route['404_override'] = 'error/index';
$route['(:any)'] = "main/$1";
So, when I made a request to www.example.com/nonexistent-url
this get served by the main
controller, then CI noticed that there is no method like this so it ran error/index
too, but the main
controller was already loaded by then.
The other method facebook
was redirected from an existing method of main
only, for example gallery
, this way it is like if I went to the url www.example.com/error/facebook
, so the main
controller is not loaded, because only error/facebook
is requested. If I call www.example.com/error/index
it works the same, because in this case the main
controller is not loaded, only the error
.
(The bounty goes to @TheShiftExchange, because his answer was the most accurate and provided me the best information to able track down the problem. Thanks !
One of my redirect was never reached, which I tought was calling the error/index page.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With