Building reusable library with Composer
I'm building BB Code Parser library which will be publish on GitHub soon. On this little project I will write series of articles how to make reusable PHP code like a boss.
What is library?
Library is collection of classes and/or functions that provide concepts to solve some shit. Main feature of library is reusable behavior. You can use it in as many project as you want. It's my definition so you likely find other/better definition on the web. Good example of library in PHP world in swift mailer that is library for sending an emails or Gregwar\Image that is library for resize images and do some other manipulations with them.
Init composer.json
I presume you have composer installed on machine. Open console, navigate to some nice directory where we put our library code. Just type in your console: composer initAnswer to composer prompts and you should end like this where you can everything confirm by typing yes.
{
"name": "matok/bbcode-parser",
"description": "BB Code Parser: Turns BB Code to any format you like.",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Matej Kuna",
"email": "mat.kuna@gmail.com"
}
],
"require": {}
}
Do you confirm generation [yes]?
Fill it by your way. If you don't know anything just hit return. Most import is name
and it has format vendor/name
. There can be many parsers, but only one and best one from matok
rule them all. Emm.. pardon me. After confirm generation you should have this file in directory:
$ ls -l
total 1
-rw-r--r-- 1 Matej Kuna 197121 242 Jun 29 20:23 composer.json
Define requirements and autoloading
I make two more directories and now it looks like:$ ls
composer.json library/ tests/
I put source code to library directory and unit tests to tests directory. Now I open composer.json
in editor and add some more information, my whole file now looks like this:
{
"name": "matok/bbcode-parser",
"description": "BB Code Parser: Turn BB code to any format you like.",
"homepage": "http://matok.me.uk",
"keywords": ["bbcode", "phpbb", "bb code", "parser", "html converter"],
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Matok",
"email": "mat.kuna@gmail.com"
}
],
"autoload": {
"psr-4": {
"Matok\\BBCode\\": "library/"
}
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"phpunit/phpunit": "dev-master"
},
"autoload-dev": {
"psr-4": {
"Matok\\BBCode\\Tests\\": "tests/"
}
}
}
This reflects directories I mentioned. I want use PHP 7 (I use features from this version), therefore require
section contains minimal version of PHP. During development I am using unit test so phpunit/phpunit
has place in require-dev
section.
Last configuration I want to setup is PSR4 autoloading which means all files placed directly in library/ directory has namespace Matok\BBCode
. To be sure what I am saying:
$ ls
Converter/ Exception/ Parser.php Token/
$ head -7 Parser.php
<?php
namespace Matok\BBCode;
class Parser
{
private $text;
Working with you library
Everything is configured now. To check that config is correct type in console composer install, output:
$ composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Writing lock file
Generating autoload files
New files should be here
$ ls
composer.json composer.lock library/ tests/ vendor/
Important file is vendor/composer/autoload_psr4.php because it holds mapping between namespace and directory
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Matok\\BBCode\\Tests\\' => array($baseDir . '/tests'),
'Matok\\BBCode\\' => array($baseDir . '/library'),
);
In situation you need to change directory or add new directory in composer.json
you must do composer install again or maybe a little faster way is composer dump-autoload
Epilogue
When everything is properly set up I can write whole library logic and also unit tests to its functionality. Unit test result looks like this:
$ phpunit
PHPUnit 6.0.10 by Sebastian Bergmann and contributors.
................................................................. 65 / 70 ( 92%)
..... 70 / 70 (100%)
Time: 644 ms, Memory: 12.00MB
OK (70 tests, 70 assertions)
Well, library is written & tested. I intentionally omit GIT or any type of versioning system, but I presume we are using for the whole time.
I'm foreigner. Where I live my friends call me Maťok.