tags:

views:

462

answers:

2

This doesn't work:

test.php:

include_once('test-include.php');  

$main = new mainClass();

//======================================================================
class mainClass { 
   function __construct() {
      $test2 = new Test2();
      echo $test2->var;
   }
}

//======================================================================
class Test2 extends Test1 { // test2
  var $var = 'b';
}

test-include.php:

// this does get printed out, so I know the include statement is working
echo 'DEBUG: this is the test-include.php file<br>'; 

//======================================================================
class Test1 { // test1
  var $var = 'a';
}

It gives the following error

PHP Fatal error:  Class 'Test2' not found in /path/to/test.php on line 8

whereas this does work

test2.php:

// this is in the same position as the include statement in test.php
//======================================================================
class Test1 { // test1
  var $var = 'a';
}

$main = new mainClass();

//======================================================================
class mainClass { 
   function __construct() {
      $test2 = new Test2();
      echo $test2->var;
 }
}

//======================================================================
class Test2 extends Test1 { // test2
  var $var = 'b';
}

Why does putting the Base class (Test1) in an include file cause the child class that is extending it to not be found? In other words, the first example is failing because it can't find Test2 when we attempt to instantiate it. This kind of makes sense as we haven't gotten to Test2 in the code execution flow yet. However, in the second example (without the include statement) there's no error, even though it's a similar situation (we haven't reached the Test2 class in code execution yet)

Oh, and this is under version 5.1.6.

UPDATE:

OK, Daff is correct - if I move

$main = new mainClass();

to the end in the test.php example, it works. I would still like to know why it doesn't work if the above line isn't at the end - it works just fine in the test2.php example which doesn't have the $main = new mainClass() line at the end.

UPDATE 2:

OK, I've tried using require, require_once and include in place of include_once - none of these work. And I also added a test echo statement to the test-include.php file and it gets printed out (plus I don't get an error about a non-existent include file) so I know the include statement is working.

+1  A: 

This should have something to do with the definition order and that EVERY class should be included before you actually work with them. If you put the call of

$main = new mainClass();

At the end of your script it works fine even with the include file because all the classes are defined already. Eventually you should have a look at the PHP autoload function because you will get rid of these problem with one small function.

Daff
I think part of the question is the class definition order is the same in both examples, but one works and the other doesn't.
Alan Storm
Yep, Alan is correct and I've modified test2.php (and tested it) to put the base class (Test1) in the same place as the include statement is in test.php - test2.php still works in this case, so it's not an order issue unless PHP includes don't work the way I thought they did (i.e., the code from the included file is inserted where the include statement was).
Bill
Ok definition order is the better word for it. I still recommend autoloading or at least including all class files before any processing begins.
Daff
Yep, I think that's what I'm going to do - thanks Daff!
Bill
+1  A: 

OK, I think I may have figured this one out. According to this bug report:

http://bugs.php.net/bug.php?id=30453

PHP 4 allowed classes to be defined after they are used but for PHP 5, in the words of the end poster on the bug thread:

PHP5 supports it [declaring classes after they are used] for backward compatibility, but we don't plan support for all combinations.

So I'm guessing this particular case is one of those unsupported combinations.

Bill