This article is produced by scandiweb

scandiweb is the most certified Adobe Commerce (Magento) team globally, being a long-term official Adobe partner specializing in Commerce in EMEA and the Americas. eCommerce has been our core expertise for 20+ years.

PHP Series: How to Publish a Composer Package

To publish a package, we first have to host it on a version control system repository. The source code should be placed in the root directory, and a composer.json file should be configured appropriately under the rules below. Afterward, you can submit your package on different platforms.

Read this article to learn more about composers and what is a composer package and how to install it.

Step 1: Set up a Git repository

scandiweb uses GitHub for hosting public ScandiPWA packages and Bitbucket for hosting private repositories. Make sure you have a secure connection and SSH keys set up. If you’ve been working on a package, you probably have the repository set up and cloned locally. If not, set up a repository and clone it afterward. You can check out the following guides:

Step 2: Create a composer.json

We need to create a composer.json file in the repository’s root directory and fill it with important configuration properties. You can do it manually, or if you have Composer installed, you can use a composer init command and fill fields interactively from the command line.

composer init should be run from the project root directory

Template for a package composer.json file:

{
    "name": "<PACKAGE NAME>",
    "description": "<PACKAGE DESCRIPTION>",
    "type": "<PACKAGE TYPE>",
		"require": {
        "<DEPENDENCY NAME>": "*"
    },
		"authors": [
	    {
	      "name": "scandiweb.com",
	      "email": "[email protected]"
	    }
		]
}

How do I name a package?

The package name must be lowercase, with a vendor name and one package name separate by /. The vendor name and the package name also need to be in lowercase and can be separated only by -, ., or _. For example, <vendor_name>/<package_name>.

"name": "magento/updater",
"name": "scandipwa/menu-organizer",
"name": "magento/project-community-edition",
"name": "squizlabs/php_codesniffer",

What should the description have?

Use it to briefly define the purpose of the package and give a short description of it. Usually, this is one line long. 

"description": "Magento Project Name",

Required for published packages (libraries).

What types can a package have?

Package types are used for custom installation logic.

  • custom: If you need to define a unique logic and be specific to a particular project, you might need to create a custom type with a name separated by dashes (-). Example: magento2-module
  • library: This is the default. It will copy the files to the vendor
  • project: This denotes a project rather than a library
  • metapackage: An empty package containing requirements that will trigger their installation but has no files and will not write anything to the filesystem. As such, it does not require a dist or source key to be installable
  • composer-plugin: A package of type composer-plugin may provide an installer for other packages with a custom type.
"type": "magento2-module",
"type": "project",

How to specify the dependencies?

You can see the dependency definitions under the require field. Each has a name matching the <vendor_name>/<package_name> pattern and a version specified.

"require":"magento/product-community-edition":"2.2.3",
"require": {
        "monolog/monolog": "1.0.*@beta",
        "acme/foo": "@dev"
    }
"replace":"drupal/action": "self.version",

How to specify which version of the package to install?

The version must follow the format X.Y.Z or vX.Y.Z with an optional suffix of -dev, -patch (-p), -alpha (-a), -beta (-b), or -RC. The patch, alpha, beta, and RC suffixes can also be followed by a number.

Here are some examples of the SemVer versioning approach in practice:

"require": {
    "vendor/package": "1.3.2", // exactly 1.3.2

    // >, <, >=, <= | specify upper / lower bounds
    "vendor/package": ">=1.3.2", // anything above or equal to 1.3.2
    "vendor/package": "<1.3.2", // anything below 1.3.2

    // * | wildcard
    "vendor/package": "1.3.*", // >=1.3.0 <1.4.0

    // ~ | allows last digit specified to go up
    "vendor/package": "~1.3.2", // >=1.3.2 <1.4.0
    "vendor/package": "~1.3", // >=1.3.0 <2.0.0

    // ^ | doesn't allow breaking changes (major version fixed - following semver)
    "vendor/package": "^1.3.2", // >=1.3.2 <2.0.0
    "vendor/package": "^0.3.2", // >=0.3.2 <0.4.0 // except if major version is 0
}

See more information here.

require

Map of packages required by this package. The package will only be installed if those requirements can be met.

replace

Map of packages that are replaced by this package. This allows you to fork a package and publish it under a different name with its version numbers. In contrast, packages requiring the original package continue to work with your fork because it replaces the original package.

This is also useful for packages that contain sub-packages; for example, the main symfony/symfony package contains all the Symfony Components, which are also available as individual packages. If you require the main package, it will automatically fulfill any requirement of one of the individual components since it replaces them.

Caution is advised when using replace for the sub-package purpose explained above. You should then typically only replace using self.version as a version constraint to ensure the main package only replaces the sub-packages of that exact version and not any other version, which would be incorrect.

You can check more options on the official website.

Step 3: Publish the package

After configuring everything locally, you should commit and push changes to update the repository.

How to publish a public package?

If the package you plan to publish was made for public usage, you should have a Packagist account and go to their submission page. There, add the package repository URL and click check; if Packagist finds it, it’ll ask you to submit it.

How to publish a private package?

For publishing packages intended for private usage, scandiweb uses Satis.

Was this article helpful? There’s more where this came from! Browse our tech category in the blog, or contact our team directly!

Related articles:

PHP Series: How to Use a Composer Patch

PHP Series: How to Install a Composer Package?

Need help with your eCommerce?

Get in touch for a free consultation to discuss your business and explore how we can help.

Your request will be processed by

If you enjoyed this post, you may also like