Like a composer who can’t wait to conduct a great symphony, I couldn’t wait to get my hands on Composer, a PHP dependency management tool.
You could say this blog post is my "Ode to Joy" about using Composer. It was fun watching it update all my libraries on just a single command:
composer update
But I shouldn’t have all the fun. I’d like to help you incorporate third-party libraries into a project by using Composer. In this post, we’ll create a test PHP project and run test cases using phpunit.
Before we hit the “update” button, though, first let’s look at what Composer is, and why you’ll need it. After all, as my Acquia colleague Chris Pilakas aptly describes in Good Engineer/Bad Engineer, good engineers first focus on the “what” and the “why” before moving onto the “how.”
In a nutshell, Composer manages all of your project’s dependencies by downloading them in a clean directory and tracking the package versions. It’s simple and easy to use.
Composer can play a vital role when you start a project in PHP. It doesn’t want to reinvent the wheel for every single function of your project; rather it wants to use third-party libraries. Before Composer, you had to manually download and manage these libraries. But now, Composer makes it easier to download and maintain the latest version of third-party libraries.
Picture this: Let’s say you want to use PHPUnit for testing and Log for logging your project. You simply tell Composer that you need this particular version of PHPUnit for your project and it is installed locally, in your project directory. After installation, it’s Composer’s responsibility to look for PHPUnit library and download it and the other packages required by the PHPUnit.
So that’s the “what” and “why.” Now, it’s time to learn how Composer works. Here’s a step-by-step guide.
Step 1
Install the composer using Homebrew for OSX, or download it directly. Let's install it globally, so that it's available from anywhere.
$ curl -sS https://getcomposer.org/installer | php
$ mv composer.phar /usr/local/bin/composer
(Note: Might need to use sudo
is case of permission issues.)
Step 2
Validate the installation
$ composer --version
It should return something like Composer version 1.0-dev (829199c0530ea131262c804924f921447c71d4e8) 2015-03-16 13:11:02
Step 3
After successfully installing Composer, create a JSON file named “composer.json” in the root of your project. This file contains simple things like: “name” “license” “authors” “dependencies.” For this blog, the project directory name is “php-composer-example”. So, with help from the box below, go ahead and create the “composer.json” file.
{
"name": "charu/composer-example",
"require": {
"phpunit/phpunit": "~3.0",
"psr/log": "1.0.*@dev"
}
}
require
here states that phpunit and psr is a required dependency, and phpunit version ~3.0
means package version >=3.0, <4.0
is allowed. With the @dev
constraint in psr/log package, composer installs the dev version of the package. Also, if you need to add unstable or dev package, say version dev-master
, include flag "minimum-stability": "dev"
and "prefer-stable": true
as this flag enables composer to prefer more stable packages over unstable ones.
Understanding the Package Name and version:
Package name consists of two parts: first is the vendor name, the other one is the project name. In above case, vendor and project name is phpunit. However, in other dependency applications, vendor is "psr" and project is "log". In Composer, this package name method allows a user to have the same project name with different vendor names.
Package versioning follows the schemantic versioning notation. Here is a good article that explains composer versioning in more detail.
Step 4
Now it's time to install the dependencies.
$ composer install
Once you run the command in the box above, Composer will install all the required packages in the vendor directory.
Step 5
Composer install
generates the autoload file in the vendor directory. There are two ways to use the third party libraries installed by composer:
- You just have to include this code into your file.
<?php
require 'vendor/autoload.php';
?>
- Create a bootstrap.php and phpunit.xml file under your project, so when you execute the phpunit test command from your terminal, it will run the test for all your Test.php files.
It’s time to execute these steps. Start by adding these files in your project.
path\_to\_project/test/bootstrap.php
<?php
$autoloadFile = __DIR__.'/../vendor/autoload.php';
if (!file_exists($autoloadFile)) {
throw new RuntimeException('Install dependencies to run phpunit.');
}
require_once $autoloadFile;
?>
path\_to\_project/phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<testsuites>
<testsuite name="small">
<directory suffix="Test.php">test</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
path\_to\_project/test/ComposerExampleTest.php
<?php
/**
* Class ComposerExampleTest
*/
class ComposerExampleTest extends PHPUnit_Framework_TestCase
{
/**
* Test Case 1
*/
public function testCase1()
{
$this->assertTrue(true, "Returns True");
$this->assertEquals(2, 1+1);
}
/**
* Test Case 2
*/
public function testCase2()
{
$this->assertFalse(false, "Returns False");
$this->assertNotEquals(2, 2+1);
}
}
?>
path\_to\_project/test/ExampleTest.php
<?php
/**
* Class ExampleTest
*/
class ExampleTest extends PHPUnit_Framework_TestCase
{
/**
* @var string
*/
private $id = "";
/**
* Test Case 3
*/
public function testExampleSuccess()
{
$this->id = "123";
$this->assertClassHasAttribute('id', 'ExampleTest');
}
}
?>
Final directory structure should look like this:
Now, run this command from project root:
$ vendor/bin/phpunit
Notes:
Add your own code to the autoloader by adding autoload field in composer.json. Below code uses PSR-4 autoloader.
{
"autoload": {
"psr-4": {
"Charu\\ComposerExample\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Charu\\ComposerExample\": "test/"
}
},
}
Run this command to get the latest version of the required packages.
$ composer update
Sometimes we need to update the composer itself.
$ composer self-update
Good links