Hola amigos La aparición de un administrador de dependencias popular en PHP es uno de los eventos más importantes en la vida de la comunidad PHP. Composer dividió el tiempo en "antes", cuando nuestras bibliotecas autoescritas estaban en archivos zip o simplemente dispersas en carpetas y copiadas por "bolígrafos", solo en casos raros se usaba git o PEAR, y "después" cuando comenzamos a usar composer. Pero, ¿qué pasa si trabaja con un CMS específico, pero no "sabe" qué es el compositor?
Prólogo
Trabajo como líder de equipo en un pequeño estudio web y hace aproximadamente un año tuve que reconsiderar el enfoque para utilizar las mejores prácticas en mi equipo. Para el desarrollo de proyectos, más del 70% de la funcionalidad de los cuales puede llamarse estándar (sitio web, tienda en línea), utilizamos 1C-Bitrix. Como todos los populares CMS 1C-Bitrix tiene una estructura modular y admite la instalación de módulos de terceros. Suena bien, pero en realidad es un poco diferente. Puede desarrollar sus propios módulos y almacenarlos en el archivo copiando los códigos fuente en las carpetas deseadas e instalando los módulos uno a la vez en el panel de control, o puede publicar los módulos en el sitio de 1C-Bitrix Marketplace provisto para esto. Para publicar los módulos solo necesita concluir un acuerdo de asociación y firmar un acuerdo que describa su responsabilidad. Y no estamos hablando de ninguna dependencia de los módulos ni de la instalación de la cadena de dependencias.
Este problema en un grado u otro es inherente a todos los CMS desarrollados "antes". Desmotiva el desarrollo de pequeños módulos (nos parece que "esta funcionalidad simple" no debe convertirse en un módulo), y requiere documentación por separado.
En este artículo, le diré cómo organizar el almacenamiento y el uso de las mejores prácticas en un equipo / empresa. Esto será interesante para aquellos que han enfrentado un problema similar, aquellos que desarrollan sitios web usando CMS, aquellos que desarrollan su propio CMS y aquellos que simplemente desarrollan proyectos en PHP. Vamos!
Primera parte Colocación pública de módulos
La primera tarea que debe resolverse es dónde almacenar los módulos. Los códigos fuente del módulo se pueden almacenar en cualquier repositorio git, mercurial o svn. Para módulos públicos, recomiendo GitHub. En GitHub, tendrá la oportunidad de ver fácilmente el código fuente y mantener la documentación en formato Markdown. Para usar composer, debe crear y completar el archivo composer.json. Esto se puede hacer en el editor, en su IDE o llamando al comando init del compositor. En adelante, no profundizaré en las características básicas y los comandos del compositor, si eres nuevo en el compositor, lee este artículo .
Una vez que haya creado su módulo (por ejemplo, está vacío por ahora) y haya publicado su código en GitHub, debe registrar el módulo en packagist.org . Packagist le ofrecerá configurar los ganchos de GitHub para que cuando los cambios lleguen al repositorio, la información sobre el módulo se actualice en packagist.org.
Segunda parte Instalación Lo mas interesante aqui
Usted, por supuesto, está muy familiarizado con el CMS con el que trabaja, lo que significa que conoce todas las sutilezas de instalar módulos en él. En 1C-Bitrix, la instalación de módulos se realiza en 2 etapas:
- colocando el código fuente del módulo en un directorio específico
<project_dir>/local/modules/<company_name>.<mod_mame>
- Llame a la función RegisterModule (<company_name>. <mod_mame>). Como regla general, todas las acciones de instalación del módulo se describen en el método DoInstall de la clase responsable de instalar y quitar el módulo.
<project_dir>/local/modules/<company_name>.<mod_mame>/install/index.php
La segunda parte es una. Ocultar paquetes en un lugar seguro
De manera predeterminada, el compositor instala todos los paquetes en el <project_dir>/vendor
si el compositor se encuentra en la raíz del proyecto y no ejecuta ningún enlace en sus paquetes. Pero eso es fácil de cambiar.
Necesitamos colocar el archivo composer.json en la raíz del proyecto:
{ "name": "sites/<sitename>", "description": "<SiteName>", "authors": [ { "name": "<developerName>", "email": "<developerEmail>" } ], "minimum-stability": "dev", "require": {}, "config": { "vendor-dir": "local/vendor" } }
En 1C-Bitrix, el código escrito por los desarrolladores generalmente se coloca en el <project_dir>/local
. Por lo tanto, movimos la carpeta del vendor
allí escribiendo en la sección de configuración . Ahora todos los paquetes de terceros se alojarán allí. Pero nuestros módulos deben ubicarse en el directorio <project_dir>/local/modules/<company_name>.<mod_mame>
, ¿qué debo hacer?
Parte dos dos. Complemento de instalación de módulos
Composer tiene varios tipos de paquetes, uno de los cuales composer-plugin es una extensión para el propio compositor. Para que nuestros módulos se instalen como lo requiere el CMS, necesitamos escribir nuestro propio complemento. Para hacer esto, cree un proyecto separado y coloque composer.json en su raíz:
{ "name": "<my_name>/installer", "description": "Plugin for custom installing", "type": "composer-plugin", "license": "MIT", "homepage": "<link to homepage github>", "version": "0.0.1", "authors": [ { "name": "<name>", "email": "<email>" } ], "require": { "composer-plugin-api": "^1.0" }, "require-dev": { "composer/composer": "^1.0" }, "autoload": { "psr-4": { "<my_name>\\installer\\": "" } }, "extra": { "class": "<my_name>\\installer\\Plugin" } }
Hay 3 puntos clave en este archivo:
- "type": "composer-plugin" - le dice al compositor que es un complemento
- carga automática : describe las reglas para las clases de carga automática
- extra : indica qué clase es el complemento
El complemento constará de dos clases:
- El complemento en sí. Agregará su propio instalador al compositor
- instalador, que se dedicará a la instalación de módulos
El complemento simplemente agrega el instalador (archivo: Plugin.php )
namespace company_name\installer; use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; class Plugin implements PluginInterface { public function activate(Composer $composer, IOInterface $io) { $composer->getInstallationManager()->addInstaller(new Bitrix($io, $composer)); } }
A continuación, el instalador en sí ( company_name\installer\Bitrix
). La clase debe heredar de Composer\Installer\LibraryInstaller
y contener los siguientes métodos:
- admite : devuelve verdadero si el instalador admite este tipo de paquete
- getInstallPath : devuelve la ruta donde desea colocar el código fuente del paquete
- instalar / desinstalar / actualizar - paquete instalar / desinstalar / actualizar ganchos
Todos nuestros módulos serán del tipo de módulo bitrix y el instalador debería trabajar con ellos.
public function supports($packageType) { return $packageType === 'bitrix-module'; }
Decidí mantener la integridad del nombre del módulo (que consiste en nombre_de_empresa y nombre_de_modulación separados por un punto) y nombrar los paquetes <my_name>/<company_name>.<mod_mame>
o <company_name>/<company_name>.<mod_mame>
. Si tomamos el nombre del paquete y lo rompemos con una barra, entonces la segunda parte será el nombre del módulo
public function getInstallPath(PackageInterface $package) { $name = explode("/", $package->getName()); return "local/modules/{$name[1]}/"; }
Los métodos initBitrix y getModule implementan el trabajo con la API 1C-Bitrix para instalar el módulo. El método de actualización se implementa en función de qué CMS tiene y cómo libera las actualizaciones del módulo y cómo planea ejecutarlas (archivo: Bitrix.php ).
namespace company_name\installer; use Composer\Installer\LibraryInstaller; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; class Bitrix extends LibraryInstaller { public function supports($packageType) { return $packageType === 'bitrix-module'; } public function install(InstalledRepositoryInterface $repo, PackageInterface $package) { parent::install($repo, $package); $name = explode("/", $package->getName()); $this->initBitrix(); $module = $this->getModule($name[1]); $module->DoInstall(); } public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) { $name = explode("/", $package->getName()); $this->initBitrix(); $module = $this->getModule($name[1]); $module->DoUninstall(); parent::uninstall($repo, $package); } public function getInstallPath(PackageInterface $package) { $name = explode("/", $package->getName()); return "local/modules/{$name[1]}/"; } protected function initBitrix() { $_SERVER['DOCUMENT_ROOT'] = __DIR__ . "/../../../../"; define('STOP_STATISTICS', true); define("NO_KEEP_STATISTIC", "Y"); define("NO_AGENT_STATISTIC","Y"); define("NOT_CHECK_PERMISSIONS", true); require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php'); $GLOBALS['APPLICATION']->RestartBuffer(); } protected function getModule($module) { include_once $_SERVER['DOCUMENT_ROOT'] . "/local/modules/" . $module . "/install/index.php"; $class = str_replace(".", "_", $module); $module = new $class(); return $module; } }
Después de verificar el complemento, el código puede cargarse en GitHub y registrarse con Packagist.
Parte dos tres. Modulo
Volvamos al módulo en sí, que mencionamos en la primera parte. o más bien, a su compositor . json .
{ "name": "<my_name>/<company_name>.<mod_mame>", "type": "bitrix-module", "description": " ", "version": "1.0.0", "time": "11.09.2018", "minimum-stability": "dev", "license": "MIT", "homepage": "<link to homepage github>", "authors": [ { "name": "<name>", "email": "<email>" } ], "require": { "<my_name>/installer": "*" } }
El nombre del módulo debe cumplir con los requisitos del CMS, se debe especificar el tipo con el que trabaja el instalador (en nuestro caso, módulo bitrix ) y en las dependencias el módulo debe tener un complemento (sección requerida ). Después de crear el módulo en sí y verificar su funcionamiento, complete su código en GitHub y regístrelo con Packagist.
Parte dos cuatro. uso de
Permítame recordarle que el proyecto (sitio) en sí tiene aproximadamente el siguiente composer.json
{ "name": "sites/<sitename>", "description": "<SiteName>", "authors": [ { "name": "<developerName>", "email": "<developerEmail>" } ], "minimum-stability": "dev", "require": {}, "config": { "vendor-dir": "local/vendor" } }
ahora podemos enumerar en la sección requerida todos los módulos que necesitamos o llamar al comando
composer require "<my_name>/<company_name>.<mod_mame>" "*"
Puede sentir completamente la utilidad del trabajo realizado si tiene que, por ejemplo, agregar un módulo de autorización al proyecto con el envío de una contraseña en SMS

El módulo en sí contiene un código que es responsable de la lógica de autorización, no debe incluir el código de envío de SMS, ya que otros módulos, por ejemplo, el módulo de notificación, también envían SMS, es mejor hacer que SMS sea un módulo separado para que su código no se duplique. Así es el servicio REST. También puede ser utilizado por otros módulos. Y con todo este complicado esquema, cuando su módulo tira cuatro más junto con él, su instalación sigue siendo igual de simple. Solo ejecuta un comando:
composer require "<my_name>/<company_name>.<mod_mame>" "*"
Y qué y en qué orden descargar e instalar, deja que el compositor decida.
Tercera parte Módulos privados
Amigos, si en todo lo anterior no les gusta que sus módulos estén en el dominio público, entonces lo arreglaremos rápidamente. Para organizar hello storage de módulos, necesitará dos herramientas:
- GitLab es un análogo de GitHub que puede descargar e instalar en sus servidores.
- Satis es un generador de repositorio con el que el compositor puede trabajar.
Para comenzar, instale GitLab y transfiera los códigos fuente de sus módulos. luego instale Satis y describa todos sus módulos en satis.json
{ "name": "ropoName", "homepage": "https://composer.<company_name>.ru/", "repositories": [ { "type": "vcs", "url": "https://gitlab.<company_name>.ru/<my_name>/installer" }, { "type": "vcs", "url": "https://gitlab.<company_name>.ru/<my_name>/<company_name>.<mod_name>" } ], "config": { "gitlab-domains": [ "gitlab.<company_name>.ru" ], "gitlab-token": { "gitlab.<company_name>.ru": "GitLab Token" } }, "require-all": true }
En GitLab, debe crear un token para el que estará disponible la API y especificarlo en satis.json . Después de todas estas manipulaciones, ejecute el comando:
php bin/satis build satis.json ./web
Y en la carpeta web , obtenga un repositorio estático, que puede publicarse en https: // composer . <company_name> .ru /.
composer.json del sitio solo diferirá en que tendrá una sección de repositorios
{ "name": "sites/<sitename>", "description": "<SiteName>", "authors": [ { "name": "<developerName>", "email": "<developerEmail>" } ], "minimum-stability": "dev", "require": {}, "config": { "vendor-dir": "local/vendor" }, "repositories": [ { "type": "composer", "url": "https://composer.<company_name>.ru/" } ] }
Epílogo
Amigos, realmente espero que este artículo les haya sido útil. Y no importa qué CMS use, podrá organizar correctamente el almacenamiento de su código, lo documentará estrictamente, podrá dividir los módulos "gruesos" en muchas dependencias de formato "delgadas" y dejará de tener dificultades para instalar o actualizar los módulos. Buena suerte