This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Codeigniter extending extended MY_Controller
I have been fiddling with this problem for a while now, and am at the point of frustration. I am extending the controller class with MY_Controller.
Here are the details:
__construct() does not seem to be called.
The file is located in application/core as it should be
The file is named MY_Controller.php
I have MY_ set up as the prefix for extensions (I have other extensions which work fine)
Here is my code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
echo 'TESTING!!!'; // This should print, followed by an ob_start() error
}
}
I should get a page back that says TESTING!!! followed by an ob_start() error, but instead the page renders normally.
I have tried splitting up the constructor class and just calling a private function within MY_Controller, but that doesn't work. I know the file is being called because if I purposefully create a php error within MY_Controller.php, the page will error out. It seems to me that the __construct() is just not running.
Can you show an example of one your controllers under application/controllers? Pls note that the controllers under application/controller should extend MY_Controller instead of CI_Controller - I think this is what you missed.
For example, under your controller application/controller/test.php. it should look like this:
class Test extends MY_Controller {
public function index()
{
echo 'test';
}
}
Related
This question already has answers here:
How to load a controller from another controller in codeigniter?
(10 answers)
Closed 3 years ago.
I am trying to load controller but neither its giving error or showing blank after loading this controller
$this->load->library('../controllers/invoiceajax');
$this->invoiceajax->sendsecurityinvoice($this->input->post('depositid'),$insert_id,$this->security->xss_clean($this->input->post('securitycheck')));
I think it's not good practice to call another controller's function.
Just try to make it as CodeIgniter's custom helper function and use it in both controller.
Make invoice helper function in application/helpers directory of CI.
$this->load->helper('invoice');
$this->invoice->sendsecurityinvoice($this->input->post('depositid'),$insert_id,$this->security->xss_clean($this->input->post('securitycheck')));
You can extend one controller like this and then use this controller in other. It's good practice to save this controller in libraries, not in controllers.
This is base controller Base_CI.php in application/libraries
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Base_CI extends CI_Controller{
public function sendsecurityinvoice($data){
if(!empty($data)){
return $data;
}
}
}
Then in other controller Invoiceajax.php do this:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require APPPATH.'/libraries/Invoiceajax.php';
class Invoiceajax extends Base_CI{
public function test() {
return $this->sendsecurityinvoice('Hi');
}
var_dump($this->test());
}
I have been using codeigniter for sometime now. But I am still new to it. And when I bump into some problem, its takes days to figure it out and solve it.
Unable to locate the model you have specified: page_m
I usullay face these sort of errors too. However since I am using multiple hierarchy of classes (Controllers) I am not being able to figure it out.
Is there any way I could make codeigniter to log the error messages with the line number??
You have to create model in Application/Models directory. and make sure you extend your CI_Model class.
eg. model name : my_model
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class my_model extends CI_Model {
public function __construct() {
$this->load->database();
}
}
Are you sure that the file name is the same as the name of the class?
If your file is page_model.php the class must start with class Page_Model extends CI_Model
And in your controller remember $this->load->model('page_model');
Hi I'd like to add a public variable ($this->data[]) to all instances of CI_Controllers, that way I can store some base rules for outputting a page (css/js, etc) then have each controller append to this array to add its own requirements (more css/js). I have a core library with custom view functions that take those arrays and inject them into the head tag of the page template.
The options I've thought of;
Edit CI_Controller and add it there... guessing that's a bad idea.
Create a shell controller that extends CI_Controller, add the var to that, then have every other controller extend the shell controller.
Any other clever ways?
I've only been using CI for about a month and I've tried reading through the docs but I can't find any built in ways to do something like this? Has anyone encountered this before and if so how did you solve it?
Thanks!
[edit] Using PHP 5.3.x [/edit]
http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html
You can extend CI_Controller to have the functionality you want.
application/core/MY_Controller.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
}
public function my_function()
{
return "Cool return from my_function";
}
}
controllers/welcome.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Welcome extends MY_Controller {
public function index()
{
echo $this->my_function();//echo's "Cool return from my_function"
}
}
You simply define the functionality you want in MY_Controller. Then in your controllers, use extends MY_Controller instead of extends CI_Controller and you can call the functions anywhere inside those controllers.
I think what you want can be easily achieved using traits. Check here: PHP: Traits
More specifically -> Example #11 Defining Properties.
The only limitation is it's PHP 5.4+
You can create your own a base controller file to inherit basic page load methods from in \application\core\MY_Controller.php as such:
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
}
protected function loadPage($path, $data = array())
{
$this->load->view('common/head'); // Assuming you will use a folder for page parts
$this->load->view($path, $data);
$this->load->view('common/foot');
}
}
Afterwards in your page controller you can call upon the same methods much more easily:
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class User extends MY_Controller {
public function index()
{
$data = array(); // get data from model
$this->loadPage('user/view', $data); // Assuming you will use folders for sets of views
}
public function edit()
{
$data = array(); // get data from model
$this->loadPage('user/edit', $data);
}
}
I have class MY_Controller extends CI_Controller and common logic for big profile section, so I'va tried to create class Profile extends MY_Controller with common logic for profile section and all class related to this section should extends this Profile class as I understand right, but when I tried to create class Index extends Profile I recieve an error:
Fatal error: Class 'Profile' not found
CodeIgniter tries to find this class in index.php which I am running.
Where is my mistake? Or maybe there is anoter better way to mark out common logic?
I take it you have put your MY_Controller in /application/core, and set the prefix in the config.
I would be careful about using index as a class name though. As a function/method in Codeigniter it has a dedicated behaviour.
If you then want to extend that controller you need to put the classes in the same file.
E.g. In /application core
/* start of php file */
class MY_Controller extends CI_Controller {
public function __construct() {
parent::__construct();
}
...
}
class another_controller extends MY_Controller {
public function __construct() {
parent::__construct();
}
...
}
/* end of php file */
In /application/controllers
class foo extends MY_Controller {
public function __construct() {
parent::__construct();
}
...
}
or
class bar extends another_controller {
public function __construct() {
parent::__construct();
}
...
}
I found this page on Google because I had the same problem. I didn't like the answers listed here so I created my own solution.
1) Place your parent class in the core folder.
2) Place an include statement at the beginning of all classes that include the parent class.
So a typical controller might look like this:
<?php
require_once APPPATH . 'core/Your_Base_Class.php';
// must use require_once instead of include or you will get an error when loading 404 pages
class NormalController extends Your_Base_Class
{
public function __construct()
{
parent::__construct();
// authentication/permissions code, or whatever you want to put here
}
// your methods go here
}
The reason I like this solution is, the whole point of creating a parent class is to cut down on code repetition. So I don't like the other answer that suggested copy/pasting the parent class into all of your controller classes.
It is possible with Codeigniter 3. Just including the parent file is enough.
require_once(APPPATH."controllers/MyParentController.php");
class MyChildController extends MyParentController {
...
All classes you are extending should live in application/CORE directory so in your case both My_Controller and Profile should live there. All "end point" controllers will live in application/controllers folder
UPDATE
I stand corrected. Extended classes should live in the same file. #Rooneyl's answer shows how to implement
After some struggle with version 3 and this issue I decided this was not a bad solution...
require_once BASEPATH.'core/Controller.php';
require_once APPPATH.'core/MYCI_Controller.php';
to add this second line where the first exists in the system/core/CodeIgniter.php
[If it's not too late, I recommend strongly against php and/or CodeIgniter.]
Ok, so in my base controller (page.php) I have the following code which works fine:
$this->load->library('Siteclass');
$mysite = new site_model();
The siteclass library references a model named site_model and instantiates based on data received from that model. All is good.
Now I want to load another library so that I can instantiate another object as well. So I add this to page.php:
$this->load->library('Memberclass');
$mysite = new member_model();
But now I get the following error:
Message: Undefined property: Memberclass::$site_model
Filename: libraries/Loader.php
Line Number: 1035
From what I can tell, it seems that the loader class, when being applied to the Memberclass, is somehow still referencing the site_model instead of the member_model. I've checked my code and I am definitely calling the correct files.
Here's what Siteclass.php looks like:
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Siteclass extends Controller {
function __construct() {
parent::Controller();
$this->load->model('Site_model');
$data = $this->Site_model->load_site_data();
// etc etc
and here's what Memberclass.php looks like:
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Memberclass extends Controller {
function __construct() {
parent::Controller();
$this->load->model('Member_model');
$data = $this->Member_model->load_member_data();
// etc etc
Thanks in advance for any help!
Gary
I think you're confused about how MVC works in CodeIgniter. Why are you using the loader class to create a controller? Why are you creating a stand-alone instance of your model outside of your controller class?
In CodeIgniter, your URLs represent paths to your controllers' methods. That means that your "base controller" should automatically be instantiated if you go to:
www.example.com/memberclass
Or perhaps more to the point, if you have a link like this:
www.example.com/page
You should have a file in your /application/controllers directory called page.php which looks like this:
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Page extends Controller {
function __construct() {
parent::Controller();
// etc etc
Furthermore, unless you're loading data from your model to be used every single time you call this controller, you'll want to put your model calls inside a non-constructor method of this class. Something like:
class Page extends Controller {
function __construct() {
parent::Controller();
}
function index() {
$this->load->model('Member_model');
$data = $this->Member_model->load_member_data();
$this->load->view('myview', array('data'=>$data));
}
}
So again...not entirely sure what context you're doing this all in, but it seems like you're not standing firmly within the framework. There's basically no reason you should be using the loader class to load controllers, and furthermore there's no reason you should be creating stand-alone instances of model classes using PHP's new keyword.