Usuario:ManuelRomero/composer
De WikiEducator
< Usuario:ManuelRomero
Revisión a fecha de 04:42 15 abr 2021; ManuelRomero (Discusión | contribuciones)
Saltar a: navegación, buscar
https://medium.com/swlh/composer-everything-i-should-have-known-794225cde691
La autocarga
- La programación actual es claramente estructurada-modular programando con el paradigma orientado a objetos (existen otros paradigmas)
- PHP es un lenguaje para programar orientado a objetos
- Las buenas prácticas de programación nos llevan a crear diferentes objetos estructurados en distintas carpetas implementadas en ficheros independientes.
- Para cargar de forma automática las clases ya hemos visto como realizar un autoload de cada clase que necesitemos.
- La autocarga
- Para ello escribimos el código en la función anónima que recibe en callback como argumento la función
spl_autload_register.
- En esta situación hemos de saber que las clases las tenemos en el directorio Clases del proyecto
spl_autoload_register(function ($clase)){ require("Clases/$clase.php"); }
- La autocarga
- Esto también lo podríamos poner escribiendo la función nominada
function autocarga($clase){ require("Clases/$clase.php"); } spl_autoload_register(autocarga);
- La autocarga
- Esto está bien, y previo a utilizar una clase, cargamos previamente el fichero que lo implementa.
- Por lo tanto, solo están cargados los ficheros que necesitemos en un momento dado.
- Se pueden verificar los ficheros cargados en un momento dado invocando a la función get_included_files() que te devuelve un array con todos los ficheros cargados.
https://www.php.net/manual/es/function.get-include-path.php
- La autocarga
- Como vemos, este método presenta el inconveniente de que tienes todas las clases implementadas en un mismo directorio, o bien en la función de autocarga busca en directorios según el nombre de la clase, lo cual puede ser muy incómodo y poco productivo.
- Para ello, de alguna forma habría que añadir un prefijo a cada nombre de fichero de cada clase que identificar la ubicación de directorio
Complicando la estructura del directorio
- Vamos a trabajar con una estructura compleja de directorios en un proyecto.
- Supongamos la siguiente estructura de clases en nuestro proyecto como se especifica en la imagen
- Estructura de directorios ejemplo
- Este ejemplo implica la siguiente estructura de directorios y las clases correspondientes
- Estructura de directorios ejemplo
- En cada fichero vamos a escribir el método mágico __toString() para que nos diga el nombre de la clase y el directorio en el que nos encontramos
public function __toString() { return "<h2>Estoy en la clase " . get_class ($this) . " ubicado en " . __DIR__; }
- Estructura de directorios ejemplo
- La función get_class($obj) retorna el nombre de la la clase de un objeto
https://www.php.net/manual/es/function.get-class.php
- La constante __DIR__ da el nombre del directorio dónde se ubica el fichero que invocamos
https://www.php.net/manual/es/language.constants.predefined.php
- El objetivo es instanciar un objeto de cada clase y probarlo
- Estructura de directorios ejemplo
- Para poder acceder a cada clase, necesitaríamos tener previamente cargado el fichero que contiene la implementación de la clase.
- Con la función que conocemos de autoload, no podemos hacer de esta forma, podríamos hacer que cada clase tuviera un prenombre que identificara su ubicación y dentro de esta función analizáramos dicho prenombre para localizar el fichero que implementa la clase.
- De momento, para probarlo e identificar nuevos problemas a solucionar, hacemos una carga literal de cada fichero.
- Lo hacemos con objetos ubicados en el directorio librerias
- Estructura de directorios ejemplo
<?php require "./librerias/A.php"; require "./librerias/B.php"; require "./librerias/C.php"; $a = new A(); $b = new B(); $c = new C(); echo $a; echo $b; echo $c;
- Estructura de directorios ejemplo
- Con lo que hemos visto hasta ahora de autocarga estaríamos muy limitados por dos temas:
- Los ficheros diferentes están ubicados en distintos directorios
- Hay clases con el mismo nombre y ubicadas en distinto que realizarán distintas tareas ...
- Para cubrir estas situaciones surge los namespace, si bien no nos van a facilitar la autocarga para lo cual tendremos composer
Concepto de namespace
- Espacio de nombres
- https://diego.com.es/namespaces-en-php
- https://www.php.net/manual/es/language.namespaces.php
- El espacio de nombres o namespace es una forma de organizar las clases mejorando la estructura del proyecto y evitando conflictos (permitir dos clases diferentes con el mismo nombre).
- Es una forma de agrupar clases lo mismo que un directorio agrupa todo su contenido y los permite localizarlo
- namespace
- En java podríamos asemejarlo al concepto de package
- En un sistema operativo tenemos un concepto muy parecido con los directorios, de esta forma no tendremos ningún problema en tener dos ficheros con el mismo nombre (en diferente directorio)
/home/profesor/dwes/notas.ods /home/profesor/bd/notas.ods
- namespace
clases, funciones, interfaces y constantes relacionadas. |
- Declarar un namespace
- Debe de ser la primera instrucción del fichero (Cuidado incluso con espacios en blanco)
<?php namespace MiProyecto; ..
- namespace
- El namespace puede tener varios niveles de jerarquía que se establecen (cuidado con la barra de separación \)
<?php namespace MiProyecto\nivel1\subnivel2; ...
- Volviendo a nuestro ejemplo
- Ahora vamos a establecer un namespace en cada clase
- librerias/comunes/a.php
<?php namespace Librerias\Comunes; class A{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- librerias/comunes/e.php
<?php namespace Librerias\Comunes; class E{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- librerias/privadas/a.php
<?php namespace Librerias\Privadas; class A{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- librerias/privadas/e.php
<?php namespace Librerias\Privadas; class E{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- librerias/a.php
<?php namespace Librerias; class A{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- librerias/b.php
<?php namespace Librerias; class B{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- librerias/c.php
<?php namespace Librerias; class C{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- controlador/comunes/ca.php
<?php namespace Controlador\Comunes; class CA{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- controlador/comunes/cd.php
<?php namespace Controlador\Comunes; class CD{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- controlador/c.php
<?php namespace Controlador; class C{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- controlador/ca.php
<?php namespace Controlador; class CA{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- controlador/cb.php
<?php namespace Controlador; class CB{ public function __toString() { return "<h2>Estoy en la clase ".get_class($this)." ubicado en ".__DIR__; } } ?>
- Index.php
//Primero cargaremos todos los ficheros <?php require "./librerias/A.php"; require "./librerias/B.php"; require "./librerias/C.php"; require "./librerias/comunes/A.php"; require "./librerias/comunes/E.php"; require "./librerias/privadas/A.php"; require "./librerias/privadas/E.php"; require "./controlador/comunes/CA.php"; require "./controlador/comunes/CD.php"; require "./controlador/C.php"; require "./controlador/CA.php"; require "./controlador/CB.php"; ?>
- Index.php
//Ahora instanciamos los objetos $a = new \Librerias\A(); $b = new \Librerias\B(); $c = new \Librerias\C(); $a_comun = new \Librerias\Comunes\A(); $e_comun = new \Librerias\Comunes\E(); $a_p = new mi_A(); $e_p = new \Librerias\Privadas\E(); $c_c=new \Controlador\C(); $c_a=new \Controlador\CA(); $c_b=new \Controlador\CB(); $c_a_comun=new \Controlador\Comunes\CA(); $c_b_comun=new \Controlador\Comunes\CD();
- Index.php
//Y procedemos a visualizarlos echo $a; echo $b; echo $c; echo $a_comun; echo $e_comun; echo $a_p; echo $e_p; echo $c_c; echo $c_a; echo $c_b; echo $c_a_comun; echo $c_b_comun;
- Empleo de use
- Vemos como hemos conseguido solventar el tema de clases con el mismo nombre
- Podemos evitar tener que referenciar toda la estructura de namespace al instanciar una clase
- Para ello usaremos la palabra reservada use
https://www.php.net/manual/es/language.namespaces.importing.php
- Empleo de use
- En el ejemplo anterior
<?php require "./librerias/A.php"; //.... use Librerias\Comunes\A; $a = new A();
- Empleo de use
- También podríamos cambiar crear un alias
<?php require "./librerias/A.php"; //.... use Librerias\Comunes\A as mi_A; $a = new mi_A(); ?> </div> <div class="slide"> {MRM_Resumen|Title=Algunos comentarios| *Cada namespace referencia a una ubicación en un directorio *No tiene por qué coincidir el namespace con el nombre de directorio, Suele coincidir, pero no hay ningún tipo de dependencia }} *Una vez establecido un namespace en una clase, para acceder a él debemos de referenciarlo en su ubicación *Podemos crear un alias con la palabra reservada Use </div> <div class=slide> ===Composer=== *Ahora vamos a ver cómo composer puede solucionar la autocarga *El objetivo será delegar en composer la carga de los ficheros que contienen las clases *Vamos a ver dos técnicas, aunque hay más ;classmap ;psr-4 </div> ;composer <br /> {{MRM_Previos| *Tener instalado composer. *Visitar la página de composer *Es muy fácil de instalar {{MRM_Web| https://getcomposer.org/ }} }} </div> ===composer.json=== *Para especifivar la autocarga, usaremos el ===Ubicar las clases en nuestro proyecto=== ===El namespace=== *Los espacios de nombres realmente ayudan a organizar su código y a evitar conflictos de nombres dentro de la base de código de su proyecto. ===Actualizar/Instalar composer en nuestro proyecto=== ===Usando las clases en nuestro proyecto=== </div> {{MRM_Web|Title=referencias| https://getcomposer.org/doc/04-schema.md#psr-4 https://www.php-fig.org/psr/psr-4/ https://thewebtier.com/php/what-are-namespaces-in-php/ https://thewebtier.com/php/psr4-autoloading-php-files-using-composer/ }} </div >