• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
CI and instantiating classes

#1
[eluser]Jow272[/eluser]
Hello all,

I keep getting errors when I instantiate a class in a controller. I can't figure out what I'm doing wrong.

I'm writing a web application in CI in which there are several types of addresses to be stored, like the address of a building, of a persons birth, death and more variations. As I want to store all addresses in one single table, it seems appropriate to me to use a specialised address controller and address model to handle the functions related to the addresses. So I did the following:

address.php;
Code:
class Address extends MY_Controller{
   // private fields
   private $m_id;
   private $m_street;
   ...

   // constructor
   function __construct($address = NULL)
   {
      // load the parent controller
      parent::Controller();

      $this->load->model('address_model');

      // set the private fields
      if ( $address != NULL )
      {
         $this->m_street = $address->street;
         ...
      }
   }

   public function create()
   {
      // create a new address
      ...
   }

   public function check_if_address_is_known($address = NULL)
   {
      // check if the address is already stored in the address table
      ...
   }
}

example caller i.php:
Code:
include_once("address.php");

class I extends MY_Controller{
   // constructor
   function __construct($address = NULL)
   {
      // load the parent controller
      parent::Controller();

      $this->load->model('i_model');
   }

   public function create($data)
   {
      $address_controller = new Address($data);

      $address_id = $address_controller->check_if_address_is_known();

      ...
   }
}

Running the code produces a php error "Undifined property: Address::$i_model", Filename "libraries/Loader.php", Line NUmber: 1035.

This error is caused by the instantiating of the address class.

Anyone any idea's? Thanx in advance!

#2
[eluser]jedd[/eluser]
[quote author="Jow272" date="1258835507"]

Code:
class Address extends MY_Controller{
   // constructor
   function __construct($address = NULL)
   {
      // load the parent controller
      parent::Controller();
[/quote]

The parent controller of anything that extends MY_Controller is not Controller(), but MY_Controller().

#3
[eluser]Jow272[/eluser]
@jedd, thanx for your reply. You'r wright of course, only that the constructor in MY_Controller is called __construct(). So I altered that, but unfortunately it did not solve my problem. I still have the same error. By the way, the error also shows the following message "Fatal error: Call to a member function _assign_libraries() on a non-object in C:\xampp\htdocs\Concept\system\libraries\Loader.php on line 1035". Sorry I missed to add it to my first message.

I did find a bit more about the error though. It seems that it has to do with loading the libraries. If I comment out the
Code:
$this->load->model('address_model');
line in the address.php file, the error disappears.

But this means I will not be able to load the required model for accessing the database!

To complete the code I use I'll add the address_model.php code:

Code:
class Address_model extends Model{
    // constructor
    function __construct()
    {
        // load the parent constructor
        parent::Model();

        // load the database class and connect to MySql
        $this->load->database();
    }

    public function get_address_id_from_data($street, $number, $place, $country = NULL, $postal_code = NULL)
    {
       return false;
    }
}

I do need the access to the address_model functions to be able to manipulate the data in the tables.

#4
[eluser]jedd[/eluser]
[quote author="Jow272" date="1258845032"]
I did find a bit more about the error though. It seems that it has to do with loading the libraries. If I comment out the
Code:
$this->load->model('address_model');
line in the address.php file, the error disappears.
[/quote]

That's a model, not a library. Are you loading libraries successfully - such as CI library classes for example?

Try doing what the user guide suggests, and follow the case specifications. That is, ucfirst() style.

So instead of this:
Quote:
Code:
$this->load->model('address_model');

Do this:
Code:
$this->load->model('Address_model');

Ensure your model's filename is 'address_model.php'. Your Address_model class name looks fine.

#5
[eluser]Jow272[/eluser]
You're wright, it's a model of course.

I tried the Uppercase first style, but that didn't solve the problem, although I will keep that style as it is best practice.

But I suddenly thought I'd try to make the Address_model class clean, so I commented out the constructor and got the error out. By removing the comments signs one by one I found out that the problem lies with the
Code:
$this->load->database();
line! This is wierd, why should that not work? I used that in so many other (if not all of mine) model classes.

Damn; again one step further, but still useless. I of course need the database class in my model to be able to work with the database. Also a bit stupid I didn't think earlier about commenting out deeper.

When I leave the line out I (obviously) get errors concerning the $this->db lines.

Any thoughts?

#6
[eluser]jedd[/eluser]
[quote author="Jow272" date="1258849312"]
But I suddenly thought I'd try to make the Address_model class clean, so I commented out the constructor and got the error out. By removing the comments signs one by one I found out that the problem lies with the
Code:
$this->load->database();
line! This is wierd, why should that not work? I used that in so many other (if not all of mine) model classes.
[/quote]

I think there was a problem like this a little while ago where the guy ended up just pulling in a new copy of CI, putting their code back into place, and it worked. Certainly most of us have no problems most of the time when we load the database class. Wink

Can you autoload it? It doesn't sound like it's autoloaded already, otherwise your db calls would work.

It might be a database configuration problem - can you share (with minimal changes - just xxxx the password) your config/database.php file?

#7
[eluser]Jow272[/eluser]
Ok, to me it seems like a CI limitation Undecided.

In the webapplication I already have several models that load the CI database class with no problem. I even tried calling this Address_model from other controllers and that was no problem at all. This means to me that there is nothing wrong with the Address_model class.

The only difference in the situation that fails is that I instantiate a new controller class (the Address class) from within a CI controller class, instead of activating it from a URL.

If I start the "localhost/Concept/index.php/address/check_if_address_is_known URL", it works without a problem. It also works when I remove all CI code and only use bare PHP database access code in the Address_model class.

So to me it looks like CI does not allow to instantiate controller classes from within CI controller classes.

I'm not sure what to do now. I don't like to use CI data access procedures and PHP data access procedures together in one application, but I also would hate to have to use just one large controller that does not separate the address functions I use everywhere. Maybe I'll go for putting them in the MY_Controller class, but I found the first option of having a seperate Controller and Model for this better.

Any ideas/sugestions?

#8
[eluser]jedd[/eluser]
[quote author="Jow272" date="1258905282"]
Any ideas/sugestions?[/quote]

I'm about to duck out, but briefly - you may want to investigate the get_instance() function of CI - it's truly ugly to use it in this context, and I suspect that you just need to redesign your application such that you're not trying to create a clone of your controller from within your controller ... but for the time it will give you something to play with.

Consider writing up a description of your goal here - not the way you're currently doing it - but what you are actually trying to achieve, in terms of results. It means someone will be more likely able to offer you some genuinely useful advice on how to do this more elegantly.

#9
[eluser]Jow272[/eluser]
Thank you jedd so far.

To explain what I want to do; I'm building a webapplication in which users can store a wide variaty of information. This means that user data is stored and with this user data of course also address data.

A user can store address data of his home address, but also from buildings, schools, events and more. This means that there will be several Controllers in the application that require functionalities to work with address data. The database for the application has for normalization reasons only one table for addresses.

So to me it seems nice (BP) to have one specialized set of (Address_)Controller and (Address_)Model to handle all the address related functions. But this then means that I have to activate (instantiate) the Address_controller from within the controller where the user is currently working in.

Hope this clarifies things.

#10
[eluser]jedd[/eluser]
[quote author="Jow272" date="1258915803"]
To explain what I want to do; I'm building a webapplication in which users can store a wide variaty of information. This means that user data is stored and with this user data of course also address data.
[/quote]

Happily this doesn't sound hugely left-field. Wink


From what you describe .. well, I have a few ideas, but need more info. I'd suggest that some of the functions in your controller(s) that you want to call from elsewhere should be, themselves, relocated. They could reside in any of these places:
o MY_Controller - excellent for common functionality that's short, sharp and sweet
o library - excellent for stuff that you want from some, but not all, your controllers
o helpers - ideal for things that involve munging around with data but ideally don't required the $CI superobject / DB access
o models - yes, you have some already, but they aren't *just* for getting/setting database records

Okay, for instance, can you give a list of the controller function that you've got (cd application/controllers ; grep function * ) - that will provide a good insight, assuming you've used sensible names for your functions in there.

Alternatively you may just get away with having fewer, fatter controllers (though I suspect you'll still need to consolidate some functionality as per the above options).

Quote:The database for the application has for normalization reasons only one table for addresses.

Normalisation reasons are good reasons - in my v.minimal experience, a decently normalised (to 3NF) schema makes for cleaner model interfaces, though this may apply more to models that front several tables - rather than a 1-model-per-table arrangement. Oh, if you're using that approach, you might get some benefit from shifting several tables to be handled by one model - depends on your schema, and complexity of data accesses of course.

In any case, I think we can help you come up with a more elegant method than calling multiple instances of a controller.


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2019 MyBB Group.