How to create a PSR-4 PHP package

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
[/bash]
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?](http://culttt.com/2013/01/07/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:
```js
{
"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
[/bash]
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:
```bash
/vendor
composer.lock
[/bash]
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](https://github.com) a nice free feature is the ability to integrate with [Travis CI](https://travis-ci.org/), 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:
```bash
language: php
php:
– 5.4
– 5.5
– 5.6
– hhvm
before_script:
– composer self-update
– composer install –prefer-source –no-interaction –dev
script: phpunit
[/bash]
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
<?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]

./tests/

[/xml]
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:

vendor/bin/phpunit
[/bash]
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](https://github.com/new).
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:
```bash
git remote add origin git@github.com:username/nacho.git
git push -u origin master
[/bash]
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!