Cinan's world

GNU/Linux & free software, howtos, web development, scripts and other geek stuff

Dependency Management in PHP Projects #2

In the last article about dependency management I’ve explained why we, PHP programmers, need composer and why you should use it in your PHP projects.

Let’s dig deeper in composer internals.

Where can I find packages for composer?

Many of packages which we can use as project dependencies can be found on packagist.

Dependency versioning

Let’s say our project depends on Twig library. The require section in composer.json file will look like this:

1
2
3
 "require": {
        "twig/twig": "1.12.*"
    }

The file says we want Twig version at least 1.12.0. Composer will install the newest minor version (e.g. 1.12.1 or 1.12.3) of major version 1.12. We’ll never get Twig 1.11 or Twig 1.13 or Twig 2.0.

We can define an exact version of Twig like this: "twig/twig": "1.12.1".

Maybe we want any newest development version. It’s simple: "twig/twig": "dev-master". Now composer will install newest bleeding-edge version from master branch from Twig’s Git repository. The used schema is: dev-<branch>.

Using custom dependencies

If you have your own libraries you want to use in a project, add repositories section to the composer.json. It contains array of VCS repositories.

Let’s say you want to use a library hosted on github. Then the repositories section can look like this:

1
2
3
4
5
6
 "repositories": [
      {
          "type": "git",
          "url": "https://github.com/vendor/example.git"
      }
  ]

In type field we said it’s a Git repository and an address of the repository is defined in url field.

Then, you can edit the require section:

1
2
3
4
 "require": {
      "twig/twig": "1.12.*",
      "vendor/example": "dev-master"
  }

Now composer update will fetch code of “example” library from https://github.com/vendor/example.git repository.

How my project knows about installed dependencies?

Composer creates autoload.php file in vendor directory. The file takes care of dynamic autoloading of all dependencies. Dynamic means all required files are loaded when they are needed. If we had defined 20 dependencies, it would be very inefficient and slow to load all files.

When some dependency class is used for the first time, composer’s Autoloader gets called and tries to find and load needed files.

I believe an example below enlightens the question. All you need to do is to include autoload.php file in your project.

index.php
1
2
3
4
5
6
7
8
9
10
11
12
  <?php
  
  // load autoload.php
  require 'vendor/autoload.php';
  
  // how many files has been loaded so far
  echo "Number of loaded files: " . count(get_included_files()) . "\n";

  // can use Twig class
  $loader = new Twig_Loader_String();
  
  echo "Number of loaded files: " . count(get_included_files()) . "\n";

The example is very simple, I just wanted to show dependency autoloading just works. By the way, the output is:

Number of loaded files: 6
Number of loaded files: 9

First time a counter was called there were loaded only composer files. Next time composer loaded more files required by Twig.

Very interesting topic about autoloading of your own code is explained on composer official guide.

This article was also published on my school blog.

Comments