Page 1 of 1

Scope issue with __construct()

Posted: Wed Jul 04, 2007 11:51 pm
by Quintok
Hello All, I apologise in advance my first post is a request for help, I know how irritating that can be.

I think I've made a quite obvious mistake it's just I can't figure out what it is.
For some reason php doesn't seem to like me referencing external global (is it global?) variables from inside a constructor of another class in another file. Here are my three files and their corresponding contents, I've written two copies of "loadSecond.php" one that works and one that does not but I'd like it to.

I'm using v5.2.3

index.php

Code: Select all

<?php
include_once "loadFirst.php";
include_once "loadSecond.php";
?>
loadFirst.php

Code: Select all

<?php
class FirstLoaded
{
   function test()
   {
      echo "hurrah!";
   }
}
$FirstLoaded = new FirstLoaded();
?>
loadSecond.php that does not work

Code: Select all

<?php
class foo
{
   function __construct()
   {
      $FirstLoaded->test();
   }
}
$foo = new foo();
?>
loadSecond.php that does work

Code: Select all

<?php
$FirstLoaded->test();
?>
here is the output
Notice: Undefined variable: FirstLoaded in C:\Inetpub\wwwroot\new\loadSecond.php on line 6

Fatal error: Call to a member function test() on a non-object in C:\Inetpub\wwwroot\new\loadSecond.php on line 6
thank you for any possible help.

Posted: Thu Jul 05, 2007 12:01 am
by John Cartwright
The manual explains everything on scope :wink:

To solve your situation, you need to pass the object to the class.

Code: Select all

class foo
{
   function __construct($FirstLoaded)
   {
      $FirstLoaded->test();
   }
}

$FirstLoaded = new someotherclass();

$foo = new foo($FirstLoaded);

Posted: Thu Jul 05, 2007 12:02 am
by Zoxive
$FirstLoaded isn't global.

So either do

Code: Select all

<?php
class foo
{
   function __construct()
   {
      GLOBAL $FirstLoaded;
      $FirstLoaded->test();
      // OR
      FirstLoaded::test();
   }
}
$foo = new foo();

Posted: Thu Jul 05, 2007 12:11 am
by Quintok
thank you for your replies.
I had actually tried global in my actual code and it'd thrown up a similar error to my example I posted here however it was for an unrelated problem (forgot a '$') when I tried the equivilent of:

Code: Select all

<?php
class foo
{
   function __construct()
   {
      global $FirstLoaded;
      $FirstLoaded->test();
   }
}
$foo = new foo();
?>
which lead me to believe that 'global' was not the solution :)
thanks for the help.

Posted: Thu Jul 05, 2007 1:54 am
by miro_igov
Zoxive forgot to

Code: Select all

}
$FirstLoaded = new FirstLoaded();
before to the

Code: Select all

$foo = new foo()
This will work with global , but using globals is not good idea. Better pass the first class as parameter.

Posted: Thu Jul 05, 2007 7:35 am
by feyd
Using the global keyword is bad practice. Pass the object into the constructor as Jcart suggests.

Posted: Thu Jul 05, 2007 7:45 am
by Chris Corbyn
If FirstLoaded will always be the same object instance, you may want to look at the singleton or the registry pattern. I'll show the singleton because it's simple to demonstrate, although used wrongly it will get you in sticky situations:

Code: Select all

class FirstLoaded {
  private static $_instance = null;

  private function __construct() {} //So it can't be instantiated publically

  public static function getInstance() {
    if (self::$_instance === null) self::$_instance = new self();
    return self::$_instance;
  }
  
  public function test() {
  }
}

class SecondLoaded {
  public function __construct() {
    $firstLoaded = FirstLoaded::getInstance();
    $firstLoaded->test();
  }
}

$firstLoaded = FirstLoaded::getInstance();
$secondLoaded = new SecondLoaded();