PHP and circular dependencies
Today I noticed the strangest bug in PHP. Apparently there's a problem with circular dependencies and interfaces.
This is how the problem occurs:
<?php
// this is class1.php
require_once 'iclass.php';
class class1 implements iclass {
}
?>
<?php
// this is class2.php
require_once 'class1.php';
class class2 extends class1 {
}
?>
<?php
// this is iclass.php
require_once 'class2.php';
interface iclass {
function setSomething(class2 $object);
}
?>
Now, if you run class1.php, you will get the following error:
Fatal error: Class 'class1' not found in /home/filemobile/testscript/class2.php on line 5
I know this is not proper OOP, but its still a strange error. Normally PHP is pretty good at these weird structures ;). Weirdest thing was that it happened for me on one server, but not the other.
There is a bug marked bogus for this, which is understandable. It would be great though if the PHP could somehow throw an error thats a bit more helpful =P. Its a strange error, especially since I could only reproduce it with this structure, and not with for example just 2 classes with circular dependencies.
Comments
Richard Thomas •
None of your files load class2.php so unless you run class2.php your out of luck, since the other 2 classes to "cross load" you would be fine if you run class2.phpGregory Beaver •
Actually, your code is buggy. You do not need the require_once in iclass.php, it works just fine without it, and then you don't get any error (except the missing abstract method in class1)Alternately, if you're feeling particularly anal about documenting requirements, you could move the require_once to the end of the file like so:
// this is iclass.php
interface iclass {
function setSomething(class1 $object);
}
require_once 'class1.php';
?>
Richard's comment is incorrect, class2.php does not solve anything, because the loading conflict still exists in class1.php.
So in short, there's no bug in PHP at all.
Evert •
my example code was wrong (thats what you get from re-typing, without testing)The interface now makes use of class2 instead of class1.
You were also right about not requireing that other class at all. I guess I made a habit out of using require_once whenever I use a class. Quite surprised it wasn't needed here..
Oh well.. I got rid of this circular dependency anyway.. Its not good practice to start with =)
Thanks for your comments
John Brynte Turesson •
I discovered I had the same circular dependency problem by logging the array returned from `get_declared_classes()` (http://php.net/manual/en/fu.... At least the horrible error digging made me realise that my code structure was bad :)