I have MY_Controller in core that extends CI_Controller. That works fine. But, I want to create another core controller named MY_Controller_2 for some reasons. Can I do this in codeigniter? If yes then what will be the changes in config file?
config.php
$config['subclass_prefix'] = 'MY_';
Directory Structure
core/MY_Controller
core/MY_Controller_2 <-------- I want another controller too.
MY_Controller
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
}
.....
so, basically, some of the controller files, I want to extend from MY_Controller and some from MY_Controller_2.
By placing this at the bottom of your config.php
function __autoload($class) {
if(strpos($class, 'CI_') !== 0) {
#include_once( APPPATH . 'core/'. $class . EXT );
}
}
This will load all core controllers.
Related
I am trying extending CodeIgniter controller in my application using composer but it's not working.
This give me
Fatal error: Class 'CI_Controller' not found in D:\xampp\htdocs\ci-dev\application\core\MY_Controller.php on line 11
i knew that if i add spl_autoload_register in my config.php then it is work but i want to use composer.
here is my all set up.
i create MY_Controller in my application/core/MY_Controller.php
class MY_Controller extends CI_Controller
{
public $data = array();
public function __construct()
{
parent::__construct();
}
}
after this i add admin controller in application/libraries/Admin_Controller.php
class Admin_Controller extends MY_Controller
{
public function __construct()
{
parent::__construct();
}
}
and front-end controller in application/libraries/Frontend_Controller.php
class Frontend_Controller extends MY_Controller
{
public function __construct()
{
parent::__construct();
}
}
This is my default controller index call
class Welcome extends Frontend_Controller {
public function index()
{
$this->load->view('welcome_message');
}
}
i set up my composer like this in config.php
$config['composer_autoload'] = FCPATH.'../vendor/autoload.php';
and composer.json file like this
"autoload": {
"files" : [
"application/core/MY_Controller.php",
"application/libraries/Admin_Controller.php",
"application/libraries/Frontend_Controller.php"
]
},
CodeIgniter loads CI_Controller after your vendor/autoload.php file, and since you're listing them under the "files" option in your composer.json, they're included immediately as opposed to right when you need them.
That's not only what causes the error, but also beats the entire purpose of using an autoloader - if you'd be explicitly listing the includes, you might as well just require_once them.
What's common in CI, is to require or even directly declare your multiple base controller classes from inside MY_Controller.php - then you know they'll be available exactly when you need them.
But if you insist on loading them through Composer, there's a work-around - list system/core/Controller.php under the autoloaded files as well.
I have a controller "MY_Controller.php" in "application/core" that extends "CI_Controller":
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Controller extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->helper('form');
$this->load->helper('url');
$this->load->helper('security');
$this->load->helper('language');
// Load language file
$this->lang->load('en_admin', 'english');
}
}
I created another controller called "Auth.php" in "application/controllers" that extends "MY_Controller":
class Auth extends MY_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('ion_auth');
if ($this->ion_auth->logged_in() === FALSE) {
redirect('user/login');
}
}
}
I created a third controller "Dashboard.php" that should extend "Auth", but throws an error:
class Dashboard extends Auth
{
public function index()
{
echo 'Hello from the dashboard';
}
}
Fatal error: Class 'Auth' not found in /home/user/www/forum/application/controllers/Dashboard.php on line 5
Would appreciate your advice to solve this problem.
The link in my comment has multiple ways to solve your problem. I prefer to use the #3 method - "Using an autoload function with hooks". Here's what works for me.
application/config/config.php
$config['enable_hooks'] = TRUE;
application/config/hooks.php
$hook['pre_system'][] = array(
'class' => '',
'function' => 'register_autoloader',
'filename' => 'Auto_load.php',
'filepath' => 'hooks'
);
application/hooks/Auto_load.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
function register_autoloader()
{
spl_autoload_register('site_autoloader');
}
/*
* Custom autoloader.
* This piece of code will allow controllers and other classes
* that do not start with "CI_" to be loaded when
* extending controllers, models, and libraries.
*/
function site_autoloader($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.'core/'.$class.'.php'))
{
require_once $file;
}
elseif(file_exists($file = APPPATH.'libraries/'.$class.'.php'))
{
require_once $file;
}
elseif(file_exists($file = APPPATH.'models/'.$class.'.php'))
{
require_once $file;
}
}
}
Your first extend of CI_Controller - class MY_Controller extends CI_Controller - should probably be in application/core/MY_Controller.php. Any classes that extend MY_Controller should be in application/libraries/.
The linked page labels the "hook" method as "the slow and right way" but the profiling I did comparing it to "2. Using an autoload function (the fast and dirty way)" showed a time difference of slightly over a microsecond. That's not worth worrying about.
I used the "fast and dirty way" for many years but kept forgetting about it when upgrading CI and I'd overwrite the config file resulting in a lost autoloader routine. Don't have that problem using the hook method other than remembering to set $config['enable_hooks'] to TRUE.
This is the regular behavior. Controllers do not extend each other. They may only extend MY_Controller (or CI_Controller). This is true for all MVC frameworks.
The way to use ion_auth, is not to extend Auth controller. You have already loaded ion_auth library, so you may directly use its methods in all controllers, the same way you use them in Auth controller.
Documentation for ion_auth here.
Well I've never used MY_Controller. I specify my class names.
I create all my classes under application/libraries and my structure is
Admin extends Common_Controller
Common_Controller handles the auth stuff for admin and members login/auth etc
Admin is a Controller up in application/modules/admin/controllers/Admin.php
Common_Controller extends Base_Controller
Base_Controller handles all the stuff common to all controllers like the templating etc
Base_Controller extends MX_Controller
MX_Controller is the wiredesignz HMVC Controller
MX_Controller extends CI_Controller
and we are done.
This is of course a HMVC setup but the principle is the same. Just don't use MY_Controller, give it a real name and use it normally.
And of course HMVC uses MY_Loader and other classes MY_xxx it uses to hook itself into CI and they live under application/core and it all plays nicely.
So as far as I can tell, there isn't a limit on how many classes deep you can go when you are extending them.
How can i create MY_Controller. Where is right place to put this file, i put it in core, folder, and i add into autoload file
code
function __autoload($class)
{
if(strpos($class, 'CI_') !== 0)
{
#include_once( APPPATH . 'core/'. $class . EXT );
}
}
then i created MY_Controller
class My_Controller extends CI_Controller
{
public function __construct() {
parent::__construct();
$this->load->view('view_header');
$this->load->view('includes/nav_home');
$this->load->view('view_home');
$this->load->view('view_footer');
}
}
but i keep getting error
Class 'MY_Controller' not found in C:\wamp\www\vezba\application\controllers\pages.php on line 4
i called MY_Controller in file
class Pages extends MY_Controller
{
function __construct() {
parent::__construct();
}
}
Where could be problem??
Double check the case on your class name and file name.
class MY_Controller extends CI_Controller
Notice how MY_ is all upper-case. Make sure this file is saved as application/core/MY_Controller.php, again note the case.
CodeIgniter should auto-load this file for you.
Docs: https://www.codeigniter.com/user_guide/general/core_classes.html
P.S. Check the $config['subclass_prefix'] option in your application/config/config.php file.
You don't need the autoloading functionality. Codeigniter will automatically load My_Controller as long as it's in your application/core directory.
You don't need to autoload your class, the framework will do it for you. In your case check the config file whether the subclass_prefix is 'MY_'. Eg; $config['subclass_prefix'] = 'MY_';
Put your class in application/core. Make sure the class name and the file name is the same.
I have created custom controller called "MY_Controller.php" in Application/core, and successfully invoked by inheriting through application controller.
//application/core
class MY_AdminController extends CI_Controller {
function __construct() {
parent::__construct();
}
}
//application/controllers
class User extends MY_AdminController {
public function __construct(){
parent::__construct();
}
}
It works fine. I just changed my file name from "MY_Controller.php" to MY_AdminController.php, and following same class name, but it is throwing following error,
Fatal error: Class 'MY_AdminController' not found
As per the documentation, Whenever you create a class with the MY_ prefix the CodeIgniter Loader class will load this after loading the core library, then why its throwing error...!!!
Go to your config.php and change
$config['subclass_prefix'] = 'MY_'; to $config['subclass_prefix'] = 'MY_Admin';
Expanding on Patel,
the issue is that MY_ is the prefix to the original core files.
Controller, Model, View etc.
MY_ will be used to seek the name of the controller, for example, MY_controller searches for CI_controller.
You cannot load random names using the MY_prefix. you use MY_ to extend the already existing names.
I think the problem is with the class name, you may have not changed the class name from MY_Controller to MY_AdminController
You can use custom classes. But CI only loads the classes with the class prefix in the config file (e.g. MY_). So I explained how it works and created a workaround to load classes automatically. You can find it here https://stackoverflow.com/a/22125436/567854.
Hope this helps :)
If you want to include all the files that are in your core folder. Then write the following code in end of config.php file.Path to file is application/config/config.php
function __autoload($class)
{
if (strpos($class, 'CI_') !== 0)
{
#include_once( APPPATH . 'core/' . $class . EXT );
}
}
By using this you can create multiple classes.
All I'm trying to do is something fairly simple :
Create a class (let's say brandNewClass - NOT MY_Controller) which extends CI_Controller
Create other controllers which extend brandNewClass
E.g.
class brandNewClass extends CI_Controller {
public function index()
{
}
public function info()
{
}
}
used like (in a file under /controllers) :
<?php
class newController extends brandNewClass
{
}
?>
The thing is, although it works when I'm copying the file under /application/core and naming it as MY_Controller, when I change the name to something more... self-explanatory, it doesn't.
Fatal error: Class 'brandNewClass' not found in .... on line ..
I've even tried using the __autoload function mentioned here, but without any luck.
Any ideas?
Have a look at this excellent tutorial - I hope it helps
http://codeigniter.tv/a-10/Extending-the-core-MY_Controller-and-beyond
The autoloader doesn't automaticly include other controllers. you will have to include it manually like this:
if (!defined('BASEPATH'))exit('No direct script access allowed');
include_once(APPPATH . 'controllers/brandnewclass.php');
If you want to create a custom base controller and make other controllers extend there, you can do it in following ways:
Create MY_Controller extending CI_Controller in application/core/ folder and make other controllers extend MY_Controller as MY_Controller will be autoloaded from core (This I guess you already know but want other alternatives.
Create MY_Controller in application/core/. Then create other level of Controllers that can primarily be Admin_Controller and Frontend_Controller. Now, one of these controllers will make base for your actual used controllers.
e.g. in application/core/MY_Controller.php
class MY_Controller extends CI_Controller {
public function __construct(){
parent::__construct();
}
}
Then Admin and Frontend controllers will be created in application/libraries/ and will extend MY_Controller like
class Admin_Controller extends MY_Controller {
public function __construct(){
parent::__construct();
}
}
Now, Any controller can extend one of these 2 controllers but for doing that you will have to autoload them. For autoloading in this case there can be a confusion because setting autoload['libraries'] in config/autoload.php will not work . That autoload works inside a controller but here we need to autoload before that i.e. in the class declaration. Will need to set this code in config/config.php
function __autoload($class)
{
$path = array('libraries');
if(strpos($class, 'CI_') !== 0) {
foreach($path as $dir) {
$file = APPPATH.$dir.'/'.strtolower($class).'.php';
if (file_exists($file) && is_file($file))
#include_once($file);
}
}
}
Now you can create your own controller
class newController extends Admin_Controller
{
}
This is the most suggested method making your structure quite clean and effective. May take some effort in understanding for the first time but is definitely worth it.
Third method is just a tweak of the second one, just based on the condition you mentioned of not using MY_Controller
You can make Admin_Controller or Frontend_Controller extend CI_Controller directly and not extend MY_Controller
That may just lead to some duplicity of code in both these controllers if that may be the case
http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-base-Classes-Keeping-it-DRY
I suspect you're trying something similar?
There's an autoload function that you can add to the config file so that you needen't require_once() the class all the time.
You should declare the class as abstract, since it shouldn't be instantiated directly.
You'll need to modify the CodeIgniter autoloader configuration file and add your class to it, or change the actual autoloader.
You really should consider not using CodeIgniter :)