How To Build Your Own PHP Composer Package

A couple of months back, I wrote a PHP library that abstracts the API of Paystack (A Nigerian FinTech company) into a pluggable composer package. The library has since gotten more than 100 installs, and another package is dependent on it. Since then, a host of other payment systems/providers and other services have popped up, so I thought to write this tutorial or guide to building your own composer installable composer package.
So, off we go.

Directory Structure

The first thing to do is to create the directory that holds your package. It is also where you will develop the package from.
Usually, the basic directory structure for PHP packages looks like;

- parent_directory/
  - src/
  - tests/
  - composer.json
  - readme.md
  - changelog.md
  - contributing.md

The parent_directory holds all the files of the package.
The src (short for source) directory holds the package codes, the tests directory holds the package’s tests, composer.json describes your package.
readme.md contains the information about your package, forming part of its documentation.
changelog.md is a log or record of all notable changes made to a package. It is important to keep this as it helps users of your package to follow the changes you make to your package per version. More information about the format can be found here.
contributing.md explains how someone may contribute to your package. It ideally should contain information like the coding standards, submission and review process.

Composer

I won’t be demystifying composer in this article, but composer is key in helping you distribute your PHP library/SDK. The composer.json file describes your package and any dependencies it may need to both Packagist (the default composer packages repository) and Composer. Other actions/configurations – such as how your package should be autoloaded- are specified in this file. For your package though, few things are important and required in your composer.json file;

  • name: This describes the unique name of your package often in the form vendor/package_name. This format allows for uniqueness of the package incase the package name you decided on already exists. Vendor is usually the the name of the author or organization that made the package.
  • version: This describes the current version of your package. This is key because the version is what Packagist uses to resolve the version(s) of your package. Ideally, you should follow the Semantic version specification (http://semver.org)
  • description: This describes your package
  • require: This is a list of other packages your package depends on.
  • require-dev: This contains a list of packages your package depends on for its development. Typically, this contains your testing tools.
  • autoload: this describes how your package should be autoloaded. Composer supports both PSR-0 and PSR-4 autoloading.

Quick note: The difference between require and require-dev is that when your package is pulled in as a dependency or installed, only the dependencies in require will be pulled in along with it as they are “required” for the proper working of your package. However, during development of your package, “require-dev” dependencies will be pulled in as well because they are required for development.

At its barest minimum, your composer.json should look something like;

 {
    "name": "vendor/package_name",
    "version": "0.0.1"
    "description": "My PHP Package",
    "require": {
    },
    "require-dev": {
    },
    "autoload": {
        "psr-4": {
            "vendor\\package_name\\": "src/",
            "vendor\\package_name\\Tests\\": "Tests/"
        }
    }
}

At this point, what is left is to run a composer install to pull in your dependencies and write your package codes.

Testing your package

Often time during development, we want to test how our package integrates with other packages/projects when pulled in. Note that this is different from the very important unit tests.
One way is to “require” your package in another project locally. To do this, you need to specify a “repository” that points to the local file path of your package in the composer.json of that project, and require your package like so;

{
    "name": "test-php-project",
    "description": "A PHP project to test my package",
    "repositories": [
        {
            "type": "path",
            "url": "full/file/path/to/directory/containing/my_package"
        }
    ],
    "require": {
        "my/package": "*"
    }
}

This is simply saying to composer, “Please check this folder location too for packages during install”.

Other Important Things To Note

  • Unit testing in very important. Make sure to get good code coverage on your unit tests for all your classes and files. This helps build user confidence in your package.
    Travis CI is a service that should be integrated in your package for continuous integration. This will run your complete test suite when you or collaborators make pull requests and contributions, which will allow you quickly see if new changes break anything.
  • Follow the PHP FIG PSR standards, especially PSR-1, PSR-2, and PSR-4. This defines expectations that keep your package up to the community standards.

In the next part of this article, we’ll discuss publishing your package.

Some important links;