By default, when you run
$ composer require some/package
Composer will ask packagist.org where it can find the some/package
package, (this is usually, but not always, a GitHub repo) Once composer knows where to find a package, it will download the package into your ./vendor
folder.
Packagist.org is a composer repository. However, it is not the only composer repository. Composer has a number of different repository types that allow you to tell composer to look for packages from other sources.
For example, if you’re a Magento 2 developer you’re probably familiar with repo.magento.com
— this authenticated repository is how Magento distributes its composer packages. When you create a new Magento 2 project, you add this repository to your configuration file via the --repository-url
option
% composer create-project --repository-url=https://repo.magento.com/ \
magento/project-community-edition \
<install-directory-name>
Composer also allows you to create “a repository of one package”. The most common example of this is the vcs
repository type. A vcs
repository allows you to tell composer “look at this git, mercurial, or svn repository for a package” by adding the following to your configuration.
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/astorm/monolog"
}
]
}
This tells composer the GitHub repository at https://github.com/astorm/monolog contains a composer package. Composer will check this repository’s composer.json
file when it’s looking for packages. In this particular case, a request to use monolog/monolog
% composer require monolog/monolog
would pull this package from https://github.com/astorm/monolog
instead of the source provided by packagist.org.
It may feel slightly overblown to call this a “repository” since it only contains a single package, but it works all the same.
Today we’re going to take a look at another “single package” repository type — the path
repository.
The Path Repository
Path repositories allow you to point at a directory on your computer and treat it as a composer repository. In addition to this, when composer installs a package from a path
repository is does not copy the files. Instead, it creates a symlink in your vendor folder to the path. This makes it ideal for working on a package that’s part of a larger system.
Let’s look at an example. The https://github.com/astorm/hello-path-repository
GitHub repository contain a composer package. Let’s clone this to our local system.
% git clone https://github.com/astorm/hello-path-repository
This package’s name is astorm/hello-path-repository
.
In a separate folder, let’s create a composer.json
file that tells composer the hello-path-repository
folder is a a path
repository.
% ls
hello-path-repository
% mkdir our-project
% cd our-project
% touch composer.json
With an empty composer.json
created, let’s add the path
repository configuration.
// File: composer.json
{
"repositories": [
{
"type": "path",
"url": "../hello-path-repository"
}
]
}
Now, with the above composer file in place, let’s require the astorm/hello-path-repository
package.
% composer require astorm/hello-path-repository
Using version ^1.0 for astorm/hello-path-repository
./composer.json has been updated
Running composer update astorm/hello-path-repository
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
- Locking astorm/hello-path-repository (1.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing astorm/hello-path-repository (1.0): Symlinking from ../hello-path-repository
Generating autoload files
If we look at our vendor folder,
% ls -l vendor/astorm
total 0
lrwxr-xr-x 1 astorm staff 30 May 17 09:58 \
hello-path-repository -> ../../../hello-path-repository
we’ll see that astorm/hello-path-repository
is now a symlink to our cloned repository.
% php vendor/astorm/hello-path-repository/hello.php
Hello World
That’s path
repositories. They let you point at a local folder on your computer and treat that folder as a single package composer repository.
Path Repositories and composer.lock
If you’re going to use path
repositories (or you’re going to use a project that uses them), you’ll need to be careful/aware of your composer.lock
file. Once you’ve generated a composer.lock
file, that file becomes the source of truth for where composer will download a package. If we look at the composer.lock
file generated by the above activity
/* ... */
"packages": [
{
"name": "astorm/hello-path-repository",
"version": "1.0",
"dist": {
"type": "path",
"url": "../hello-path-repository",
"reference": "2ecb421aee5132f7bdbb25d7d15f3c4d0bf81572"
},
/* ... */
],
/* ... */
we see it’s pointing to our ../hello-path-repository
path.
In our case, this isn’t a big deal since astorm/hello-path-repository
doesn’t exist at packagist.org. However, if it did and we’d installed with an invalid path
repository, composer will fall back to installing the package from packagist.org and then put that location in you lock file.
If you want a second chance at installing from your path
repository, you’ll need to remove your composer.lock
file. This can also complicate development if you want to use a path
repository with a project that distributes a composer.lock
file.
These gotchas can make path
repositories a less universal tool than they might otherwise be, but they’re still a useful tool to have in your composer belt.