cult3

How to create a PSR-4 PHP package

May 07, 2014

Table of contents:

  1. The directory structure
  2. Composer
  3. Dot files
  4. Your code
  5. Writing tests
  6. Documentation
  7. Pushing to GitHub and Packagist
  8. Conclusion

Over the last couple of weeks I’ve wrote tutorials on many different aspects of the PHP programming language as building blocks for building your own packages. Understanding these different concepts will take you a long way when it comes to creating your own packages for your projects as well as for the Open Source community.

A couple of weeks ago I wrote a tutorial on the general principles behind building PHP packages. In that article I mentioned the PSR-4 standard for creating PHP packages.

In this tutorial I’m going to walk you through setting up the structure of a PHP package. By having an agreed upon structure for PHP packages we make our code a lot more interchangeable and reusable for the greater Open Source community.

The directory structure

So the first thing to do is to create a new directory on your computer that will hold all of the files. For the purpose of this tutorial I will call my package Nacho.

So firstly, create a new directory called nacho.

Open the nacho directory and create two more directories called src and tests.

All of the code of the package should reside in the src directory and all of your package’s tests should live in the tests directory.

Next, open up your command line and run:

git init

This will create a new Git repository. Git is a requirement for creating PHP packages so I’m going to assume you already have it installed.

Composer

Composer is a PHP package manager that plays a pivotal role in how we pull dependencies into our projects. If you are unfamiliar with Composer, read What is PHP Composer? before continuing on with this tutorial.

Create a file under the nacho directory called composer.json and copy the following code:

{
    "name": "philipbrown/Nacho",
    "description": "Nacho, nacho man. I want to be a nacho man",
    "license": "MIT",
    "keywords": ["nacho"],
    "authors": [
        {
        "name": "Philip Brown",
        "email": "name@domain.com"
        }
    ],
    "require": {},
    "require-dev": {
        "phpunit/phpunit": "4.0.*"
    },
    "autoload": {
        "psr-4": {
            "PhilipBrown\\Nacho\\": "src"
        }
    }
}

The composer.json file defines meta data about the package. As you can see from the text above, we specify a name, description, license as well as who is responsible for the package.

The three most important sections of this file are require, require-dev and autoload.

require is where you list any dependencies that your package will require.

require-dev is where you list any dependencies that are required to develop your package. In this example I’ve listed PHPUnit which will be used for writing tests.

And finally, autoload specifies how your package should be autoloaded. Composer can handle autoloading your files, but you need to specify how you want it to work. In this example I’ve specified to use psr-4.

Once you have the file saved, go to your command line and run:

composer install

This will create a new directory called vendor and pull in any dependencies that you have requested.

Dot files

Now that you have specified your project’s dependencies and pulled in a local copy using Composer you have what you need to start developing your package.

However, when it comes to distributing your package, you only care about your code and not the dependencies that you’ve pulled in.

Committing your vendor directory to your Git repository would mean a lot of duplicated code when your package was pulled into someone else’s project.

Git allows you to specify which files or directories that you don’t want to include in your repository through a .gitignore file:

/vendor
composer.lock

In this example I’m specifying that the vendor directory and the auto generated composer.lock file should not be included in the Git repository.

If you are going to be hosting your package on GitHub a nice free feature is the ability to integrate with Travis CI, a continuous integration application that will run your tests for you. This is really useful when you start accepting pull requests as you will be able to quickly see if all the tests are passing right from GitHub’s interface.

To integrate with Travis, add a new file called .travis.yml and copy the following text:

language: php

php:
- 5.4
- 5.5
- 5.6
- hhvm

before_script:
- composer self-update
- composer install -prefer-source -no-interaction -dev

script: phpunit

I won’t go into depth about using Travis in this post, but this should be a good start for you to explore the service for yourself.

Your code

Now you are ready to write your code. Open the src directory and create a new file called Nacho.php.

Copy the following code into that file:

<?php namespace PhilipBrown\Nacho;

class Nacho
{
    public function hasCheese($bool = true)
    {
        return $bool;
    }
}

If you have ever looked at the source code of older PHP packages, you would of been expecting a PhilipBrown directory and then a Nacho directory. PSR-4 has done away with that nested directory structure and instead allows you to write your classes directly under the src directory.

Writing tests

Now that we’ve got the code of the package set up, we can start to write some tests. PHPUnit requires a file called phpunit.xml in order to define some settings. Create a new phpunit.xml file in the root of your directory and copy the following code:

<?xml version="1.0" encoding="UTF-8" ?>
<phpunit
  backupGlobals="false"
  backupStaticAttributes="false"
  bootstrap="vendor/autoload.php"
  colors="true"
  convertErrorsToExceptions="true"
  convertNoticesToExceptions="true"
  convertWarningsToExceptions="true"
  processIsolation="false"
  stopOnFailure="false"
  syntaxCheck="false"
>
<testsuites>
<testsuite name="Nacho Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>

If you are unfamiliar with the xml in this file, don’t worry about it, you don’t really need to know what’s going on. This file is basically just defining some settings to use and how the files should be autoloaded.

Next under your tests directory, create a new file called NachoTest.php and copy the following code:

use PhilipBrown\Nacho\Nacho;

class NachoTest extends PHPUnit_Framework_TestCase
{
    public function testNachHasCheese()
    {
        $nacho = new Nacho();
        $this->assertTrue($nacho->hasCheese());
    }
}

Open up your command line and run:

vendor/bin/phpunit

PHPUnit should automatically run the test and give you a green “all tests passed” output.

When writing your tests you need to ensure that your test class extends PHPUnit_Framework_TestCase.

Documentation

The final thing to do is to create a readme.md documentation file. If you are going to be hosting your code on GitHub, this file will be automatically displayed first, so it’s a good way of describing your package, what it does and how it works.

You should also include a license with your open source code. By default, anything you put out into the world is your copyright, so if you want to allow other people to use your code, you need to put a license on it. A good choice is the MIT license.

Pushing to GitHub and Packagist

Now that you’ve finished your package you can push it to GitHub and to Packagist.

GitHub is a hosted git repository service that makes it really easy to collaborate on software.

Packagist is a central directory to find and use PHP packages.

To push your repository to GitHub, create a new repository.

You will be given instructions for adding an existing git repository to GitHub. To push your repository, you will need to run the following two commands from the command line:

git remote add origin git@github.com:username/nacho.git
git push -u origin master

To integrate Packagist and Travis with your repository on GitHub, you need to go into Settings, and then find the two services in the Webhooks & Services section. To integrate both of these services you just need to authenticate your GitHub account and follow some simple instructions.

Conclusion

If you have never developed a released a PHP packaged before, this can be a lot to take in. However, once you’ve set up this process more than once, it becomes second nature.

The structure of a PHP package is really quite simple, and PSR-4 has made it even simpler. Once you know what each bit of the structure is used for, reading through someone else’s PHP package becomes a lot easier.

PHP suffered for many years by not having this package approach to releasing open source software. Nowadays it’s a breeze to pull in someone else’s package so that you don’t have to reinvent the wheel.

Next week I’m going to look at what goes in to a real world PHP package, using lots of the theory that we’ve been looking at for the last couple of weeks!

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.