3
votes

Yes another question about the "class not found" error. Either I am missing something, or I misunderstood the PSR-4 logic.

My composer library directory sturcture:

"Scanner" => "src" => "Test.php"

Test.php

namespace MyNS;

class Test
{
}

composer.json

"autoload": {
        "psr-4": {
            "MyNS\\": "src/"
        },
}

So, now I load the library in my project with composer and try using it.

require_once("../vendor/autoload.php");

$test = new MyNS\Test();

Which always results in

"Fatal error: Uncaught Error: Class 'MyNS\Test' not found."

. What am I missing? I am staring at this for days now. I have changed folders, I have changed folder names, I have changed uppper to lower and vise versa. Nothing seems to work.

I am using PHP 7.2.2 and Composer version 1.2.2

Even tried this:

require_once("../vendor/autoload.php");

use MyNS\Test;

$scanner = new Test();

Update

I debugt the Composer ClassLoader.php file (findFileWithExtension($class, $ext)) method and apparently my files are never loaded because I get put an echo "Done" and a die(); at the end of this method which means the file is not found and thus not loaded. What is wrong with my composer.json?

{
    "name": "test/test",
    "type": "library",
    "description": "",
    "keywords": ["php"],
    "homepage": "",
    "license": "MIT",
    "authors": [
        {
            "name": "",
            "email": "",
            "homepage": "",
            "role": ""
        }
    ],
    "require": {
        "php": ">=7.2.2"
    },
    "autoload": {
        "psr-4": {
            "MyNS\\": "src/"
        }
    }
}
2
Looking at the provided namespace, your path should be src/PSR4/ and not src/ and the namespace of class Test is MyNS\PSR4 and not MyNS alone.revo
I removed PSR4 in the namespace (as mentioned) . Not working. I also moved Test.php to folder src/PSR4 and left namespace in tackt. Still not working.Digital Human
Did you do composer dump-autoload after making changes?revo
It feels like that the autoloader isn't working at all. It doesn't seem to make a difference what names I use, what folders I use. I tried removing namespaces in both the classes and the composer.json. Even that didn't work. It still returns 'Class not found'.Digital Human
@revo yes everytime. Is there a way to debug what 'autoload' is exactly doing? In what folder it looks for what files for example?Digital Human

2 Answers

3
votes

To debug what is happening open ClassLoader.php file then go where findFileWithExtension() method is defined to add an echo statement:

# vendor/composer/ClassLoader.php:386

foreach ($this->prefixDirsPsr4[$search] as $dir) {
    if (file_exists($file = $dir . $pathEnd)) {
        return $file;
    }
    // Add this line
    echo $file, PHP_EOL;
}

Do not do composer dumpautoload after you manually modified above file until we are done.

Now by executing your PHP file you will see something similar to this at the very beginning of output:

path/to/project/vendor/composer/../../src/Test.php

Which is:

path/to/project/src/Test.php

So this is the file that composer is looking for and should contain something like this:

namespace MyNS;

class Test { }

If there is an issue in including the file then it means you have to care about three things:

  1. Path and filename
  2. Namespace used in file
  3. Class name used in file (class name should be the same as filename)
0
votes

i think the problem is in your namespace declaration

you calling the class from MyNS but class namespace is namespace MyNS\PSR4;

require_once("../vendor/autoload.php");

$test = new MyNS\Test();

// it should be new MyNS\PSR4\Test();

and make sure, your class file in same directory which you mentioned in composer autoload file

also you have to run dump-autoload command for any change in classnames

you can visit for this autoload feature