Welcome Guest, Not a member yet? Register   Sign In
Weird behaviour in $this->model->load()
#1

[eluser]Unknown[/eluser]
Hi guys,

I was wondering if you could shed a little light on my current dilemma.

Basically, I'm using $this->load->model(X) and $this->load->model(Y)

Both files X and Y exist, are identically located with identically formatted names ('posts' and 'pages' in minuscule).

Both models X and Y are at the moment identical apart from their name (and the appropriate function name changes).

However, I can call $this->X but not $this->Y - see the error message

Code:
A PHP Error was encountered

Severity: Notice

Message: Undefined property: Sidebars::$Posts

Filename: models/sidebars.php

Line Number: 97

Fatal error: Call to a member function getRows() on a non-object in /****/application/models/sidebars.php on line 97

Best explained through code, the relevant files (various comments removed) are below:

Model: Sidebars (application/models/sidebars.php)
Code:
<?php
class Sidebars extends Model
{
    function Sidebars()
    {
          parent::Model();
    }

    function loadSidebar($type)
    {
        $sidebar = array();
        
        switch( $type )
        {
            case "pages":
                $sidebar['pages']    = $this->pageList();
                $sidebar['popular'] = $this->popularPosts();
                break;
        
        }
        
        return $sidebar;
    }
    
    function pageList()
    {
        $pageList = array();
        
        $this->load->model("Pages");
        
        foreach( $this->Pages->getRows(NULL, "method, title") as $row )
        {
            $pageList[ $row['method'] ] = $row ['title'];
        }
        
        return $pageList;
    }
    
    function popularPosts()
    {
        $popularPosts = array();
        
        $this->load->model("Posts");
        
        foreach( $this->Posts->getRows(NULL, "id, method, title", "views DESC", "5") as $row )
        {
            $popularPosts[ $row['id']."/".$row['method'] ] = $row ['title'];
        }
        
        return $popularPosts;
    }
}
?>

Model: Pages (application/models/pages.php)
Code:
<?php
class Pages extends SpecialActiveRecord
{
    function Pages()
    {
          parent::SpecialActiveRecord();
          
          $this->loadColumnsFromTable("pages");
    }
}
?>

Model: Posts (application/models/posts.php)
Code:
<?php
class Posts extends SpecialActiveRecord
{
    function Posts()
    {
          parent::SpecialActiveRecord();
          
          $this->loadColumnsFromTable("posts");
    }
}
?>


Note: The class SpecialActiveRecord is just an extension to the standard Model class. It actually provides me with quick shortcuts to the combination of ActiveRecord functions I use most (another layer of abstraction! yipee). This shouldn't be causing the error as it is identically loaded by both X and Y classes!

---

So basically the first call to $this->pageList() is working fine but not $this->popularPosts();

Many thanks for any help you can give me!
#2

[eluser]gtech[/eluser]
You cant load a model within a model like that outside the constructor... has the pages model been loaded outside the model and thats why it works?


what you could try is to load the models in the constructor

Code:
<?php
class Sidebars extends Model
{
    function Sidebars()
    {
          parent::Model();
          $this->load->model("posts");
          $this->load->model("pages");
    }
    function you_get_the_gist()
    {
        $this->pages->methodname();

....

give it a go see if it works I may be on the wrong track its only a guess.



you can also try this
Code:
class Sidebars extends Model
{
    private $CI;

    function Sidebars()    
    {
        parent::Model();
        $this->CI =& get_instance();    
    }
    
    function you_get_the_gist()
    {
        $this->CI->load->model('pages');
        $this->pages->methodname();
#3

[eluser]tonanbarbarian[/eluser]
Ok

Firstly I am not sure if you load a model from a model that the new model will be available inside the original model, only in the controller. Not 100% sure on that so that might be the issue.

More likely though is that you are doing the following...
Code:
$this->load->model("Posts");
        
        foreach( $this->Posts->getRows(NULL, "id, method, title", "views DESC", "5") as $row )
But i am pretty sure CI only loads the model names in lower case so try
Code:
$this->load->model("Posts");
        
        foreach( $this->posts->getRows(NULL, "id, method, title", "views DESC", "5") as $row )
#4

[eluser]gtech[/eluser]
[quote author="tonanbarbarian" date="1197520454"]Ok

Firstly I am not sure if you load a model from a model that the new model will be available inside the original model, only in the controller. Not 100% sure on that so that might be the issue.

[/quote]

[edit]
you may of have a point tonanbarbarian, as you often give good advice so I tested your theory, however the results suggested the following:

Code:
<?php
class Test extends Controller {

  function Test()
  {
    parent::Controller();
  }
  function start($user='foo',$pw='bar')
  {
    $this->load->model('mod1');
    $this->load->model('Mod2');
    $this->Mod2->fg1();

  }
}
?>

<?php
class Mod1 extends Model
{
  function Mod1()
  {
    parent::Model();
  }

  function f1() {
    echo "hello";
  }
}
?>

<?php
class Mod2 extends Model
{
  function Mod2()
  {
    parent::Model();
  }
  function fg1() {
    echo "hello";
    $this->mod1->f1();
  }
}
?>
Note: The capitalization did not make a difference (I did not know this before I tried it)
Result: hellohello

Which means even though I load Mod1 outside Mod2 in the controller, I can still reference Mod1 inside Mod2. This means in theory at least Adrien could of loaded the pages model before you load the sidebar model and maybee thats why one works and one does not.

Adrien is loading a model within a model and I know in CI you cant do this by using the normal $this->load->model outside the constructor as I have been stung by this before.

You either need to load the model/s in the constructor of the model (you will be able to reference the methods outside the constructor) OR use the CI instance as described in reply 1.
#5

[eluser]Unknown[/eluser]
Thanks guys.

I'd tried using the CI instance and it worked, I forgot to mention this in my first message.

I was wondering if there was a way of doing it without using the CI instance (which is a rather ugly solution) but gTech's suggestion works: load the models within the constructor.

I guess it'll be a tradeoff decision: load all my models within the constructor or using the CI instance to limit the number of modules being loaded to the minimum necessary (the sidebar model is likely to have the ability to loadover a dozen modules).

Cheers though!
#6

[eluser]gtech[/eluser]
[quote author="MPress" date="1193887618"]The problem is in the 'model' method of Loader.php.

You just have to add
Code:
$this->_ci_assign_to_models();
to the last line (after line 169) of the 'model' method and the problem disappears. Without this line, the reference to the newly instantiated model is not being assigned to the subject (calling) model and only exists in the CI instance.

I'll reference this thread in a bug report and hopefully this will be remedied in the next release.[/quote]

Mpress found the above solution so you can load the models in the 'normal' way, and it does work however I do not know what the trade offs are (if any).




Theme © iAndrew 2016 - Forum software by © MyBB