How does PHP's spl_autoload_register resolve circular dependencies with require_once?
Circular dependencies can be resolved some cases, but not all. Let's start with an example of when it fails. Suppose we have three classes defined in separate files:
cat.php
class Cat extends Animal {}
animal.php
require_once('cat.php');
class Animal extends Creature {}
creature.php
class Creature {}
Let's say we also have a script that has an autoloader and creates an instance of Animal:
run.php
spl_autoload_register(function($className) {
require_once("$className.php");
});
$a = new Animal();
Running this script with "php run.php" will result in a PHP Fatal error:
PHP Fatal error: Class 'Animal' not found in .../Cat.php
I think this makes intuitive sense to me, because of the circular dependency between Animal and Cat:
Here are some modifications to ensure that we don't get a fatal
Questions:
The complete code (with some additional logging) from this examples can be found here
To resolve the circular dependency, you must break the loop by replacing the dynamic reference to the bucket resource.
A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.
In software engineering, a circular dependency is a relation between two or more modules which either directly or indirectly depend on each other to function properly. Such modules are also known as mutually recursive.
In my experience, the best way to deal with circular dependencies is to avoid them altogether. Circular dependencies are usually an indication of bad code design, and they should be refactored and removed if at all possible.
Since your autoloader does - what its name says - auto load your classes, you dont need any other require then the one in the autoloader function.
If you use require_once instead of require in it, it will still only load it once, no matter if you extending from it or just create an object.
So just use the code you posted in your question and remove the require_once() in your animal.php since the autoloader already requires it.
Side note: If you dont want to deal with creating your own autoloader, you could use the composer autoloader. Its easy to install and very useful, because it deals with sub directories and makes you follow a strict namespace convention.
If you want to do so, you need to install composer first. Then, you create a file called composer.json in your base directory with following content
{
"autoload": {
"psr-4": { "YourProject\\": "src/" }
}
}
You then need to execute following command in your command line:
cd path/to/your/project
composer dump-autoload
If you have done it put your classes in basedirectory/src
Note that you now have to give all classes a namespace, in this case if would be namespace YourProject
. You are finally done!
Now go in your base directory and create a file, lets call it index.php:
require_once ('vendor/autoloader.php');
$a = new YourProject\Animal();
Sorry for long side note, sir!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With