Install a WordPress plugin from a self-hosted ZIP file using Composer

With tools like WP Starter or Bedrock, we can manage WordPress sites with Composer easily.

Thanks to WordPress Packagist, when we want to install a plugin from the WordPress.org Plugin Directory, it's just a matter of requiring them:

composer require wpackagist-plugin/akismet

However, things are more complicated when we are dealing with commercial plugins.

Those are not listed on WordPress Packagist, and most lack Composer support. Some do, for example, Yoast SEO.

We can get around this using Private Packagist. That's the most convenient way. Although it's a paid service, its convenience makes it a worthy investment. Moreover, it's a solid way to support this crucial project within the PHP ecosystem.

But there are other ways.

Typically, when we purchase a commercial plugin, we can download it as a ZIP file, but we rarely get access to a private Git repository where the source code is.

We can take advantage of this and self-host the plugin's ZIP files. We can simply upload them to our server.

Once we do that, we can make Composer aware of it. This is possible by registering a package as the type of package. Here's how it looks:

{
    "require": {
        "example/foo": "1.2.1"
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "example/foo",
                "version": "1.2.1",
                "type": "wordpress-plugin",
                "dist": {
                    "url": "https://example.org/restricted/foo-1.2.1.zip",
                    "type": "zip"
                }
            }
        }
    ]
}

With this configuration, Composer treats it as any other package, and we can install it as example/foo.

Likely, we don't want to keep these files accessible to the public. We can protect these files with Basic Authentification.

Composer knows how to deal with it out of the box.

To provide the credentials, we can create an auth.json:

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