I have trouble instantiating class by path in my PSR-0
autoloaded project. Structure is as follows:
| - src/
| - Models/
| - My_New_Model_Migration.php
| - ...
| SeederCommand.php
| - vendor/
| - ...
| composer.json
And Composer autoloader:
"autoload": {
"psr-0": {
"" : [
"src/"
]
}
}
Not to get to much in SeederCommand
class, it is basically a Doctrine/migrations class which is supposed to create a migration with up()
and down()
methods.
Inside the function responsible for generating those I have this part:
if (file_exists(__DIR__ . "/Models/{$model}_Migration.php")) {
$class = "{$model}_Migration";
$instantiated = new $class;
....
}
When echoing I notice that file indeed does exist, so this part is working as it should. When newing up the class however I am getting an error:
PHP Fatal error: Uncaught Error: Class
‘/var/www/html/…/src/Models/My_New_Model_Migration.php’ not found in
/var/www/html/…/src/SeederCommand.php:97
Since paths are correct, I presume the issue must be in way a PSR-0
autoloader works by parsing paths by underscore?
Is there some way around it?
EDIT:
This answer doesn’t help me as it explains the ‘why’ of the autoloader story. I know how both PSR-0
and PSR-4
autoloaders work on the high level. I would like a way around the fact that autoloader wants a directory structure where there is none (and I don’t want it introduced in this case).
EDIT2:
SeederCommand
class requires autoload file:
require "../vendor/autoload.php";
I’ve tried doing a dump-autoload
and renaming class to one without underscores and same thing happens, so I might have done something wrong with autoloading itself.
EDIT3:
I have tried newing up a class I renamed to a non-underscore version. For example newing up MyNewClass
works, but My_New_Class
throws an error.
2
Answers
Error while creating instance of new class
This is wrong because you cannot create an instance of a class by its file name like:
Instead you need to use the class name and namespace:
So in your specific case it could be something like
PSR-0 and underscores
After reading the PSR-0 Standard again, I honestly think there is no way to achieve what you want (having a class name with underscore but no directory for it) while using PSR-0. The standard explicitly states:
Possible solution: Classmap autoloader
But you could use composer’s classmap autoloader for those files instead:
It could maybe look like that (but I was not able to test it):
You cannot have underscores in your classname, and not have them in the directory structure.
If your class is named
Models_MyWhatever_Migration
, because you dynamically add the string “MyWhatever” to the classname during migration, that class MUST be placed insrc/Models/MyWhatever/Migration.php
. You cannot have it insrc/Models/MyWhatever_Migration.php
.If you want to keep the underscore as part of the filename, you have to switch to PSR-4 and use namespaces.