skip to Main Content

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


  1. Error while creating instance of new class

    $class = __DIR__ . "/Models/{$model}_Migration.php";
    $instantiated = new $class;
    

    This is wrong because you cannot create an instance of a class by its file name like:

    $instance = new /var/www/html/.../Class.php; // <-- wrong
    

    Instead you need to use the class name and namespace:

    $instance = new ProjectNamespaceClass;
    

    So in your specific case it could be something like

    $class = "\Project\Models\".$model."_Migration";
    // ^ depends on the real namespace and name of your migration classes
    $instantiated = new $class;
    

    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:

    Each _ character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR.

    Possible solution: Classmap autoloader

    But you could use composer’s classmap autoloader for those files instead:

    This map is built by scanning for classes in all .php and .inc files in the given directories/files. You can use the classmap generation support to define autoloading for all libraries that do not follow PSR-0/4. To configure this you specify all directories or files to search for classes.

    It could maybe look like that (but I was not able to test it):

    "autoload": {
        "psr-0": {
            "" : [
                "src/"
            ]
        },
        "classmap": ["src/Models/"]
    }
    
    Login or Signup to reply.
  2. 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 in src/Models/MyWhatever/Migration.php. You cannot have it in src/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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search