Gerenciando seus módulos para CMS usando o compositor

Olá amigos! O surgimento de um gerenciador de dependência popular em PHP é um dos eventos mais importantes na vida da comunidade PHP. O compositor dividiu o tempo em “antes” - quando nossas bibliotecas auto-escritas estavam em arquivos zip ou simplesmente espalhadas em pastas e copiadas por “canetas”, apenas em casos raros o git ou o PEAR era usado e “depois” quando começamos a usar o compositor. Mas e se você trabalha com um CMS específico, mas ele "não sabe" o que é o compositor?


Prefácio


Trabalho como líder de equipe em um pequeno estúdio na web e, há um ano, tive que reconsiderar a abordagem para usar as melhores práticas da minha equipe. Para o desenvolvimento de projetos, mais de 70% das funcionalidades podem ser chamadas de padrão (site, loja online), usamos o 1C-Bitrix. Como todos os populares CMS 1C-Bitrix, possui uma estrutura modular e suporta a instalação de módulos de terceiros. Parece bom, mas na realidade é um pouco diferente. Você pode desenvolver seus próprios módulos e armazená-los no arquivo morto, copiando os códigos-fonte para as pastas desejadas e instalando os módulos um de cada vez no painel de controle, ou pode publicar os módulos no site do 1C-Bitrix Marketplace fornecido para isso. Para publicar os módulos, você só precisa concluir um contrato de parceria e assinar um contrato que descreva sua responsabilidade. E não estamos falando de nenhuma dependência dos módulos e instalando a cadeia de dependências.


Esse problema, em um grau ou outro, é inerente a todos os CMS desenvolvidos “antes”. Desmotiva o desenvolvimento de pequenos módulos (parece-nos que “essa funcionalidade simples” não deve ser transformada em módulo) e requer documentação separada.


Neste artigo, mostrarei como organizar o armazenamento e o uso das melhores práticas em uma equipe / empresa. Isso será interessante para aqueles que enfrentaram um problema semelhante, aqueles que desenvolvem sites usando o CMS, aqueles que desenvolvem seu próprio CMS e aqueles que simplesmente desenvolvem projetos em PHP. Vamos lá!


Parte I Colocação pública de módulos


A primeira tarefa que precisa ser resolvida é onde armazenar os módulos. Os códigos-fonte do módulo podem ser armazenados em qualquer repositório git, mercurial ou svn. Para módulos públicos, eu recomendo o GitHub. No GitHub, você terá a oportunidade de visualizar facilmente o código fonte e manter a documentação no formato Markdown. Para usar o compositor, você precisa criar e preencher o arquivo composer.json. Isso pode ser feito no editor, no seu IDE ou chamando o comando init do compositer. A seguir, não vou me aprofundar nos recursos básicos e nos comandos do compositor, se você é novo no compositor, leia este artigo .


Depois de criar seu módulo (por exemplo, ele está vazio por enquanto) e postar seu código no GitHub, é necessário registrar o módulo no packagist.org . O Packagist oferecerá a configuração dos ganchos do GitHub para que, quando as alterações chegarem ao repositório, as informações sobre o módulo sejam atualizadas no packagist.org.


Parte Dois Instalação O mais interessante aqui


Você, com certeza, está muito familiarizado com o CMS com o qual trabalha, o que significa que conhece todas as sutilezas da instalação de módulos nele. No 1C-Bitrix, a instalação dos módulos ocorre em 2 etapas:


  • colocando o código-fonte do módulo em um diretório específico <project_dir>/local/modules/<company_name>.<mod_mame> diretório do projeto <project_dir>/local/modules/<company_name>.<mod_mame>
  • Chame a função RegisterModule (<nome da empresa>. <Nome_moda>). Como regra, todas as ações de instalação do módulo são descritas no método DoInstall da classe responsável pela instalação e remoção do módulo. <project_dir>/local/modules/<company_name>.<mod_mame>/install/index.php

A parte dois é uma. Ocultando pacotes em um local seguro


Por padrão, o compositer instala todos os pacotes no diretório <project_dir>/vendor se o compositor estiver localizado na raiz do projeto e não executar nenhum gancho em seus pacotes. Mas isso é fácil de mudar.


Precisamos colocar o arquivo composer.json na raiz do projeto:


 { "name": "sites/<sitename>", "description": "<SiteName>", "authors": [ { "name": "<developerName>", "email": "<developerEmail>" } ], "minimum-stability": "dev", "require": {}, "config": { "vendor-dir": "local/vendor" } } 

No 1C-Bitrix, o código escrito pelos desenvolvedores geralmente é colocado no diretório <project_dir>/local . Portanto, movemos a pasta do vendor lá por uma entrada na seção de configuração . Agora todos os pacotes de terceiros serão hospedados lá. Mas nossos módulos devem ser colocados no diretório <project_dir>/local/modules/<company_name>.<mod_mame> , o que devo fazer?


Parte dois dois. Plugin de Instalação de Módulos


O Composer possui vários tipos de pacotes, um dos quais o compositor-plugin é uma extensão para o próprio compositor. Para que nossos módulos sejam instalados conforme exigido pelo CMS, precisamos escrever nosso próprio plugin. Para fazer isso, crie um projeto separado e coloque composer.json em sua raiz:


 { "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" } } 

Existem 3 pontos principais neste arquivo:


  • "type": "compositor-plugin" - informa ao compositor que é um plugin
  • autoload - descreve as regras para as classes de carregamento automático
  • extra - indica qual classe é o plug-in

O plugin consistirá em duas classes:


  • o próprio plugin. Ele adicionará seu próprio instalador ao compositor
  • instalador, que estará envolvido na instalação dos módulos

O plugin simplesmente adiciona o instalador (arquivo: 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)); } } 

Em seguida, o próprio instalador ( company_name\installer\Bitrix ). A classe deve herdar de Composer\Installer\LibraryInstaller e conter os seguintes métodos:


  • suporta - retorna verdadeiro se o instalador suportar este tipo de pacote
  • getInstallPath - retorna o caminho em que você deseja colocar o código-fonte do pacote
  • install / uninstall / update - ganchos de instalação / desinstalação / atualização de pacotes

Todos os nossos módulos serão do tipo bitrix-module e o instalador deve trabalhar com eles.


 public function supports($packageType) { return $packageType === 'bitrix-module'; } 

Decidi manter a integridade do nome do módulo (ele consiste em nome_da_empresa e nome_da_moda separados por um ponto) e nomeie os pacotes <my_name>/<company_name>.<mod_mame> ou <company_name>/<company_name>.<mod_mame> . Se pegarmos o nome do pacote e quebrá-lo com uma barra, a segunda parte será o nome do módulo


 public function getInstallPath(PackageInterface $package) { $name = explode("/", $package->getName()); return "local/modules/{$name[1]}/"; } 

Os métodos initBitrix e getModule implementam trabalho com a API 1C-Bitrix para instalar o módulo. O método de atualização é implementado com base no CMS que você possui, como você libera as atualizações do módulo e como planeja executá-las (arquivo: 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; } } 

Depois de verificar o plug-in, o código pode ser carregado no GitHub e registrado no Packagist.


Parte dois três. Módulo


Vamos voltar ao próprio módulo, que mencionamos na primeira parte. ou melhor, ao seu 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": "*" } } 

O nome do módulo deve atender aos requisitos do CMS, o tipo deve ser especificado com o qual o instalador trabalha (no nosso caso, módulo bitrix ) e nas dependências o módulo deve ter um plug-in (seção requer ). Após criar o próprio módulo e verificar sua operação, preencha seu código no GitHub e registre-o no Packagist.


Parte dois quatro. uso de


Deixe-me lembrá-lo de que o próprio projeto (site) possui aproximadamente o seguinte compositor.json


 { "name": "sites/<sitename>", "description": "<SiteName>", "authors": [ { "name": "<developerName>", "email": "<developerEmail>" } ], "minimum-stability": "dev", "require": {}, "config": { "vendor-dir": "local/vendor" } } 

agora podemos listar na seção exigir todos os módulos que precisamos ou chamar o comando


 composer require "<my_name>/<company_name>.<mod_mame>" "*" 

Você pode sentir plenamente a utilidade do trabalho realizado se, por exemplo, adicionar um módulo de autorização ao projeto enviando uma senha no SMS


imagem


O módulo em si contém um código responsável pela lógica de autorização; você não deve incluir o código de envio de SMS, porque outros módulos, por exemplo, o módulo de notificação, também enviam SMS; é melhor fazer do SMS um módulo separado para que seu código não seja duplicado. O mesmo acontece com o serviço REST. Também pode ser usado por outros módulos. E com todo esse esquema complicado, quando o módulo puxa mais quatro, a instalação permanece simples. Basta executar um comando:


 composer require "<my_name>/<company_name>.<mod_mame>" "*" 

E o que e em que ordem para baixar e instalar, deixe o compositor decidir.


Parte três. Módulos privados


Amigos, se, em todas as opções acima, você não gostar que seus módulos sejam de domínio público, iremos corrigi-lo rapidamente. Para organizar o hello storage dos módulos, você precisará de duas ferramentas:


  • GitLab é um análogo do GitHub que você pode baixar e instalar em seus servidores.
  • Satis é um gerador de repositório com o qual o compositor pode trabalhar.

Para começar, instale o GitLab e transfira os códigos-fonte dos seus módulos para ele. instale o Satis e descreva todos os seus módulos em 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 } 

No GitLab, você precisa criar um token para o qual a API estará disponível e especificá-lo em satis.json . Após todas essas manipulações, execute o comando:


 php bin/satis build satis.json ./web 

E na pasta da Web , obtenha um repositório estático, que pode ser publicado em https: // compositer . <Nome da empresa> .ru /.


O compositer.json do site diferirá apenas no fato de ter uma seção de repositórios


 { "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/" } ] } 

Posfácio


Amigos, espero realmente que este artigo tenha sido útil para você. E não importa qual CMS você usa, você poderá organizar corretamente o armazenamento do seu código, documentará-o estritamente, poderá dividir os módulos "grossos" em muitas dependências de formatação "finas" e deixará de ter dificuldade em instalar ou atualizar os módulos. Boa sorte

Source: https://habr.com/ru/post/pt429150/


All Articles