Autoloading Classes in PHPunit Using Composer and Autoload.Php

Autoloading classes in PHPUnit using Composer and autoload.php

Well, at first. You need to tell the autoloader where to find the php file for a class. That's done by following the PSR-0 standard.

The best way is to use namespaces. The autoloader searches for a Acme/Tests/ReturningTest.php file when you requested a Acme\Tests\ReturningTest class. There are some great namespace tutorials out there, just search and read. Please note that namespacing is not something that came into PHP for autoloading, it's something that can be used for autoloading.

Composer comes with a standard PSR-0 autoloader (the one in vendor/autoload.php). In your case you want to tell the autoloader to search for files in the lib directory. Then when you use ReturningTest it will look for /lib/ReturningTest.php.

Add this to your composer.json:

{
...
"autoload": {
"psr-0": { "": "lib/" }
}
}

More information in the documentation.

Now the autoloader can find your classes you need to let PHPunit know there is a file to execute before running the tests: a bootstrap file. You can use the --bootstrap option to specify where the bootstrap file is located:

$ ./vendor/bin/phpunit tests --bootstrap vendor/autoload.php

However, it's nicer to use a PHPunit configuration file:

<!-- /phpunit.xml.dist -->
<?xml version="1.0" encoding="utf-8" ?>
<phpunit bootstrap="./vendor/autoload.php">

<testsuites>
<testsuite name="The project's test suite">
<directory>./tests</directory>
</testsuite>
</testsuites>

</phpunit>

Now, you can run the command and it will automatically detect the configuration file:

$ ./vendor/bin/phpunit

If you put the configuration file into another directory, you need to put the path to that directory in the command with the -c option.

Autoloading of classes through composer does not work

App.php are inside /core directory :

autoload": {
"psr-4": {
"App\\Controllers\\": "app/controllers",
"Xuborx\\Cms\\": "vendor/xuborx/cms/core"

}
}

Composer autoloader can't find PHPUnit when running tests

PHPUnit_Framework_TestCase does not exist in PHPUnit version 8, which is your minimum specified version. As of (I think) PHPUnit version 5, it's using namespaces, so your test case should be named \PHPUnit\Framework\TestCase.

You can downgrade your PHPUnit requirement to an older version, or (preferably) update your tests to meet the new naming style.

Why does class autoloading not work for a package required using repositories.package ?

Your problem is that by using a package key for that repository, you are telling composer "read the package information from here, do not read the hosted composer.json". And since the package settings are almost bare, dependencies are not resolved and autoloader not generated.

The only thing that happens is that composer clones the repo within your vendor, then you are on your own.

You could add an autoload section to your current package key, as shown here. This way you could at least have the autoloader correctly generated.

But note that recursive dependency resolution will not be dealt with, which might leave you with other issues.

For that you could replicate the require part of the original composer.json within the package setting... but this is not smart. The package key is meant for packages that do not support Composer, so you can force them into supporting it within your application. You'd end with something like this:

{
"repositories": [
{
"type": "package",
"package": {
"name": "mygitlab/ach-file",
"version": "1.2",
"type": "package",
"autoload": {
"psr-4": {
"RW\\": "src/"
}
},
"require": {
"ext-ssh2": "*",
"ext-bcmath": "*"
},
"source": {
"url": "https://mygitlab.ca/mygitlab/ach-file.git",
"type": "git",
"reference": "master"
}
}
}
],
"require": {
"mygitlab/ach-file": "*"
}
}

Frankly, I wouldn't recommend this for a forked composer package. If what you want is use a fork of an existing package, do not use the package key at all.

Simply add the repository configuration, and require the forked package by its original name (revenuewire/ach-file in this case). Replace the version by dev-master (or whatever branch you use to hold your fork), and voilà, everything will work as usual because the library will be required as a regular composer package.

{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/yivi/ach-file"
}
],
"require": {
"revenuewire/ach-file": "dev-master"
}
}

How to autoloading my classes alongside with composer autoloader?

You can add your own autoloader rules into the composer.json file in your project - this adds your own rules to the vendor/autoload.php file so that your own classes will load as well as the ones in the vendor/ directory. There's more information in the docs here: https://getcomposer.org/doc/04-schema.md#autoload. Take a look at the PSR-0 section to load classes from your two directories.

Try something like:

{
"autoload": {
"psr-0": { "": ["models/", "libraries"] }
}
}

If your classes are namespaced, then specify the namespaces as this will stop composer from looking for all classes in those directories.

Composer Auto-loading & PHPUnit

In your index.php you're not importing the right class:

use Models\Base;

$derp = new BaseModel();

You should import the Models\BaseModel class:

use Models\BaseModel;

$derp = new BaseModel();

Also, the file name should match the class name. The BaseModel class should be located in the framework/models/BaseModel.php file instead of framework/models/Base.php.

Note that you don't need to optimise the autoloader during development (that's what -o flag is doing). Only use it in production, otherwise you'll have to dump the autoloader each time you add a new class.

More about the autoloading standards can be read here:

  • http://www.php-fig.org/psr/psr-4/
  • http://www.php-fig.org/psr/psr-0/


Related Topics



Leave a reply



Submit