Repositories - Composer (2024)

  • Concepts
    • Package
    • Repository
  • Types
    • Composer
      • packages
      • notify-batch
      • metadata-url, available-packages and available-package-patterns
      • providers-api
      • list
      • provider-includes and providers-url
      • cURL or stream options
    • VCS
      • Loading a package from a VCS repository
      • Using private repositories
      • Git alternatives
      • Bitbucket Driver Configuration
      • Subversion Options
    • Package
  • Hosting your own
    • Private Packagist
    • Satis
    • Artifact
    • Path
  • Disabling Packagist.org

This chapter will explain the concept of packages and repositories, what kindsof repositories are available, and how they work.

Concepts#

Before we look at the different types of repositories that exist, we need tounderstand some basic concepts that Composer is built on.

Package#

Composer is a dependency manager. It installs packages locally. A package isessentially a directory containing something. In this case it is PHPcode, but in theory it could be anything. And it contains a packagedescription which has a name and a version. The name and the version are usedto identify the package.

In fact, internally, Composer sees every version as a separate package. Whilethis distinction does not matter when you are using Composer, it's quiteimportant when you want to change it.

In addition to the name and the version, there is useful metadata. Theinformation most relevant for installation is the source definition, whichdescribes where to get the package contents. The package data points to thecontents of the package. And there are two options here: dist and source.

Dist: The dist is a packaged version of the package data. Usually areleased version, usually a stable release.

Source: The source is used for development. This will usually originatefrom a source code repository, such as git. You can fetch this when you wantto modify the downloaded package.

Packages can supply either of these, or even both. Depending on certainfactors, such as user-supplied options and stability of the package, one willbe preferred.

Repository#

A repository is a package source. It's a list of packages/versions. Composerwill look in all your repositories to find the packages your project requires.

By default, only the Packagist.org repository is registered in Composer. You canadd more repositories to your project by declaring them in composer.json.

Repositories are only available to the root package and the repositoriesdefined in your dependencies will not be loaded. Read theFAQ entry if youwant to learn why.

When resolving dependencies, packages are looked up from repositories fromtop to bottom, and by default, as soon as a package is found in one, Composerstops looking in other repositories. Read therepository priorities article for moredetails and to see how to change this behavior.

Types#

Composer#

The main repository type is the composer repository. It uses a singlepackages.json file that contains all of the package metadata.

This is also the repository type that packagist uses. To reference acomposer repository, supply the path before the packages.json file.In the case of packagist, that file is located at /packages.json, so the URL ofthe repository would be repo.packagist.org. For example.org/packages.json therepository URL would be example.org.

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

packages#

The only required field is packages. The JSON structure is as follows:

{ "packages": { "vendor/package-name": { "dev-master": { @composer.json }, "1.0.x-dev": { @composer.json }, "0.0.1": { @composer.json }, "1.0.0": { @composer.json } } }}

The @composer.json marker would be the contents of the composer.json fromthat package version including as a minimum:

  • name
  • version
  • dist or source

Here is a minimal package definition:

{ "name": "smarty/smarty", "version": "3.1.7", "dist": { "url": "https://www.smarty.net/files/Smarty-3.1.7.zip", "type": "zip" }}

It may include any of the other fields specified in the schema.

notify-batch#

The notify-batch field allows you to specify a URL that will be calledevery time a user installs a package. The URL can be either an absolute path(that will use the same domain as the repository), or a fully qualified URL.

An example value:

{ "notify-batch": "/downloads/"}

For example.org/packages.json containing a monolog/monolog package, thiswould send a POST request to example.org/downloads/ with followingJSON request body:

{ "downloads": [ {"name": "monolog/monolog", "version": "1.2.1.0"} ]}

The version field will contain the normalized representation of the versionnumber.

This field is optional.

metadata-url, available-packages and available-package-patterns#

The metadata-url field allows you to provide a URL template to serve allpackages which are in the repository. It must contain the placeholder%package%.

This field is new in Composer v2, and is prioritised over theprovider-includes and providers-url fields if both are present.For compatibility with both Composer v1 and v2 you ideally wantto provide both. New repository implementations may only need tosupport v2 however.

An example:

{ "metadata-url": "/p2/%package%.json"}

Whenever Composer looks for a package, it will replace %package% by thepackage name, and fetch that URL. If dev stability is allowed for the package,it will also load the URL again with $packageName~dev (e.g./p2/foo/bar~dev.json to look for foo/bar's dev versions).

The foo/bar.json and foo/bar~dev.json files containing package versionsMUST contain only versions for the foo/bar package, as{"packages":{"foo/bar":[ ... versions here ... ]}}.

Caching is done via the use of If-Modified-Since header, so make sure youreturn Last-Modified headers and that they are accurate.

The array of versions can also optionally be minified usingComposer\MetadataMinifier\MetadataMinifier::minify() fromcomposer/metadata-minifier.If you do that, you should add a "minified": "composer/2.0" keyat the top level to indicate to Composer it must expand the versionlist back into the original data. Seehttps://repo.packagist.org/p2/monolog/monolog.json for an example.

Any requested package which does not exist MUST return a 404 status code,which will indicate to Composer that this package does not exist in yourrepository. Make sure the 404 response is fast to avoid blocking Composer.Avoid redirects to alternative 404 pages.

If your repository only has a small number of packages, and you want to avoidthe 404-requests, you can also specify an "available-packages" key inpackages.json which should be an array with all the package names that yourrepository contains. Alternatively you can specify an"available-package-patterns" key which is an array of package name patterns(with * matching any string, e.g. vendor/* would make Composer look upevery matching package name in this repository).

This field is optional.

providers-api#

The providers-api field allows you to provide a URL template to serve allpackages which provide a given package name, but not the package which hasthat name. It must contain the placeholder %package%.

For example https://packagist.org/providers/monolog/monolog.json lists somepackage which have a "provide" rule for monolog/monolog, but it does not listmonolog/monolog itself.

{ "providers-api": "https://packagist.org/providers/%package%.json",}

This field is optional.

list#

The list field allows you to return the names of packages which match agiven filter (or all names if no filter is present). It should accept anoptional ?filter=xx query param, which can contain * as wildcards matchingany substring.

Replace/provide rules should not be considered here.

It must return an array of package names:

{ "packageNames": [ "a/b", "c/d" ]}

See https://packagist.org/packages/list.json?filter=composer/* for example.

This field is optional.

provider-includes and providers-url#

The provider-includes field allows you to list a set of files that listpackage names provided by this repository. The hash should be a sha256 ofthe files in this case.

The providers-url describes how provider files are found on the server. Itis an absolute path from the repository root. It must contain the placeholders%package% and %hash%.

These fields are used by Composer v1, or if your repository does not have themetadata-url field set.

An example:

{ "provider-includes": { "providers-a.json": { "sha256": "f5b4bc0b354108ef08614e569c1ed01a2782e67641744864a74e788982886f4c" }, "providers-b.json": { "sha256": "b38372163fac0573053536f5b8ef11b86f804ea8b016d239e706191203f6efac" } }, "providers-url": "/p/%package%$%hash%.json"}

Those files contain lists of package names and hashes to verify the fileintegrity, for example:

{ "providers": { "acme/foo": { "sha256": "38968de1305c2e17f4de33aea164515bc787c42c7e2d6e25948539a14268bb82" }, "acme/bar": { "sha256": "4dd24c930bd6e1103251306d6336ac813b563a220d9ca14f4743c032fb047233" } }}

The file above declares that acme/foo and acme/bar can be found in thisrepository, by loading the file referenced by providers-url, replacing%package% by the vendor namespaced package name and %hash% by thesha256 field. Those files themselves contain package definitions asdescribed above.

These fields are optional. You probably don't need them for your own customrepository.

cURL or stream options#

The repository is accessed either using cURL (Composer 2 with ext-curl enabled)or PHP streams. You can set extra options using the options parameter. ForPHP streams, you can set any valid PHP stream context option. See Contextoptions and parameters for moreinformation. When cURL is used, only a limited set of http and ssl optionscan be configured.

{ "repositories": [ { "type": "composer", "url": "https://example.org", "options": { "http": { "timeout": 60 } } } ], "require": { "acme/package": "^1.0" }}

VCS#

VCS stands for version control system. This includes versioning systems likegit, svn, fossil or hg. Composer has a repository type for installing packagesfrom these systems.

Loading a package from a VCS repository#

There are a few use cases for this. The most common one is maintaining yourown fork of a third party library. If you are using a certain library for yourproject, and you decide to change something in the library, you will want yourproject to use the patched version. If the library is on GitHub (this is thecase most of the time), you can fork it there and push your changes toyour fork. After that you update the project's composer.json. All you haveto do is add your fork as a repository and update the version constraint topoint to your custom branch. In composer.json only, you should prefix yourcustom branch name with "dev-" (without making it part of the actual branchname). For version constraint naming conventions seeLibraries for more information.

Example assuming you patched monolog to fix a bug in the bugfix branch:

{ "repositories": [ { "type": "vcs", "url": "https://github.com/igorw/monolog" } ], "require": { "monolog/monolog": "dev-bugfix" }}

When you run php composer.phar update, you should get your modified versionof monolog/monolog instead of the one from packagist.

Note that you should not rename the package unless you really intend to forkit in the long term, and completely move away from the original package.Composer will correctly pick your package over the original one since thecustom repository has priority over packagist. If you want to rename thepackage, you should do so in the default (often master) branch and not in afeature branch, since the package name is taken from the default branch.

Also note that the override will not work if you change the name propertyin your forked repository's composer.json file as this needs to match theoriginal for the override to work.

If other dependencies rely on the package you forked, it is possible toinline-alias it so that it matches a constraint that it otherwise would not.For more information see the aliases article.

Using private repositories#

Exactly the same solution allows you to work with your private repositories atGitHub and Bitbucket:

{ "repositories": [ { "type": "vcs", "url": "git@bitbucket.org:vendor/my-private-repo.git" } ], "require": { "vendor/my-private-repo": "dev-master" }}

The only requirement is the installation of SSH keys for a git client.

Git alternatives#

Git is not the only version control system supported by the VCS repository.The following are supported:

To get packages from these systems you need to have their respective clientsinstalled. That can be inconvenient. And for this reason there is specialsupport for GitHub and Bitbucket that use the APIs provided by these sites, tofetch the packages without having to install the version control system. TheVCS repository provides dists for them that fetch the packages as zips.

The VCS driver to be used is detected automatically based on the URL. However,should you need to specify one for whatever reason, you can use bitbucket,github, gitlab, perforce, fossil, git, svn or hgas the repository type instead of vcs.

If you set the no-api key to true on a github repository it will clone therepository as it would with any other git repository instead of using theGitHub API. But unlike using the git driver directly, Composer will stillattempt to use github's zip files.

Please note:

  • To let Composer choose which driver to use the repository type needs to be defined as "vcs"
  • If you already used a private repository, this means Composer should have cloned it in cache. If you want to install the same package with drivers, remember to launch the command composer clearcache followed by the command composer update to update Composer cache and install the package from dist.
  • VCS driver git-bitbucket is deprecated in favor of bitbucket

Bitbucket Driver Configuration#

Note that the repository endpoint for Bitbucket needs to be https rather than git.

After setting up your bitbucket repository, you will also need toset up authentication.

Subversion Options#

Since Subversion has no native concept of branches and tags, Composer assumesby default that code is located in $url/trunk, $url/branches and$url/tags. If your repository has a different layout you can change thosevalues. For example if you used capitalized names you could configure therepository like this:

{ "repositories": [ { "type": "vcs", "url": "http://svn.example.org/projectA/", "trunk-path": "Trunk", "branches-path": "Branches", "tags-path": "Tags" } ]}

If you have no branches or tags directory you can disable them entirely bysetting the branches-path or tags-path to false.

If the package is in a subdirectory, e.g. /trunk/foo/bar/composer.json and/tags/1.0/foo/bar/composer.json, then you can make Composer access it bysetting the "package-path" option to the sub-directory, in this example itwould be "package-path": "foo/bar/".

If you have a private Subversion repository you can save credentials in thehttp-basic section of your config (See Schema):

{ "http-basic": { "svn.example.org": { "username": "username", "password": "password" } }}

If your Subversion client is configured to store credentials by default thesecredentials will be saved for the current user and existing saved credentialsfor this server will be overwritten. To change this behavior by setting the"svn-cache-credentials" option in your repository configuration:

{ "repositories": [ { "type": "vcs", "url": "http://svn.example.org/projectA/", "svn-cache-credentials": false } ]}

Package#

If you want to use a project that does not support Composer through any of themeans above, you still can define the package yourself by using a packagerepository.

Basically, you define the same information that is included in the composerrepository's packages.json, but only for a single package. Again, theminimum required fields are name, version, and either of dist orsource.

Here is an example for the smarty template engine:

{ "repositories": [ { "type": "package", "package": { "name": "smarty/smarty", "version": "3.1.7", "dist": { "url": "https://www.smarty.net/files/Smarty-3.1.7.zip", "type": "zip" }, "source": { "url": "http://smarty-php.googlecode.com/svn/", "type": "svn", "reference": "tags/Smarty_3_1_7/distribution/" }, "autoload": { "classmap": ["libs/"] } } } ], "require": { "smarty/smarty": "3.1.*" }}

Typically, you would leave the source part off, as you don't really need it.

If a source key is included, the reference field should be a reference to the version that will be installed.Where the type field is git, this will the be the commit id, branch or tag name.

Note: It is not recommended to use a git branch name for the reference field. While this is valid since it is supported by git checkout,branch names are mutable so cannot be locked.

Where the type field is svn, the reference field should contain the reference that gets appended to the URL when running svn co.

Note: This repository type has a few limitations and should be avoidedwhenever possible:

  • Composer will not update the package unless you change the version field.
  • Composer will not update the commit references, so if you use master asreference you will have to delete the package to force an update, and willhave to deal with an unstable lock file.

The "package" key in a package repository may be set to an array to define multiple versions of a package:

{ "repositories": [ { "type": "package", "package": [ { "name": "foo/bar", "version": "1.0.0", ... }, { "name": "foo/bar", "version": "2.0.0", ... } ] } ]}

Hosting your own#

While you will probably want to put your packages on packagist most of thetime, there are some use cases for hosting your own repository.

  • Private company packages: If you are part of a company that uses Composerfor their packages internally, you might want to keep those packages private.

  • Separate ecosystem: If you have a project which has its own ecosystem,and the packages aren't really reusable by the greater PHP community, youmight want to keep them separate to packagist. An example of this would beWordPress plugins.

For hosting your own packages, a native composer type of repository isrecommended, which provides the best performance.

There are a few tools that can help you create a composer repository.

Private Packagist#

Private Packagist is a hosted or self-hostedapplication providing private package hosting as well as mirroring ofGitHub, Packagist.org and other package repositories.

Check out Packagist.com for more information.

Satis#

Satis is a static composer repository generator. It is a bit like an ultra-lightweight, static file-based version of packagist.

You give it a composer.json containing repositories, typically VCS andpackage repository definitions. It will fetch all the packages that arerequired and dump a packages.json that is your composer repository.

Check the satis GitHub repository andthe handling private packages article for moreinformation.

Artifact#

There are some cases, when there is no ability to have one of the previouslymentioned repository types online, even the VCS one. A typical example could becross-organisation library exchange through build artifacts. Of course, mostof the time these are private. To use these archives as-is, one can use arepository of type artifact with a folder containing ZIP or TAR archives ofthose private packages:

{ "repositories": [ { "type": "artifact", "url": "path/to/directory/with/zips/" } ], "require": { "private-vendor-one/core": "15.6.2", "private-vendor-two/connectivity": "*", "acme-corp/parser": "10.3.5" }}

Each zip artifact is a ZIP archive with composer.json in root folder:

unzip -l acme-corp-parser-10.3.5.zip
composer.json...

If there are two archives with different versions of a package, they are bothimported. When an archive with a newer version is added in the artifact folderand you run update, that version will be imported as well and Composer willupdate to the latest version.

Path#

In addition to the artifact repository, you can use the path one, which allowsyou to depend on a local directory, either absolute or relative. This can beespecially useful when dealing with monolithic repositories.

For instance, if you have the following directory structure in your repository:

...├── apps│ └── my-app│ └── composer.json├── packages│ └── my-package│ └── composer.json...

Then, to add the package my/package as a dependency, in yourapps/my-app/composer.json file, you can use the following configuration:

{ "repositories": [ { "type": "path", "url": "../../packages/my-package" } ], "require": { "my/package": "*" }}

If the package is a local VCS repository, the version may be inferred bythe branch or tag that is currently checked out. Otherwise, the version shouldbe explicitly defined in the package's composer.json file. If the versioncannot be resolved by these means, it is assumed to be dev-master.

When the version cannot be inferred from the local VCS repository, or when youwant to override the version, you can use the versions option when declaringthe repository:

{ "repositories": [ { "type": "path", "url": "../../packages/my-package", "options": { "versions": { "my/package": "4.2-dev" } } } ]}

The local package will be symlinked if possible, in which case the output inthe console will read Symlinking from ../../packages/my-package. If symlinkingis not possible the package will be copied. In that case, the console willoutput Mirrored from ../../packages/my-package.

Instead of default fallback strategy you can force to use symlink with"symlink": true or mirroring with "symlink": false option. Forcingmirroring can be useful when deploying or generating package from amonolithic repository.

Note: On Windows, directory symlinks are implemented using NTFS junctionsbecause they can be created by non-admin users. Mirroring will always be usedon versions below Windows 7 or if proc_open has been disabled.

{ "repositories": [ { "type": "path", "url": "../../packages/*", "options": { "symlink": false } } ]}

Leading tildes are expanded to the current user's home folder, and environmentvariables are parsed in both Windows and Linux/Mac notations. For example~/git/mypackage will automatically load the mypackage clone from/home/<username>/git/mypackage, equivalent to $HOME/git/mypackage or%USERPROFILE%/git/mypackage.

Note: Repository paths can also contain wildcards like * and ?.For details, see the PHP glob function.

You can configure the way the package's dist reference (which appears inthe composer.lock file) is built.

The following modes exist:

  • none - reference will be always null. This can help reduce lock file conflictsin the lock file but reduces clarity as to when the last update happened and whetherthe package is in the latest state.
  • config - reference is built based on a hash of the package's composer.json and repo config
  • auto (used by default) - reference is built basing on the hash like with config, but ifthe package folder contains a git repository, the HEAD commit's hash is used as reference instead.
{ "repositories": [ { "type": "path", "url": "../../packages/*", "options": { "reference": "config" } } ]}

Disabling Packagist.org#

You can disable the default Packagist.org repository by adding this to yourcomposer.json:

{ "repositories": [ { "packagist.org": false } ]}

You can disable Packagist.org globally by using the global config flag:

php composer.phar config -g repo.packagist false

Schema | Config

Found a typo? Something is wrong in this documentation? Fork and edit it!

Repositories - Composer (2024)

References

Top Articles
Latest Posts
Article information

Author: Kareem Mueller DO

Last Updated:

Views: 6074

Rating: 4.6 / 5 (46 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Kareem Mueller DO

Birthday: 1997-01-04

Address: Apt. 156 12935 Runolfsdottir Mission, Greenfort, MN 74384-6749

Phone: +16704982844747

Job: Corporate Administration Planner

Hobby: Mountain biking, Jewelry making, Stone skipping, Lacemaking, Knife making, Scrapbooking, Letterboxing

Introduction: My name is Kareem Mueller DO, I am a vivacious, super, thoughtful, excited, handsome, beautiful, combative person who loves writing and wants to share my knowledge and understanding with you.