Composer behind the scene

Almost all modern PHP frameworks rely on Composer.

The idea is to have PHP libraries and packages you can reuse through a unique dependency manager.

Composer is ridiculously easy to install, and once you have it on your local machine, you can start using it.

Permalink to heading Why should I use it? Why should I use it?

The key concept is “reuse”. With Composer, you get access to an extensive range of standardized packages. This way, you don’t reinvent the wheel, and you can easily manage all dependencies.

Autoloading is also one of the killer features of Composer. Instead of doing this:

$root_dir = "/path/to/root_folder";
require $root_dir . "/lib/mylib.php";
require $root_dir . "/lib/mylib2.php";
require $root_dir . "/lib/mylib3.php";

You call only one file, vendor/autoload.php:

require $root_dir . "/vendor/autoload.php";

No more includes/requires at the beginning of each script. Besides, Composer has a smarter way to load classes. Thanks to an internal mapping, it only loads necessary files.

Permalink to heading Quick installation Quick installation

Please follow instructions here: for Mac and Linux.

For Windows, it’s a little bit different: see instruction

Then run the following command on your terminal:

composer -v

it gives you the specific version of Composer you just installed.

Permalink to heading First Composer init First Composer init

Composer gives you a useful command to get started:

composer init

It guides you with some prompts. The typical scenario might look like that:

Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

Package name (/) [julien/test]:

Description []:

Author [Julien Maury, n to skip]:

Minimum Stability []:

Package Type (e.g. library, project, metapackage, composer-plugin) []:

With those details, Composer will initialize your project and your dependencies. You will get a new vendor directory where Composer downloads all packages and two files called composer.json and composer.lock.

If you open the composer.json file, you may see something like:

  "name": "julien/test",
  "require": {
    "stripe/stripe-php": "^7.37"
  "authors": [
      "name": "Julien Maury",
      "email": ""

In my example, Composer puts the Stripe package in the vendor directory. I can now use the Stripe package in my code:

require $root_dir . '/vendor/autoload.php';
$stripe = new \Stripe\StripeClient("MYSECRETKEY");

Simple as that!

Permalink to heading Where to find packages? Where to find packages?

The most popular place is packagist, but you can add any repository provided it has a composer.json file.

You have to declare source repositories if it’s not from For example:

  "repositories": [
      "type": "vcs",
      "url": ""
  "require": {
    "monolog/monolog": "dev-bugfix"

Permalink to heading Composer goes way beyond that Composer goes way beyond that

Composer is not only a great dependency manager. It solves problems. Thanks to its internal mapping system (a class loader), it only loads necessary files, so if you have several packages, it does not load all packages on every single request.

It’s reverse logic. If you need to use a class in your vendors, use it, and Composer will look into the vendors and load it for you.

You can control the way Composer autoloads your classes thanks to theautoload setting in the composer.json file:

"autoload": {
 "classmap": [

With this basic rule, you tell Composer to autoload classes in the folder src/myclasses/, but indeed you can fine-tune it a little bit more…

Permalink to heading PSR PSR

PSR stands for PHP Standards Recommendations. Composer allows for easily using those standards when autoloading, so it solves another problem.

Instead of using a genericclassmap you can use a more specific sets of rulles such as “psr-4”:

"autoload": {
    "psr-4": {
      "App\\": "src/"

What’s the point? With those PSR-4 rules, you have to follow some standards to name your files and namespaces/sub-namespaces. Here we have an App namespace in the src folder.

Because we are using PSR-4, if we want to create the class App\Repository\MyRepository, the file path must be src/Repository/MyRepository.php. Composer resolves the path from the namespace.

Permalink to heading Running commands vs. editing files Running commands vs. editing files

Composer comes with a set of useful commands you can use to add/remove dependencies.

To add a package, you can either edit the composer.json file and add your dependency in the require section, or run in your terminal something like:

composer require stripe/stripe-php

To remove this package, run:

composer remove stripe/stripe-php

I recommend using command lines, especially for removing stuff.

Permalink to heading Optimizing autoload Optimizing autoload

Autoloading is a powerful feature, but you can even go beyond by switching to an optimized autoload:

"config": {
    "optimize-autoloader": true

It improves performance by 30-40%. But how?

It spares a lot of filesystem checks. Known classes return their path instantly. Besides, if you enable opcache, it’s even faster!

Composer commands are a little bit slower with this configuration, though. It needs more time to optimize autoloading, but it’s palatable.

Permalink to heading The .lock file The .lock file

Every time you run a composer command, the .lock file is updated. When you run a composer init, this file is generated for the first time.

It saves the list of installed packages at a specific version and a hash of the composer.json file.

It’s essential for Composer. It makes sure that people get the same packages as when you developed the project.

Permalink to heading The create command The create command

You can use Composer to create projects. It’s excellent to start a new code based on some skeleton.

For example, for my WordPress projects, I appreciate the Bedrock approach. It’s still WordPress but entirely reconfigured to use Composer easily.

You can run the following command to test it:

composer create-project roots/bedrock my-project

Permalink to heading Configuration Configuration

In this section, I give configuration examples. It is not an exhausting list. Please check this page to see more options.

Permalink to heading Vendor dir Vendor dir

It’s possible to change the vendor folder with the vendor-dir config:

"config": {
    "vendor-dir": "the-source"

In your code, just load the new path:

require $root_dir . '/the-source/autoload.php';

Permalink to heading Sort packages Sort packages

Make sure, the following goes in your composer.json file in the config section:

"config": {
    "sort-packages": true

It sorts packages by name, very handy for maintenance.

Permalink to heading The platform configuration The platform configuration

The PHP version is vital. How can you be sure that all your dependencies are compatible with your PHP version in production?

The answer is the platform configuration in composer.json:

"config": {
    "platform": {
        "php": "7.2"

This way, all your dependencies will be updated accordingly.

Permalink to heading Pro tips and versioning Pro tips and versioning

Permalink to heading Always commit the composer.lock file Always commit the composer.lock file

It’s crucial to commit some files and to ignore some directories. I think you should always commit the composer.lock file.

Permalink to heading Don’t try to resolve git conflicts in the composer.lock file Don’t try to resolve git conflicts in the composer.lock file

This one is a classic error. In case you need to merge or rebase your work, the composer.lock file may have some conflicts. You mustn’t attempt to resolve conflicts manually. You would get a wrong version of the file that would trigger additional errors.

Instead, run:

composer update --lock

Then, stage the resulting composer.lock file (git add).

Note that you can add a simple line in the .gitattributes file to tell Git to skip this file when merging:

/composer.lock -merge

Permalink to heading Don’t put everything in the require section Don’t put everything in the require section

If you need to add dependencies only for debugging, testing, or something specific to your local machine, it’s good practice to add them as require-dev dependencies not require.

Whenever you require something, you can either use require or require --dev:

composer require --dev <vendor-name>/<package-name>

The difference is essential. You don’t want all the things in production, especially when it’s not necessary. Composer will separate dev dependencies from other dependencies with a specific section in the composer.json file:

"require-dev": {
    "phpunit/phpunit": "9.2.6",
    "mockery/mockery": "1.4.1"

If you run a composer install, then Composer will both dev and core dependencies. You can run a composer install --no-dev to prevent that behavior, it’s useful when preparing a release for production.

Permalink to heading update vs. install vs. dump-autoload command update vs. install vs. dump-autoload command

Permalink to heading dump-autoload dump-autoload

The most basic one. It specifically generates the autoload. The composer install command already includes it, so it’s unnecessary to run it after a composer installation.

Permalink to heading install install

It installs all dependencies, including external dependencies, and it generates the autoload.

Permalink to heading update update

It updates all packages. Alternatively, you can update only a specific package :

composer update stripe/stripe-php

Permalink to heading Extending Composer with hooks Extending Composer with hooks

For that, use the scripts section of the composer.json file. It gives you entry points to run some additional command (and even PHP scripts) on specific composer events such as installing, updating, or dump-autoload.

Please visit documentation. Their tutorial is extra good, nothing to add.

Note that you can call composer commands along with your custom scripts and commands.

For example, put the following in your composer.json file:

"scripts": {
    "test": [
        "@composer show",
        "ls -alh",
        "curl -I"

then run:

composer test

Permalink to heading Wrap up Wrap up

I hope you know a little more about Composer, why it’s useful, and how it works.

I do my best to update all my contents, but keep it mind that "Composer behind the scene" has been published many months ago.