How do I release a PHP Composer package?
Composer
is the standard package manager for PHP.
Here’s how to release a package for it.
First let’s clarify what I’m doing.
I have an example project called donut-news
,
and its composer.json
looks like this:
{
"name": "jameshfisher/donut-news",
"description": "Donut news",
"type": "project",
"authors": [
{
"name": "Jim Fisher",
"email": "jameshfisher@gmail.com"
}
],
"require": {
"monolog/monolog": "^1.23"
}
}
The require
block defines the dependencies for jameshfisher/donut-news
,
and currently it has one dependency:
monolog
, a logging library.
This dependency was added by running:
php composer.phar require monolog/monolog
Now donut-news
has a lot of donut logic
which would be better put in a generic donuts
library.
I want to create a new Composer library package called donut-logic
,
so that I can add it to my donut-news
project by running
php composer.phar require jameshfisher/donut-logic
When you run php composer.phar require foo/bar
,
Composer looks for the package foo/bar
in repositories.
A repository is a store of Composer packages.
The default Composer repository is https://packagist.org
,
and you can browse all the packages on Packagist.org here.
To release jameshfisher/donut-logic
,
I need to get it into this list.
Composer package names are prefixed with a “vendor” name.
In jameshfisher/donut-logic
,
the vendor is jameshfisher
.
On Packagist.org,
vendor names correspond to accounts.
I created an account on Packagist.org called jameshfisher
.
Packages on Packagist.org are backed by git repositories.
I created a new repository at https://github.com/jameshfisher/donut-logic.
Just like your PHP projects have a composer.json
,
Composer packages/libraries also have a composer.json
.
I created this composer.json
for donut-logic
,
and added it to the root of the repository:
{
"name": "jameshfisher/donut-logic",
"description": "Shared logic related to donuts",
"require": {}
}
Next, I visited https://packagist.org/packages/submit,
which asks for the repository URL.
I submitted it, and it registed a new Packagist.org package:
https://packagist.org/packages/jameshfisher/donut-logic.
However, this new package is not “stable”,
so can’t be installed by default!:
$ php composer.phar require jameshfisher/donut-logic
[InvalidArgumentException]
Could not find package jameshfisher/donut-logic at any version for your m
inimum-stability (stable). Check the package spelling or your minimum-sta
bility
It turns out that “stable” means “has a git tag”.
So I tagged my current version as 0.0.1
:
$ git tag 0.0.1
$ git push --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:jameshfisher/donut-logic.git
* [new tag] 0.0.1 -> 0.0.1
This isn’t enough, because
Packagist.org doesn’t know that I’ve updated the source git repository.
I need to tell it that the repository has been updated:
curl \
-X POST \
-H 'Content-Type: application/json' \
-d '{"repository":{"url":"https://github.com/jameshfisher/donut-logic"}}' \
'https://packagist.org/api/update-package?username=jameshfisher&apiToken=MY_API_TOKEN'
(I got my Packagist.org API token at https://packagist.org/profile/.)
Now at https://packagist.org/packages/jameshfisher/donut-logic
I can see that there are two versions of my package: dev-master
and 0.0.1
.
I can now require
my package, and it gets version 0.0.1
:
$ php composer.phar require jameshfisher/donut-logic
Using version ^0.0.1 for jameshfisher/donut-logic
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing jameshfisher/donut-logic (0.0.1): Downloading (100%)
Writing lock file
Generating autoload files
There’s a more reliable way to ensure that
Packagist.org is up-to-date with the source git repo:
GitHub Service Hooks.
I went to https://github.com/jameshfisher/donut-logic/settings/hooks/new?service=packagist,
and configured it with my username and Packagist.org API token.
Now, when my repository is updated,
GitHub will notify Packagist.org.
Similar posts
How PHP and Composer find your code
Composer’s autoloader uses PSR-4 to map namespaces to directories, allowing you to load classes without explicit require
statements. 2017-11-09
Nix by example, Part 1: The Nix expression language
Nix is a functional programming language used for package management. We see the Nix expression language, including strings, primitives, operators, functions, let expressions, and conditionals. 2014-09-28
The golden rule of PR reviews
The “golden rule” of code reviews is to approve improvements. Approve pull requests that fix bugs, even if the implementation isn’t ideal. 2023-10-07
Executables in npm?
NPM packages can contain executables, not just Node.js modules. NPM provides features to help distribute and run these executables, such as the bin
field in package.json
and the npm run-script
command. 2020-10-02
Why is the contentRect
of my NSWindow
ignored?
Calling setFrameAutosaveName
on an NSWindow
causes its size and position to be saved to user defaults, overriding the contentRect
passed to the constructor. To avoid this, do not call setFrameAutosaveName
. 2020-07-10
What is simulated annealing?
Simulated annealing is a variation of trial-and-error optimization that generates mutations of the current best guess, and gradually reduces the magnitude of the mutations over time, similar to how metals cool. 2019-05-28
More by Jim
What does the dot do in JavaScript?
foo.bar
, foo.bar()
, or foo.bar = baz
- what do they mean? A deep dive into prototypical inheritance and getters/setters. 2020-11-01
Smear phishing: a new Android vulnerability
Trick Android to display an SMS as coming from any contact. Convincing phishing vuln, but still unpatched. 2020-08-06
A probabilistic pub quiz for nerds
A “true or false” quiz where you respond with your confidence level, and the optimal strategy is to report your true belief. 2020-04-26
Time is running out to catch COVID-19
Simulation shows it’s rational to deliberately infect yourself with COVID-19 early on to get treatment, but after healthcare capacity is exceeded, it’s better to avoid infection. Includes interactive parameters and visualizations. 2020-03-14
The inception bar: a new phishing method
A new phishing technique that displays a fake URL bar in Chrome for mobile. A key innovation is the “scroll jail” that traps the user in a fake browser. 2019-04-27
The hacker hype cycle
I got started with simple web development, but because enamored with increasingly esoteric programming concepts, leading to a “trough of hipster technologies” before returning to more productive work. 2019-03-23
Project C-43: the lost origins of asymmetric crypto
Bob invents asymmetric cryptography by playing loud white noise to obscure Alice’s message, which he can cancel out but an eavesdropper cannot. This idea, published in 1944 by Walter Koenig Jr., is the forgotten origin of asymmetric crypto. 2019-02-16
How Hacker News stays interesting
Hacker News buried my post on conspiracy theories in my family due to overheated discussion, not censorship. Moderation keeps the site focused on interesting technical content. 2019-01-26
My parents are Flat-Earthers
For decades, my parents have been working up to Flat-Earther beliefs. From Egyptology to Jehovah’s Witnesses to theories that human built the Moon billions of years in the future. Surprisingly, it doesn’t affect their successful lives very much. For me, it’s a fun family pastime. 2019-01-20
The dots do matter: how to scam a Gmail user
Gmail’s “dots don’t matter” feature lets scammers create an account on, say, Netflix, with your email address but different dots. Results in convincing phishing emails. 2018-04-07
The sorry state of OpenSSL usability
OpenSSL’s inadequate documentation, confusing key formats, and deprecated interfaces make it difficult to use, despite its importance. 2017-12-02
I hate telephones
I hate telephones. Some rational reasons: lack of authentication, no spam filtering, forced synchronous communication. But also just a visceral fear. 2017-11-08
The Three Ts of Time, Thought and Typing: measuring cost on the web
Businesses often tout “free” services, but the real costs come in terms of time, thought, and typing required from users. Reducing these “Three Ts” is key to improving sign-up flows and increasing conversions. 2017-10-26
Granddad died today
Granddad died. The unspoken practice of death-by-dehydration in the NHS. The Liverpool Care Pathway. Assisted dying in the UK. The importance of planning in end-of-life care. 2017-05-19
How do I call a program in C, setting up standard pipes?
A C function to create a new process, set up its standard input/output/error pipes, and return a struct containing the process ID and pipe file descriptors. 2017-02-17
Your syntax highlighter is wrong
Syntax highlighters make value judgments about code. Most highlighters judge that comments are cruft, and try to hide them. Most diff viewers judge that code deletions are bad. 2014-05-11
Want to build a fantastic product using LLMs? I work at
Granola where we're building the future IDE for knowledge work. Come and work with us!
Read more or
get in touch! This page copyright James Fisher 2017. Content is not associated with my employer. Found an error? Edit this page.