Composer Usage Tips

Composer is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will install and update them for you. We will learn:

  • how to install Composer
  • how to use it in a new or existing project

Installation

Composer is an executable .phar file that you download and install as follows.

Windows

Use the official installer Composer-Setup.exe.

Linux, macOS

All you need is 4 commands, which you can copy from this page.

Furthermore, by copying it into a folder that is in the system's PATH, Composer becomes globally accessible:

$ mv ./composer.phar ~/bin/composer # or /usr/local/bin/composer

Use in Project

To start using Composer in your project, all you need is a composer.json file. This file describes the dependencies of your project and may also contain other metadata. The simplest composer.json can look like this:

{
	"require": {
		"nette/database": "^3.0"
	}
}

We're saying here that our application (or library) requires the package nette/database (the package name consists of a vendor name and the project's name) and it wants a version that matches the ^3.0 version constraint (i.e., the latest version 3).

So, with the composer.json file in the project root, run:

composer update

Composer will download Nette Database into the vendor/ directory. It also creates a composer.lock file, which contains information about exactly which library versions it installed.

Composer generates a vendor/autoload.php file. You can simply include this file and start using the libraries' classes without any extra work:

require __DIR__ . '/vendor/autoload.php';

$db = new Nette\Database\Connection('sqlite::memory:');

Update Packages to the Latest Versions

To update the used libraries to the latest versions according to the constraints defined in composer.json, use the composer update command. For example, with the dependency "nette/database": "^3.0", it will install the latest 3.x.x version, but not version 4.

To update the constraints in the composer.json file, for example to "nette/database": "^4.1", allowing the installation of the latest version, use the composer require nette/database command.

To update all used Nette packages, you would need to list them all on the command line, e.g.:

composer require nette/application nette/forms latte/latte tracy/tracy ...

This is impractical. Therefore, use the simple script Composer Frontline that will do it for you:

php composer-frontline.php

Creating New Project

You can create a new Nette project using a single command:

composer create-project nette/web-project name-of-the-project

Replace name-of-the-project with the directory name for your project and execute the command. Composer will download the nette/web-project repository from GitHub, which already contains a composer.json file, and then install the Nette Framework itself. All that remains is to set directory permissions for the temp/ and log/ directories, and the project should be live.

If you know which PHP version your project will be hosted on, be sure to set it.

PHP Version

Composer always installs package versions compatible with the PHP version you are currently using (specifically, the PHP version used on the command line when running Composer). This might not be the same version your web host uses. Therefore, it's crucial to add information about the PHP version on your hosting to the composer.json file. Then, only package versions compatible with the host will be installed.

For example, to specify that the project will run on PHP 8.2.3, use the command:

composer config platform.php 8.2.3

The version will be written to the composer.json file like this:

{
	"config": {
		"platform": {
			"php": "8.2.3"
		}
	}
}

However, the PHP version number is also specified elsewhere in the file, in the require section. While the first number determines the version for which packages are installed, the second number indicates the version the application itself is written for. For example, PhpStorm uses this to set the PHP language level. (Of course, it doesn't make sense for these versions to differ, so the double entry is an oversight.) Set this version using the command:

composer require php 8.2.3 --no-update

Or directly in the composer.json file:

{
	"require": {
		"php": "8.2.3"
	}
}

Ignoring PHP Version

Packages typically specify both the lowest PHP version they are compatible with and the highest version they have been tested against. If you intend to use an even newer PHP version, perhaps for testing, Composer will refuse to install such a package. The solution is the --ignore-platform-req=php+ option, which makes Composer ignore the upper limits of the required PHP version.

False Reports

When upgrading packages or changing version numbers, conflicts sometimes occur. One package has requirements that conflict with another, and so on. However, Composer sometimes outputs false reports. It reports a conflict that doesn't actually exist. In such cases, deleting the composer.lock file and trying again can help.

If the error message persists, it is genuine, and you need to read it to understand what to modify and how.

Packagist.org – Global Repository

Packagist is the main repository where Composer searches for packages by default. You can also publish your own packages here.

What If We Don’t Want the Central Repository

If we have internal applications or libraries within our company that cannot be hosted publicly, we can create our own repositories for them.

Read more about repositories in the official documentation.

Autoloading

A key feature of Composer is that it provides autoloading for all the classes it installs. You activate this by including the vendor/autoload.php file.

However, you can also use Composer to load other classes from outside the vendor/ directory. The first option is to let Composer scan defined directories and subdirectories, find all classes, and include them in the autoloader. To achieve this, set autoload > classmap in composer.json:

{
	"autoload": {
		"classmap": [
			"src/",      # includes the src/ directory and its subdirectories
		]
	}
}

Subsequently, you need to run the composer dumpautoload command after each change to regenerate the autoloading tables. This is extremely inconvenient. It's much better to entrust this task to RobotLoader, which performs the same activity automatically in the background and much faster.

The second option is to adhere to PSR-4. Simply put, it's a system where namespaces and class names correspond to the directory structure and file names, e.g., App\Core\RouterFactory will be located in the file /path/to/App/Core/RouterFactory.php. Configuration example:

{
	"autoload": {
		"psr-4": {
			"App\\": "app/"   # the App\ namespace is in the app/ directory
		}
	}
}

See the Composer documentation for details on how to configure this behavior.

Testing New Versions

Want to test a new development version of a package? Here's how. First, add this pair of options to your composer.json file. This allows installing development versions, but Composer will only resort to them if no stable version combination satisfies the requirements:

{
	"minimum-stability": "dev",
	"prefer-stable": true,
}

We also recommend deleting the composer.lock file, as Composer sometimes inexplicably refuses installation, and this can resolve the issue.

Let's say the package is nette/utils and the new version is 4.0. Install it using the command:

composer require nette/utils:4.0.x-dev

Or you can install a specific version, for example, 4.0.0-RC2:

composer require nette/utils:4.0.0-RC2

However, if another package depends on the library and is locked to an older version (e.g., ^3.1), the ideal solution is to update that dependent package to work with the new version. But if you just want to bypass the restriction and force Composer to install the development version while pretending it's an older version (e.g., 3.1.6), you can use the as keyword:

composer require nette/utils "4.0.x-dev as 3.1.6"

Calling Commands

You can call your own predefined commands and scripts via Composer as if they were native Composer commands. For scripts located in the vendor/bin directory, you don't need to specify this path.

As an example, let's define a script in composer.json that uses Nette Tester to run tests:

{
	"scripts": {
		"tester": "tester tests -s"
	}
}

We then run the tests using composer tester. You can call the command even if you are not in the project's root directory, but in one of its subdirectories.

Send Thanks

We'll show you a trick to please open source authors. You can easily give stars on GitHub to the libraries your project uses. Simply install the symfony/thanks library:

composer global require symfony/thanks

And then run:

composer thanks

Try it!

Configuration

Composer is closely integrated with the version control tool Git. If you don't have Git installed, you need to tell Composer not to use it:

composer -g config preferred-install dist