Composer is a package manager for php. Just like bundler for ruby or npm for node it tries to manage packages and their dependencies.

Composer will be installed as a phar - a php executable. We start with the composer.json by running

composer init
# or
composer create-project vendor/package

On composer init you will be asked some questions and after a view questions you may start search/adding dependencies for your app (require) and for development (require-dev). On composer create-project you will download usually a framework or cms with basic dependencies. In any way, we will end up with a json file called composer.json.

We can add addtional packages with:

# for require
composer require vendor/package
# for require-dev
composer require --dev vendor/package
# or with specific version
composer require vendor/package:1.0

If we look into the composer.json now, we will see under require the newly added packages with a ^ in front of the version. The ^ is the caret version constraint. If we run:

composer update

It will check for new package updates but with the caret constraint only for patch or minor versions. There are several other constraint types. Besides the caret constraint, the most common ones are ~ or *. Tilde is very similar to caret and with star, you can specify if you just want only patches “1.1.*” or every update with just “*”. But it is also possible to use git commit ids “dev-master#2633721877cae79ad461f3ca06f3f77fb4fce02e” or git tags/branches. With hyphen you allow everything between specific versions and with operators such as >, >=, <, <= everything greater or lower, equals.

If we want to update a single package:

composer update vendor/package --with-dependencies

It will update a single package with dependencies as long other dependencies from other packages won’t create dependency conflicts. If some other packages preventing the update process you may want to use:

composer why vendor/package
composer why-not vendor/package

The why command executed with the dependency package is often used to check which other requirement using the same dependency. Most of the time this requirement needs to be updated too. The why-not command shows which other requirement is blocking the update.

By default, composer searches on https://packagist.org/ and will download the package and their dependencies under the folder vendor. Packagist.org is called a repository and provides an api. Most of the bigger projects have their own repositories just like Wordpress, Drupal, Typo3. Depending on the community it may be an unofficial one. It is also possible to provide your own repository.

{
	"repositories": [
		{
			"type": "composer",
			"url": "https://mycustomrepository.org"
		},
        ...
    ]
}


You will notice another file that has been created, the composer.lock file. This will hold every package that needs to be installed. If you transfer this project you may want to skip the computational stuff of negotiating the dependencies and just want to download the packages. This file does that. It is bigger then the composer.json because it contains every necessary package down to the current git commit (if it has one) not only your requirements. For quick deployment, this file should be committed too.

Before and after each command events will be triggered. It is possible to run different tasks on these events. By defining them in the composer.json.

{
	"scripts": {
        "post-update-cmd": "vendor\\package\\Class::somePHPScript",
        "post-package-install": [
        	"sh scripts/someRandomScript.sh"
        ],
    }
}

These scripts can be in php, shell or any other script-language running in your cli. It also possible to define a single task or multiple tasks in an array.

Depending on your needs, you want to alter the destination paths for your packages or binaries. Every binary installed via package should be symlinked into the composer bin directory.

"config": {
	"vendor-dir": "custom-vendor-path", # default: vendor
	"bin-dir":  "bin" # default: vendor/bin
}

It is possible too for altering paths of specific packages or package types.

 "extra": {
	"installer-paths": {
		"web/modules/{$name}": ["vendor/package"],
		"web/libraries/{$name}": ["type:library"]
	}
}

On top of repositories, custom packages can be defined under repositories too. It does not have to be git. It may be a zip or a tar.

{
	"repositories": [
        ...
		{
			"type": "package",
			"package": {
				"name": "customvendor/foopackage",
				"version": "1.0.0",
				"type": "library",
				"source": {
					"type": "git",
					"url": "https://github.com/customvendor/foopackage.git",
					"reference": "master"
				}
				"require": {
					"customvendor/additionalDependencies"
				}
			}
		}
    ],
    "require": {
		"customvendor/foopackage":"1.0.0"
    }
}



Composer helps with autoloading all your packages. It generates an autoloader which automatically loads required files for your application session.

<?php

require './vendor/autoload.php';

\vendor\package\Class::somePHPScript();

Check out the ./vendor/composer folder. Depending on the standard that will be used by the packages it will generate several files for loading each class. Our custom code may load as well by defining autoload in the composer.json.

{
  "autoload": {
		"psr-4": {
			"App\\" : "folder"
		},
		"psr-0": {
			"App\\" : "folder"
		},
		"classmap": {
			"App\\" : "folder"
		}
  	}
}

The major downside for classmap is, that for every new class you need to regenerate the autoloader files with composer dump-autoload.

Composer is on top of all these features extendable. Here is a list of plugins. Depending on your project you prefer the one over the other plugin. Prestissimo for example is a nice plugin, that creates multiple downloads at once. But maybe incompatible with custom download plugins.