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
How to Easily Switch Between PHP Versions on MAC Osx
How to Make Pdo Run Set Names Utf8 Each Time I Connect, in Zendframework
Verify Imagemagick Installation
When Should I Declare Variables in a PHP Class
Merge 'With' and 'Wherehas' in Laravel 5
Ajax Call with Contenttype: 'Application/JSON' Not Working
How to Check If a String Is One of the Known Values
PHP File Upload, How to Restrict File Upload Type
Sanitizing User's Data in Get by PHP
Disabling Strict Standards in PHP 5.4
Type Casting for User Defined Objects
Relative Path Not Working in Cron PHP Script
Create an Encrypted Zip Archive with PHP