====== 03 - Composer ======
**Composer** es un gestor de dependencias para PHP. Esto significa que nos permite gestionar los paquetes usados en nuestros proyectos de forma automática, sin necesidad de tener que gestionarlos nosotros manualmente.
Cuando trabajamos en un proyecto PHP es habitual incorporar librerías de terceros para evitar tener que hacer todo el trabajo desde cero. Para hacerlo, debemos ir a la web donde está publicada la librería que queremos usar, descargarla y añadirla a nuestro proyecto. Si a mitad de nuestro proyecto cambian la versión de esa librería, deberíamos borrar la anterior, volver a descargar y añadir la nueva.
Además, muchas librerías de terceros dependen, a su vez, de otras, con lo que tendríamos que mantenerlas a mano.
Para solucionar todos estos problemas (y otros), tenemos los gestores de paquetes, que nos ayudan a automatizar todas esas tareas.
Los desarrolladores en //Node.js// ya están familiarizados con un gestor de paquetes como **npm**, y, desde hace unos años, los programadores PHP cuentan con //Composer//, lo cual nos ahorra mucho tiempo y esfuerzo.
===== Instalar Composer =====
//Composer// es multiplataforma (funciona el Linux, Windows y Mac). Para instalarlo de forma sencilla en Linux o Mac, podemos ir a su página de [[https://getcomposer.org/download/|descarga]], copiar el //script// de instalación en la terminal y ejecutarlo.
Este //script// descargará el instalador de //Composer// (composer-setup.php), verificará el archivo descargado, ejecutará el instalador y por último lo eliminará.
Si te da un error a mitad de la ejecución del //script// anterior como el siguiente:
{{ :clase:daw:dws:1eval:composer01.png?400 |}}
Puede que tengas que darle permiso para ejecutar la orden PHP //composer-setup.php//:
{{ :clase:daw:dws:1eval:composer02.png?400 |}}
Con esto ya tenemos instalado //Composer//. Para comprobar nuestra instalación ejecutamos //composer --version// en la terminal y debería salirnos la versión instalada.
{{ :clase:daw:dws:1eval:composer03.png?400 |}}
Para instalarlo en Windows simplemente tenemos que bajarnos el [[https://getcomposer.org/Composer-Setup.exe|instalador]] y ejecutarlo.
==== Hacer accesible Composer desde cualquier sitio ====
Si hemos instalado //Composer// en Windows, el instaldor ya se encarga de configurar el //path// para que podamos ejecutar //Composer// desde cualquier directorio.
Por el contrario, si lo hemos instalado en Linux o Mac, sólo podremos utilizarlo en la carpeta donde lo hayamos instalado. Para que sea accesible desde cualquier sitio debemos mover //Composer// a un directorio global.
sudo mv composer.phar /usr/local/bin/composer
Ahora deberíamos poder utilizar //Composer// en cualquier proyecto que creemos sin necesidad de tener que instalarlo cada vez.
===== Usar Composer =====
//Composer// tiene una lista de comandos que nos permite realizar diferentes tareas.
==== Inicializar Composer ====
Para inicializar //Composer//, desde un terminal ejecuta la siguiente order:
composer init
Esta orden inicializará //Composer// y tendremos que definir una serie de parámetros de nuestro proyecto (puedes dejar las opciones que vienen por defecto).
Si miramos nuestra carpeta, veremos que nos ha creado un nuevo archivo llamado //composer.json//:
{{ :clase:daw:dws:1eval:composer04.png?200 |}}
Cuyo contenido será algo parecido a ésto:
{
"name": "cesar/composer",
"authors": [
{
"name": "César Guijarro",
"email": "cguijarro@fpmislata.com"
}
],
"require": {}
}
En este archivo tenemos el nombre del proyecto, los autores y las librerías que utilizamos (en principio ninguna) en la sección //require//.
También puedes crear el archivo //composer.json// a mano, aunque la opción anterior es más cómoda y te evitas posibles errores.
==== Añadir librerías externas ====
Para añadir librerías externas, usamos la orden **composer require nombre_librería**. Por ejemplo, vamos a añadir una librería para crear //timers// de forma sencilla llamada //phpunit/php-timer//:
{{ :clase:daw:dws:1eval:composer06.png?400 |}}
Si miramos nuestra carpeta del proyecto veremos que se ha creado un archivo nuevo y una nueva carpeta:
{{ :clase:daw:dws:1eval:composer07.png?400 |}}
Por ahora podemos olvidarnos del archivo //composer.lock// (**no debemos borrarlo**). Este archivo tiene el registro exacto de las versiones de dependencia que se han instalado.
La carpeta //vendor// es la que contendrá todos los archivos de las librerías que hemos instalado en nuestro proyecto (y otras librerías si éstas últimas las necesitasen). Si añadiésemos otras librerías, se añadirían a esta carpeta automáticamente, con lo que nosotros no tendríamos que preocuparnos de nada.
Desde este momento, ya podemos usar la librería recién instalada:
$timer = new SebastianBergmann\Timer\Timer;
$timer->start();
foreach (\range(0, 100000) as $i) {
// ...
}
$duration = $timer->stop();
echo "Duración en milisegundos: " . $duration->asMilliseconds();
Si ejecutamos el ejemplo tal y como está no nos funcionará, ya que primero tenemos que incluir los ficheros de la librería mediante //include// o //require//.
Ésto puede ser algo tedioso, ya que si usamos varias librerías de terceros deberemos incluir todas ellas en nuestro archivo PHP.
Por fortuna, hay una solución sencilla para ello: usar un **autocargador de clases**. Básicamente, PHP dispone de un mecanismo para intentar cargar las clases que no están definidas todavía como último recurso.
Si intentamos acceder a una clase que no hemos definido, PHP comprobará si existe un **Autoload**, y, si es así, ejecutará el código incluido en él. Ésto se suele utilizar con frecuencia para no tener que incluir todos los archivos necesarios en nuestra aplicación PHP.
//Composer// ya viene con un //autoloader// propio, con lo que para utilizarlo sólo tendremos que incluirlo (sólo el //autoloader//, sin ningún otro archivo de las librerías que utilicemos) al principio de nuestro archivo de la siguiente forma:
require __DIR__ . '/vendor/autoload.php';
$timer = new SebastianBergmann\Timer\Timer;
$timer->start();
foreach (\range(0, 100000) as $i) {
// ...
}
$duration = $timer->stop();
echo "Duración en milisegundos: " . $duration->asMilliseconds();
Ahora sí, al ejecutar el archivo debería mostrarnos el resultado:
Duración en milisegundos: 3.159912
===== La carpeta vendor =====
Como hemos visto, la carpeta //vendor// se crea automáticamente cuando instalamos alguna librería externa a nuestro proyecto, y es donde se almacena el código de todas esas librerías.
Por esta razón, esta carpeta puede llegar a ocupar bastante tamaño, con lo que subir nuestro proyecto a un servidor o a otro ordenador puede tardar mucho tiempo (incluso puede haber servidores que no te permitan subir todo el proyecto por excesivo tamaño).
Afortunadamente, //Composer// tiene una solución para eso. A la hora de trasladar nuestro proyecto podemos ignorar la carpeta //vendor// y utilizar la siguiente orden para instalar de nuevo todas nuestras dependencias:
composer install
Por ejemplo, si borras la carpeta //vendor// del ejemplo anterior, lógicamente cuando ejecutes el archivo te dará un error, ya que no existen las librerías referenciadas (ni el //autoload.php//).
{{ :clase:daw:dws:1eval:composer08.png?400 |}}
Si ejecutamos ahora la orden anterior (//composer install//), veremos como vuelve a crear la carpeta //vendor//, con lo que ya podremos ejecutar el archivo sin problemas:
{{ :clase:daw:dws:1eval:composer09.png?400 |}}
Por lo tanto, siempre es recomendable no subir la carpeta vendor y ejecutar primero la sentencia //composer install// cuando instalemos nuestro proyecto en otra ubicación, con lo que nos ahorramos subir todos los archivos de las librerías usadas.
Existen muchas otras opciones al utilizar //Composer// (como //composer update//, que actualiza nuestras librerías externas). Veremos algunas de ellas a lo largo del curso.
Otra de las opciones de //Composer// es cargar automáticamente las clases a través de su //namespace// (similar a los //packages// de Java), como veremos en los siguientes temas. Además, también podemos autocargar archivos individuales, lo que puede ser muy útil para cargar ficheros con funcionalidades globales a nuestros proyectos (como //helpers//).
===== Repositorion de paquetes =====
Para encontrar librerías externas útiles a nuestro proyecto, podemos utilizar [[https://packagist.org/|Packagist]], web que es un repositorio de paquetes php.
{{ :clase:daw:dws:1eval:composer10.png?400 |}}
Aquí podemos buscar las librerías hechas por terceros que nos pueden ayudar en nuestro proyecto. Además, podemos publicar nuestras propias librerías, y tiene, entre otras cosas, una guía rápida para utilizar //Composer//.