Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GitHub repository autoloading with Composer issue

I got PHP Fatal error: Class 'sendwithus\sendwithus_php\lib\API' not found

composer.json:

{
    "repositories": {
        "sendwithus_php": {
            "type": "package",
            "package": {
                "name": "sendwithus/sendwithus_php",
                "version": "1.0.3",
                "source": {
                    "url": "https://github.com/sendwithus/sendwithus_php",
                    "type": "git",
                    "reference": "0dfed56"
                }
            }
        }
    },
    "require": {
        "sendwithus/sendwithus_php": ">=1.0.3"
    }, "autoload": {
        "psr-0": {
            "Foo\\": "src/",
            "sendwithus\\": "vendor/sendwithus/sendwithus_php/lib"  
        }
    }, "minimum-stability" : "dev"
}

test.php:

use sendwithus\sendwithus_php\lib\API;

require_once 'vendor/autoload.php';

$api = new API('KEY');

What am I doing wrong?

like image 524
Roman Newaza Avatar asked Jan 13 '23 02:01

Roman Newaza


1 Answers

There is a bunch of stuff going wrong in your case. I'll try to correct it as well as I can.

First I took a look at the library you are requiring. It is public on Github, and it has a composer.json file that has errors.

{
    "name": "sendwithus/api",
    "version": "1.0.3",
    "require": {},
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/sendwithus/sendwithus_php"
        }
    ]
}

These infos are slightly wrong. Only the name is correctly formatted.

  • There shouldn't be a version. Versions are detected by tagging the code in git.
  • If nothing is required, that key can be omitted.
  • The current repository URL shouldn't be included in it's own repository.
  • Mentioning a license would be nice - currently everybody using this library should be scared about violating copyright.
  • The important, but missing info: How is autoloading configured?

Investigating the contents of that repository quickly reveals that it does not conform to PSR-0, so the only viable alternativ is classmap autoloading - which is sufficient enough because there are only two files in the lib folder.

A correct autoloading definition would be:

    "autoload": {
        "classmap": ["lib"]
    }

Details on how to construct this are in http://getcomposer.org/doc/04-schema.md#classmap Effectively, the value for the classmap key is a list of directories relative to the repository root directory that should be indexed.

The test folder need not be mentioned here. Using PHPUnit, that folder would be scanned for any file containing test classes. The test bootstrap should include the vendor/autoload.php file generated by Composer.

I don't know if the OP is responsible for this repository or can change it. This info above should be implemented in the repository itself, but it is also helpful if it cannot, because it can also go into a "package" definition.

So now we are going to look at the mentioned composer.json of the OP:

{
    "repositories": {
        "sendwithus_php": {
            "type": "package",
            "package": {
                "name": "sendwithus/sendwithus_php",
                "version": "1.0.3",
                "source": {
                    "url": "https://github.com/sendwithus/sendwithus_php",
                    "type": "git",
                    "reference": "0dfed56"
                }
            }
        }
    },
    "require": {
        "sendwithus/sendwithus_php": ">=1.0.3"
    }, "autoload": {
        "psr-0": {
            "Foo\\": "src/",
            "sendwithus\\": "vendor/sendwithus/sendwithus_php/lib"  
        }
    }, 
    "minimum-stability" : "dev"
}

The "repositories" key can contain objects that are of type "package" that contain all the necessary info of a project that fails to do so, or fails to do correctly. As I mentioned, the autoloading is broken in the original definition, so it must be fixed here:

        "sendwithus_php": {
            "type": "package",
            "package": {
                "name": "sendwithus/api",
                "version": "1.0.3",
                "source": {
                    "url": "https://github.com/sendwithus/sendwithus_php",
                    "type": "git",
                    "reference": "0dfed56"
                },
                "autoload": {
                    "classmap": ["lib"]
                } 
            }
        }

This would correctly reference that repository and enable autoloading. Note that the name has changed here to the original - it would probably trigger trouble if this library is known under two different names (one defined here, and the other in the original repository), but using the same namespace and class names.

Now that the repository info is fixed, all other things work as usual in composer.json.

"require": {
    "sendwithus/api": "1.0.3"
}, 
"autoload": {
    "psr-0": {
        "Foo\\": "src/"
    }
}, 
"minimum-stability" : "dev"

Note that the autoloading defined here is for THIS library or application only. Do not include the autoloading of the dependencies here!

And then we take care of your code:

use sendwithus\sendwithus_php\lib\API;

require_once 'vendor/autoload.php';

$api = new API('KEY');

The namespace is wrong. Don't use the name from Composer. Use the name from the code you are importing. This is correct:

require_once __DIR__ . "../vendor/autoload.php";

use sendwithus\API;

$api = new API("apikey");

Note that you cannot change the namespace of the library with a rename in Composer. Composer only downloads the PHP source files for you, it does not change the code inside the files.

My final composer.json file is this:

{
    "repositories": {
        "sendwithus_php": {
            "type": "package",
            "package": {
                "name": "sendwithus/api",
                "version": "1.0.3",
                "source": {
                    "url": "https://github.com/sendwithus/sendwithus_php",
                    "type": "git",
                    "reference": "0dfed56"
                },
                "autoload": {
                    "classmap": ["lib"]
                }
            }
        }
    },
    "require": {
        "sendwithus/api": "1.0.3",
    },
    "autoload": {
        "psr-0": {
            "Foo\\": "src/"
        }
    },
    "minimum-stability": "dev"
}
like image 178
Sven Avatar answered Jan 18 '23 10:01

Sven