Codeigniter - Can only load model in autoload.php - php

I'm going crazy because I have been using Codeigniter for ages now and I cannot seem to load a model in my view.
This is what I have done. Model code (models/changelog.php):
<?php
class Changelog extends CI_Model {
function __construct() {
parent::__construct();
$this->load->database();
}
function get_list() {
$query = $this->db->get('changelog');
return $query->result();
}
}
/* Location: ./application/models/changelog.php */
This is my controller (controllers/explore.php):
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Explore extends CI_Controller {
public function index() {
$this->load->view('include/header');
$this->load->view('home');
$this->load->view('include/footer');
}
public function changelog() {
$this->load->model('changelog');
$data['changelog_row'] = $this->changelog->get_list();
$this->load->view('include/header');
$this->load->view('explore/changelog', $data);
$this->load->view('include/footer');
}
}
/* Location: ./application/controllers/explore.php */
I get a Codeigniter notice telling me Message: Undefined property: Explore::$Changelog and a PHP error, Fatal error: Call to a member function get_list() on a non-object.
Here is what I did
Tried to autoload the database instead of only loading it in that model
Tried changing the Changelog call in the contorller to lowercase
Checked the connection to the database
Enabled the log file, which doesn't tells me anything new
Everything works correctly, maybe it's just me being a little tired, but if someone could help me out i'd love that :)
After some tests I found out the error is in the
$data['changelog_row'] = $this->Changelog->get_list();
line of my code. I have no idea what the problem is. Case sensitivity is fine (also tried many combinations of lowercase/uppercase), and even if I create another function with different name (e.g. foo()) with a normal echo inside I get the SAME error but referring to that function.
Here is a screen
Something incredible happened: if I add the 'changelog' model in the autoload.php, it seems it can actually load it. What is going on? I used this code already in many applications without a problem.
Another test I did: if I write
public function __construct() {
parent:: __construct();
$this->load->model('changelog');
}
In the controller or just add parent:: __construct(); in the changelog function like
public function changelog() {
parent:: __construct();
$this->load->model('changelog');
$data['changelog_data'] = $this->changelog->get_list();
$this->load->view('include/header');
$this->load->view('explore/changelog', $data);
$this->load->view('include/footer');
}
It works O_o. But why? I changed the topic title, now everything is around my inability to load my model in the controller's functions.

CI is acting a bit strange with that.
Om unix systems (where filenames a case sensitive) you have to load the model with case senstive names.
However in the controller you should address it with lowercase, i.e
$this->load->model('changeLog');
$this->changelog->getList();

Please change your changelog function with following syntax.
public function changelog() {
$this->load->model('changelog', 'model');
$data['changelog_row'] = $this->model->get_list();
$this->load->view('include/header');
$this->load->view('explore/changelog', $data);
$this->load->view('include/footer');
}
And your model's function should be as follows:
public function get_list() {
$query = $this->db->get('changelog');
return $query->result();
}
You miss the public keyword. So, it is a private function now that's why you can't access it from another class.

You are using the same name for the model as for the controller function so getting name clash because;
$this->changelog()
Is trying to refer to the model you have loaded and the class method at the same time.
Rename your Explore::changelog() function (or model name - suffix _m for example) and should be fine. Something like;
$this->changelog_m->getList();

After many hours of test and messing up with everything, INCLUDING configuration files... I DID IT!
It was something totally above models and controllers, it was something about the hooks I called. In fact, I have a hook called languageloader.php written like this:
class LanguageLoader extends CI_Controller {
public function initialize() {
$ci =& get_instance();
$site_lang = $ci->session->userdata('site_lang');
if (!empty($site_lang)) {
$ci->lang->load('text', $site_lang);
} else {
$ci->lang->load('text', 'english');
}
}
}
In my hooks file it was loaded like:
$hook['post_controller_constructor'] = array(
'class' => 'LanguageLoader',
'function' => 'initialize',
'filename' => 'languageloader.php',
'filepath' => 'hooks',
);
Since I was using post_controller_constructor, referring to CI doc files it is
Called immediately after your controller is instantiated, but prior to
any method calls happening.
I believe that doing something like my $ci =& get_instance(); I couldn't instance my damn model. I fixed it by changing the hook to
$hook['pre_controller']
I didn't think it could have been something about the hooks and that was the reasons why I didn't post it. Thanks to everyone who tried to help me out in the while. I hope this helped someone else who was in my same trouble!

For your reference, you can modify your autoload.php from
./application/config/autoload.php
then just include all you models exist on your model folder
./application/models/*_Model.php
So from autoload.php set your autoload['model'] array.
/*
| -------------------------------------------------------------------
| Auto-load Models
| -------------------------------------------------------------------
| Prototype:
|
| $autoload['model'] = array('first_model', 'second_model');
|
| You can also supply an alternative model name to be assigned
| in the controller:
|
| $autoload['model'] = array('first_model' => 'first');
*/
$autoload['model'] = array('Foo_Model', 'Bar_Model', ...);
Then from your Controller you can remove the $this->load(...); from your __construct(), since all Models you defined from autoload.php is loaded Globally and can be use whenever you run your system.
Then just call directly the public methods you need from that Model, like so;
$this->Foo_Model->your_public_method_to_call();
PS:
CI_VERSION: 3.x
PHP: 5.4+
I hope this helps somebody, thanks.

Related

Route in codeigniter3

I am learning codeigniter 3
In my config.php:
$config['base_url'] = 'http://'.$_SERVER['HTTP_HOST'].'/ci3x/admin/';
In my routes.php:
$route['customer'] = 'customer/index';
In controllers/customer.php:
class Customer extends MY_Controller{
function index(){
// some code here
}
}
When I type: http://localhost/ci3x/admin/customer on brower, it back error 404.
I have no clue to fix, please help me to solve it.
Many thanks
As you are extending a Class and that class does have a constructor, your class needs a constructor that also calls the constructor of the extended class.
Else things won't get up and running correctly.
class Customer extends MY_Controller{
public function __construct() {
parent::__construct(); // Call the MY_Controller constructor
}
function index(){
// some code here
}
}
The same goes for your MY_Controller constructor as it will need to call CI_Controller constructor... It ripples down and everything gets initialised correctly (in simplistic terms) .
Note:
Be careful with your controller and method files names. If you read the user guide it will say that the file names for controllers and methods should start with a capital letter.
So your controllers/customer.php should be controllers/Customer.php. If you are running on Windows it won't care. If you are running on Linux it will definitely matter.

Can't find model in CodeIgniter controller

I load the Get_notes model in line 8, but when I want to use Get_notes model to load add_notes method in line 23, the error occur and say Undefined property: Notes::$Get_notes in line 23 !
There is something wrong in line 23 but I dont know what is that.Please help me.
Thanks
<?php
class Notes extends CI_Controller
{
public function index()
{
$this->load->model('Get_notes');
$data['notes'] = $this->Get_notes->get_mm();
$this->load->view('show', $data);
}
public function insert()
{
$title = 'Something';
$text = 'Something else';
$data = [
'title' => $title,
'text' => $text
];
$this->Get_notes->add_notes($data);
}
}
The way you've written it, your Get_notes Model is only available within your index() function.
To make your Get_notes Model available to all functions within a single Controller, load it within that Controller's constructor function...
class Notes extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('get_notes'); // available to all functions within Notes
}
....
To make your Get_notes Model available globally to all functions in any CI Controller, put it in your $autoload['model'] array within the autoload.php file located at application/config/autoload.php...
$autoload['model'] = array('get_notes'); // available to all functions in your CI application
→ Note that it's supposed to be written in all lower-case no matter how you reference it later.
$this->load->model('get_notes');
$this->get_notes->add_notes($data);
See:
Class Constructors
If you intend to use a constructor in any of your Controllers, you MUST place the following line of code in it:
parent::__construct(); // Notice there is no dollar sign
Anatomy of a Model:
Where Model_name is the name of your class. Class names must have the first letter capitalized with the rest of the name lowercase. Make sure your class extends the base Model class.
Loading a Model:
Your models will typically be loaded and called from within your controller methods. To load a model you will use the following method:
$this->load->model('model_name');
Once loaded, you will access your model methods using an object with the same name as your class:
$this->model_name->method();
Auto-loading Resources
To autoload resources, open the application/config/autoload.php file and add the item you want loaded to the autoload array. You’ll find instructions in that file corresponding to each type of item.
An codeigniter model call is case sensitive therefore to get an model you should use
$this->get_notes->a_function_inside_the_model ();
Also note that the name inside the model folder should always start with a uppercase.
Whenever we run codeigniter on localhost servers like wamp server these problems dont exist but on a live server they will.
Hope this was helpful
Put $this->load->model('Get_notes'); in the insert() function.
If you want to use it globally, put it in a constructor.
Your get_notes model is only loaded in the index function. You cannot load the model in the index function and use it in any other function without having to load it again.
I'm thinking you're trying to load the model once and use it throughout your controller. To do this, you have to load it in the __construct method instead. Your code should be similar to this:
<?php
class Notes extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('Get_notes');
}
public function index()
{
$data['notes'] = $this->Get_notes->get_mm();
$this->load->view('show', $data);
}
public function insert()
{
$title = 'Something';
$text = 'Something else';
$data = [
'title' => $title,
'text' => $text
];
$this->Get_notes->add_notes($data);
}
}

How to get rid of &get_instance() in Codeigniter

I have been using CI for two years now. One thing that really annoys me is the use of &get_instance(). Although it is halpful while we are inside library , helper , presenters , model etc. But everytime loading it is cumborsome. If you forget loading it somewhere and simply use $this->blah->blah() instead of $CI->blah->blah() this makes too much trouble and if you are working online you face the client who is complaining that he sees the error. I have seen in the laravel that you does not need to load the instance anywhere throughout the application. This is because laravel is autoloading all the libraries and models and both are available anywhere in the application. But this seems to me disadvantage why loading classes that are not required in some particular places. This tells me Codeigniter is flexible but still i want an alternative where i dont want to use &get_instance(). Any idea or suggestion ? Please.
In your model or Core model or library
//class MY_Model extends CI_Model
//class SomeLibrary
class Some_model extends CI_Model {
private $_CI;
public function __construct() {
parent::__construct(); //for model or core model
$this->_CI =& get_instance();
}
//if you called attributs who does not exist in that class or parent class
public function __get($key)
{
return $this->_CI->$key;
}
//if you called methods who does not exist in that class or parent class
public function __call($method, $arguments)
{
call_user_func_array(array($this->_CI, $method), $arguments );
}
public function test() {
var_dump($this->some_controller_key);
var_dump($this->some_lib_loaded);
}
}
*NOT TESTED YET
Inspired by an piece of code from the awesome Flexi Auth
//from a Model to keep access of CI_Controller attributs
public function &__get($key)
{
$CI =& get_instance();
return $CI->$key;
}
I was shocked when I saw that ^^
To explain the &__get, i think when you will call this magic method a second time PHP will do not execute it again, but will take his result from the first call.

CodeIgniter adding page doesn't work

I have taken over a project written in CodeIgniter, which I have never used before. I have added a new file to views/pages called features.php, and have read on the internet that to make it accessible, I need to create a function in the controller file that will render the page.
I have tried the following:
public function features()
{
$this->render('template', 'pages/features');
}
However, when I try to open features.php, it gives me 404. How can I fix that?
Update 1 - Class
Here is the controller's class code:
class Pages extends MY_Controller {
function __construct()
{
parent::__construct();
$this->load->model('setting_model', 'setting');
$this->load->model('order_model', 'order');
$this->load->model('page_model', 'page');
$this->load->library('form_validation');
$this->load->helper(array('inflector', 'string'));
}
public function index()
{
$settings = $this->setting->get_settings();
$data['document_price'] = $settings->document_price;
$this->render('template', 'pages/index', $data);
}
//This works fine
public function about_us()
{
$this->render('template', 'pages/about_us');
}
//Here is the problem, although it follows the same pattern as about_us()
public function features()
{
$this->render('template', 'pages/features');
}
}
As you are using $this->render I guess you are using the template library. I think you should be using:
public function features()
{
$this->template->set_template('template');
$this->template->write_view('pages/features');
$this->template->render();
}
The php files contained in /views are not directly accessible by typing in some URL. CodeIgniter is an MVC framework. That means that your URLs are mapped to your controllers and the controllers call the views.
What is the name of the class that this function is encapsulated in? Please post the entire class and not just the features() function and we can help you out. If you're working locally, the default mapping to call controllers is: http://localhost/appname/controller/function/param1/param2/etc.
The $this->render() function is not vanilla CodeIgniter syntax, you either inherited a project that is using a templating library, or, there is a sibling render() function inside the controller class.
Check your config/routes.php file as well and consider posting it.
If you want to diagnose the issue, try pinpointing by removing the call to $this->render() and instead using CodeIgniter's native $this->load->view('pages/features') function. If this works, we can be sure it's the library or render() call.

Why are two controller methods being called in CodeIgniter?

Should I not be using Index as the name for a controller class in CodeIgniter? I have an Index controller, and I'm seeing its methods being called multiple times. More specifically, I always see its index method called first, whether or not I'm visiting a path that should be routed there.
In application/controllers/index.php
class Index extends CI_Controller
{
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
When I visit index/blah, I see indexblah printed. When I visit index/index, I see indexindex. If I rename the controller to something else (e.g. Foo), it doesn't have a problem. That's the obvious workaround, but can anyone tell me why this is happening? Should I report this as a bug to CodeIgniter?
(Notes: I have no routes set up in configs/routes.php; my index.php is outside the CodeIgniter tree)
To further clarify what the issue is, in PHP4 Constructors were a function that had the same name as the Class...
example
class MyClass
{
public function MyClass()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
Now for the PHP5 version (Which codeigniter now, as of 2.0.x, holds as a system requirement)
class MyClass
{
public function __construct()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
So To answer the question that addresses the problem...
Should I not be using Index as the name for a controller class in CodeIgniter?
I believe it would be best to not choose Index as a controller name as the index() function has a reserved use in codeigniter. This could cause issues depending on your PHP configuration.
can anyone tell me why this is happening?
When your controller get's instantiated, index as the constructor is getting called.
Compare Constructors and DestructorsDocs:
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 . [highlighting by me]
In your case your Controller does not have any __construct() function but a function that has the same name as the class: index. It is getting called in the moment Codeigniter resolves and loads and then instantiates your Index Controller.
You can solve this by just adding the constructor to your Controller:
class Index extends CI_Controller
{
public function __construct() {}
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
After this change, it does not happen again.
Should I report this as a bug to CodeIgniter?
No, there is not really a need to report this as a bug, it's how the language work and as Codeigniter supports PHP 4 it must remain backwards compatible and needs to offer PHP 4 constructors. (Note: The Codeigniter project documents, they need server support for PHP version 5.1.6 or newer, but the actual code has PHP 4 compatiblity build in, I'm referring to the codebase here, not the documentation.)
Here is another solution using Codeigniter3
require_once 'Base.php';
class Index extends Base
{
public function __construct()
{
parent::index();
$classname=$this->router->fetch_class();
$actioname=$this->router->fetch_method();
if($actioname=='index' || $actioname == '')
{
$this->viewall();
}
}
}
And the viewall() had the following
$this->siteinfo['site_title'].=' | Welcome';
$this->load->view('templates/header', $this->siteinfo);
$this->load->view('templates/menu', $this->siteinfo);
$this->load->view('index/viewall', $data);
$this->load->view('templates/footer', $this->siteinfo);
The Base controller does all the library and helper loading for the entire application which is why it is being required in the default class
Basically from my short understanding of CodeIgniter, having a default action as index is a wrong. I found this out by using the printing the result of $this->router->fetch_method(); in the construct() of my index class. The default action by CodeIgniter is index, you may only set the default controller within application/config/routes.php and not the default action.
So my advice, never use index() as the default action especially if you are using index as the default controller

Categories