Everything under require is installed everywhere the project is installed, servers included. PHPUnit and the packages behind it are several dozen dependencies of code with no business existing under a document root, and require-dev is the line that keeps them out of it.
{
"require": {
"php": ">=5.4.0",
"monolog/monolog": "~1.5"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
"mockery/mockery": "0.8.*"
}
}
The deploy command is composer install --no-dev --prefer-dist --optimize-autoloader, and it is not interchangeable with a plain install: --no-dev skips the dev packages and regenerates the autoloader without them. composer.lock records both sets either way, so the lock file is identical on every machine and only the installed tree differs — which is the property that makes the split safe rather than merely tidy. The failure it prevents is not hypothetical: a bootstrap that quietly references a test double, or a route file left pointing at a fixture, breaks at deploy time. Running install --no-dev once on a development machine turns that into a five-minute discovery instead of a rollback.