Normalmente utilizo composer como gestor de dependencias en los proyectos PHP pero quería aprender como crear una librería/paquete (no se bien como traducirlo) que pudiese ser utilizada en otros proyectos de PHP.
En este post vamos a aprender como hacer SimplySlug una pequeña librería para crear slugs, es decir URL’s amigables y legibles por humanos.
Características de una buena librería Open Source en PHP
Para crear una buena librería lo mejor es basarnos en la checklist de phppackagechecklist.com en ella nos indican una serie de características básicas para garantizar un mínimo de calidad en nuestra librería:
- Pick a name wisely: Escoger un buen nombre para la librería, en mi caso he elegido SimplySlug.
- Host source openly: Alojarla en un repositorio de código accesible SimplySlug) esta alojada en mi cuenta de github.
- Autoloader friendly: Utilizar (PSR4)[http://www.php-fig.org/psr/psr-4/] para el autoload y alojar todo el codigo dentro de un carpeta src.
- Distribute via Composer: De eso trata este post 🙂 de cómo crear una librería (SimplySlug) para poder distribuirla vía composer.
- Framework agnostic: Independiente de un framework
- Follow a coding style: Seguir un estandar de código, en nuestro caso hemos seguido PSR2. Además hemos utilizado PHP Coding Standar Fixed para automatizarlo y hemos configurado PHPStorm para seguir el Standard.
- Write unit tests: Escribir test unitarios de la librería, en nuestro caso hemos llegado al 100% de cobertura.
- DocBlock your code: Documentar el código. Bueno esta no sé si la he cumplido del todo….
- Use semantic versioning: Utilizar versionamiento semántico siguiendo el sistema MAJOR.MINOR.PATCH.
- Keep a changelog: Tener un archivo de “histórico de cambios”.
- Use continuous integration: Utilizar un servicio de integración continua para checkear los tests y el
standar de código(todavía no lo he hecho) aquí podemos el proyecto en travis-cCI. - Write extensive documentation: Escribir documentación, como mínimo el README de github. Explicar los requisitos de instalación y cómo utilizarla.
- Include a license: Incluir una licencia, quizás pueda ayudarte http://choosealicense.com.
- Welcome contributions: Ayudar y agradecer a la gente que contribuye.
Empezando con la nueva librería PHP
Para implementar nuestra librería podemos tomar como referencia esta https://github.com/thephpleague/skeleton sino siempre podemos hacerlo poco a poco, para ello el primer paso es crear un archivo de composer. He creado tags para poder ir siguiendo el desarrollo de cada parte:
{
"name": "jeslopcru/simply-slug",
"description": "Simple implementation for convert a string into a slug",
"minimum-stability": "dev",
"license": "MIT",
"authors": [
{
"name": "Jesús López",
"homepage": "http://jesuslc.com"
}
],
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"fabpot/php-cs-fixer": "~2.0@dev"
},
"autoload": {
"psr-4": {"jeslopcru\\SimplySlug\\": "src/"}
}
}
Con este archivo JSON, estamos indicando a composer que nuestro código va a estar en la carpeta src, que vamos a utilizar Phpunit para hacer Test y PHP-CS-Fixer para seguir el estándar PSR-2.
Después de crear el archivo en la carpeta donde queramos comenzar el proyecto, solo tenemos que hacer composer install
y composer descargará todas las librerías necesarias para poder empezar.
Comenzando nuestra primera funcionalidad
Una buena práctica para crear una buena librería es hacerla utilizando TDD, así tendremos test que nos irán ayudando durante el proceso.
En la raíz del proyecto, junto al archivo composer.json creamos el archivo de configuración de Phpunit, llamado phpunit.xml.dist
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
backupGlobals = "false"
backupStaticAttributes = "false"
colors = "true"
convertErrorsToExceptions = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
processIsolation = "false"
stopOnFailure = "true"
syntaxCheck = "false"
bootstrap = "vendor/autoload.php" >
<testsuites>
<testsuite name="Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
En este archivo le estamos indicando a PHPUnit que nuestros tests se encuentran en la carpeta tests y que el autoload del proyecto (archivo en el que se cargan todas las clases necesarias) esta en vendor/autoload.php.
Ahora solo tenemos que crear dentro de nuestra carpeta tests, nuestra clase para test, llama SimplySlugTest.php donde tendremos un primer test para ver que todo está configurado correctamente:
class SimplySlugTest extends \PHPUnit_Framework_TestCase
{
public function nothingTest()
{
$this->assertTre(true);
}
}
Con este test confirmarnos que todo está configurado correctamente, en el momento que todo funcione podemos borrarlo o dejarlo de recuerdo 🙂
Con este test es posible empezar a crear nuestra clase SimplySlug para dejarla más o menos así
namespace jeslopcru\SimplySlug;
class SimplySlug
{
const UNWANTED_CHARS = '/([^a-z0-9]|-)+/';
public function drools($text, $separator = '-')
{
$text = strtolower($text);
$text = $this->replaceUnwantedChars($text, $separator);
return trim($text, $separator);
}
protected function replaceUnwantedChars($text, $separator)
{
return preg_replace(SimplySlug::UNWANTED_CHARS, $separator, $text);
}
}
Podemos utilizar PHP-CS-fixer para ir formateando el código del proyecto siguiendo un estándar como PSR-2. Aunque lo mejor es tener configuradas las opciones de PHPStorm para que autoformatee el código:
Aunque podemos apoyarnos en php-cs-fixer desde la consola o podemos configurar como una external tool de PHPStorm
Para autoformatear los archivos de nuestro proyecto siguiendo un «code style».
Mejorando SimplySlug
Ahora tenemos una librería capaz de hacer slugs de frases en español sin acentos y sin letras extrañas, en el momento que tengamos una frase con caracteres “raros” (ñ, ç,…) dejara de funcionar.
Es necesario convertir estos caracteres para ello podemos crear un array , pero podría ser demasiado largo. Se me ocurrió utilizar un archivo YML y almacenar en él todos los posibles “mapeos” de carácter “raro” a letra.
Para ello necesitamos instalar una extensión de PHP Yaml con la que podremos leer e interpretar archivos YML.
Haciendo un pequeño test para aprender a utilizar Yaml
Como era la primera vez que utilizaba la librería Yaml, he hecho un pequeño test, para pode rutilizarlo con PHPUnit y además aprender a utilizar la librería:
amespace jeslopcru\SimplySlug\tests\YamlHelperTest;
class YamlHelperTest extends \PHPUnit_Framework_TestCase
{
public static $exampleArray = [
['test1' => 'value1'],
['test2' => 'value2'],
[
'test3' => [
'test31' => 'value31',
'test32' => 'value32',
],
],
['test4' => 'value4'],
];
public function testArrayToYaml()
{
$fileYml = __DIR__ . '/example.yml';
file_put_contents($fileYml, yaml_emit(YamlHelperTest::$exampleArray));
}
public function testYamlToArray()
{
$fileYml = __DIR__ . '/example.yml';
$resultArray = yaml_parse(file_get_contents($fileYml));
$this->assertEquals($resultArray, YamlHelperTest::$exampleArray);
}
}
Con esto ya tenemos más posibilidades de utilizar otros idiomas con nuestra librería SimplySlug
Así que ya hemos terminado nuestra librería.
Configurando Travis CI con extensiones de PHP
Ahora solo nos queda poner un sistema de integración continua para facilitar los pull request a nuestra librería y con ello hacer que cualquier persona pueda utilizarla en su proyecto.
Para configurar TravisCI solo tenemos que crear un archivo llamado .travis.yml
language: php
php:
- 5.4
- 5.5
- 5.6
before_script:
- printf "\n" | pecl install yaml-beta
- echo "extension=yaml.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- composer install
script:
- phpunit --configuration phpunit.xml.dist --coverage-text
notifications:
email: false
Con este archivo estamos indicando a Travis que las versiones para probar son PHP 5.4, 5.5, 5.6, además le decimos que tiene que instalar la extension yaml e iniciarl composer. Por utltimo solo indicamos la ruta al archivo de configuración PHPUnit y listo.
Aquí https://travis-ci.org/jeslopcru/simply-slug tenemos la página de SimplySlug en la que ver el estado del proyeto.
Terminado el proyecto
Ahora solo nos queda hacer la documentación. Es la parte más importante ya que será la carta de presentación a otros desarrolladores. La documentación debe ser clara, concisa y con ejemplos de como utilizarla.
Aparte del README, es bueno que empecemos el CHANGESLOG (historial de cambios), el CONTRIBUTING donde explicaremos como contribuir, (coding style, Tests,…) y por último la licencia LICENSE
Probando que todo funciona
Llegados a este punto, tenemos una librería funcionando, pero funcionará dentro de otro proyecto PHP, es hora de averiguarlo.
Para ello en una nueva ruta creamos un archivo composer.json como este
{
"name": "jeslopcru/Usingsimplyslug",
"description": "Using a simple implementation for convert a string into a slug",
"minimum-stability": "dev",
"authors": [
{
"name": "Jesús López",
"homepage": "http://jesuslc.com"
}
],
"repositories": [
{
"type": "git",
"url": "https://github.com/jeslopcru/simply-slug"
}
],
"require": {
"php": ">=5.3.3",
"jeslopcru/simply-slug": "*"
}
}
Con esto y podemos utilizar SimplySlug en esta nuevo proyecto.
Aquí os dejo un pequeño script de ejemplo:
<?php
require 'vendor/autoload.php';
echoln('Prueba de que la librería SimplySlug funciona');
$phrase = "esto será un slug";
echoln('Esta es la frase a probar: ');
echoln($phrase);
$simplySlug = new \jeslopcru\SimplySlug\SimplySlug();
$slugifier = $simplySlug->drools($phrase);
echoln('este es el resultado: ');
echoln($slugifier);
function echoln($message)
{
echo $message;
echo "\n";
}
Conclusiones
Con este post hemos aprendido como hacer una librería que puede utilizarse n otros proyectos de composer. Así podremos tener las nuestro código desacoplado y reutilizarlo en múltiples proyectos de una manera sencilla.
Esta librería esta basada en Slugifier de @keyvanakbary
Un comentario en “¿Cómo hacer una librería utilizable mediante composer?”