0

In CodeIgniter I have a model named User_Model and another one named Product_Model

Now in the User_Model constructor I am loading couple of models that I use in the class.

class User_Model extends CI_Model
{
  public function __construct()
  {
    parent::construct();
    $this->load-model("Product_Model");
    //load some more models I need...
  } 
}

While working on products, I need sometimes to be using the user model, so I do:

class Product_Model extends CI_Model
{
  public function __construct()
  {
    parent::construct();
    $this->load-model("User_Model");
    //load some more models I need...
  } 
}

The problem is that since these are in circular reference, I am getting Fatal error: Maximum function nesting level of '100' reached. I am using xdebug and I know that it has settings to remove this. My question is - what is the correct way to handle this without increasing setting limitations. How should I restructure the architecture?

I know that if I am using PHP without codeigniter, and create circular references (class A loads class B, class B loads class A), PHP will load it for N times (I think it is three) and then mark it as *recursive*.

But we are faced with such a situation, what is the best way to refactor?

Undefined Variable
  • 4,196
  • 10
  • 40
  • 69
  • Why not just autoload both models, You seem to need them? – jtheman Jul 03 '14 at 12:16
  • Does either model actually require an instance of the other, or does it just need some values from that class - in which case pass the values into the constructor or method – Steve Jul 03 '14 at 12:18
  • @jtheman - the problem with autoloading is that they are being used all over the place with aliases, and CI autoloading does not seem to allow loading a model with an alias name :-( – Undefined Variable Jul 03 '14 at 12:20
  • @UndefinedVariable what version of CI you have ? is it `2.2.0` or `3.0 dev` – Karan Thakkar Jul 03 '14 at 12:21
  • @user574632 - both models use the methods of the other model. For each in User class I do `$this->product->getProductList();` -- this will get the product list for that user. I can technically pass the user to get the product list I guess...but there are other examples which are bit more complex – Undefined Variable Jul 03 '14 at 12:22
  • @karanthakkar - its not the dev branch. the latest stable branch whichever it is. should be 2.2.0 – Undefined Variable Jul 03 '14 at 12:24
  • Now I'm lost, why would you want to alias a model? – jtheman Jul 03 '14 at 12:25
  • if `2.2.0` yes you are correct `CCI does not allow autoload model with alias` but in `3.0-dev` it does allow `autoload with alias` but you can auto load. `it wont effect the alias given in other controllers` they will use by alias. – Karan Thakkar Jul 03 '14 at 12:25
  • Thats good to know, sadly I cannot upgrade at the moment.. – Undefined Variable Jul 03 '14 at 12:28
  • in that case i would recommend a refactor to except a user id or similar in the method or constructor. It may be complicated but what you have is not a good design. – Steve Jul 03 '14 at 12:29
  • @jtheman, most of the models were already aliased by the time I took over. Some models have ridiculously long names and some are aliased just to remove the _model from them... – Undefined Variable Jul 03 '14 at 12:29
  • @user574632 - what you said is true. However even if I need to pass the user id to a method in product class while I am in user_model, I still need to load the product class... – Undefined Variable Jul 03 '14 at 12:30
  • Yes, and that will be fine, its the 2 way dependency that is causing your issue. Probably you actually need one higher level class that has both a user and product model as properties, then passes relevent data between them, eg `$usersProducts = $this->productModel->getProductsByUser($this->userModel->getID);` – Steve Jul 03 '14 at 12:35
  • @UndefinedVariable you can copy `5-6` lines form CI `3.0-dev` core into your `2.2.0` and can achieve the task but if you want. i myself strictly avoid editing core files. – Karan Thakkar Jul 03 '14 at 12:49
  • @karanthakkar - do you know what those `5-6` lines are? – Undefined Variable Jul 03 '14 at 12:50
  • @UndefinedVariable there is minor changes in autoloading model in both CI. you can get `3.0-dev` from here https://github.com/EllisLab/CodeIgniter open `system/core/loader.php` of both find `public function model` in both and replace your `2.2.0`. now you can load like `$autoload['model'] = array('first_model' => 'first');`.its hardly `5-6` line changes.you can copy whole function no worries. cant write steps in comment. – Karan Thakkar Jul 03 '14 at 13:08
  • @karanthakkar - thank you, you should add your comment as an answer so I can accept it! – Undefined Variable Jul 03 '14 at 16:34
  • @UndefinedVariable glad to help. posted it as answer. cheers ;) – Karan Thakkar Jul 04 '14 at 05:00

1 Answers1

2

CI 2.2.0 does not allow autoloading model with alias but 3.0-dev does support it. since you have CI 2.2.0 you need to copy a function from 3.0-dev core to your 2.2.0 core.

Seps :

  1. Get CI 3.0-dev from Github
  2. Open system/core/loader.php of CI 3.0-dev.
  3. Find public function model function.
  4. Replace it in your system/core/loader.php of CI 2.2.0.
  5. Now you can autoload like $autoload['model'] = array('first_model' => 'first');

Note : This is solution for those who want autoloading model with alias but having CI 2.2.0

Karan Thakkar
  • 1,492
  • 2
  • 17
  • 24