Proyecto clonado con inclusiones dinámicas en composer.json

Tengo un server de aplicaciones, es como un sistema de blog (my wordpress killer). Se basa en php alojado en github y usa composer para administrar dependencies. Cada installation está alojada en mi server (hago la installation para ellos). Cuando un cliente requiere un nuevo "complemento / complemento", creo un nuevo package y lo albergo en un repository de alojamiento privado. El problema viene cuando necesito agregar un nuevo package:

Client 1. - package for calculate prices Client 2. - package for show a welcome message Client 3. - package for add a calendar 

Mi aplicación tendrá todos los packages listos para usarse en todas las instancias porque los estoy requiriendo a través del compositor:

 "require": { "killer/calculate": "dev-master", "killer/message": "dev-master", "killer/calendar": "dev-master" } 

Ahora imagino si tengo clientes 2K y todos ellos están solicitando packages personalizados. ¿Cómo puedo proporcionar una aplicación (clonada de forma masiva) pero simplemente guardando en cada installation solo los packages que necesita cada cliente?

Solución hipotética

Estaba buscando (si es posible) algo como lo siguiente. Para cada installation, cree un file manualmente donde su contenido especifique el package que se requerirá. Por ejemplo, digamos que la installation de cada cliente tiene algo como esto:

 //composer.json "require": { } //plugins.json (this file is ignonetworking via .gitignore) { "killer/calculate": "dev-master" } 

Luego, de alguna manera le dice a composer.json que solicite los datos de plugins.json . De esta manera evito crear un enorme composer.json JSON comparte packages innecesarios para todos los clientes.

Hay una request de function para permitir a composer.json extender otro file. Deberías comentarlo para llamar su atención.

La forma en que usaría esa function es crear un file default.json que contenga todos sus contenidos habituales de composer.json , incluida una sección de require que enumera todos los packages comunes que necesita.

 // default.json { "require": { "php": ">=5.4.0" } } 

Luego, tenga un file composer.json para cada proyecto que amplíe y / o sobrescriba default.json siguiente manera:

 // composer.json { "require": { "killer/calculate": "dev-master" }, "extends": "default.json" } 

El resultado final sería:

 { "require": { "php": ">=5.4.0", "killer/calculate": "dev-master" } } 

Si no puede esperar en la request de fusión, puede ir a la salida del autor del autor de la request de fusión y probarla.

Parece que ha creado su propio ecosistema de packages. Por lo tanto, podría trabajar independientemente de Packagist y simplemente alojar todos los packages, probablemente usando Satis.

La principal sugerencia que tengo es presentar su aplicación como un package en este ecosistema.

Su aplicación composer.json contiene solo los packages relevantes para la aplicación en sí.

 { "name": "better/application", "require": { "another/library": "1.0.0", "another/framework": "1.2.3", "another/generator": "2.1.3" }, "require-dev" : { "phpunit/phpunit" : "4.*", } } 

Creo que esa "clonación" de la aplicación para el cliente / cliente no es una buena idea, ya que ignora que los complementos tienen dependencies en una versión específica de la aplicación, que no siempre es "última" o "dev-master". Deje Composer extraer la aplicación por versión para cada cliente.

De esta manera evito crear un enorme composer.json JSON comparte packages innecesarios para todos los clientes.

  • crear un repository por cliente / cliente nuevo
  • agregue la aplicación en sí y los packages solicitados por el cliente dentro de composer.json
  • agregar una configuration de cliente en la parte superior

Por ejemplo, el composer.json para Client1:

 { "name": "better/application-for-client1", "require": { "better/application": "1.0.0", "better/app-calculate": "1.2.3" } } 

Por ejemplo, el composer.json para Client2:

 { "name": "better/application-for-client2", "require": { "better/application": "1.0.1", "better/app-calculate": "1.2.4", "better/app-message": "2.0.0" } } 

Cada cliente puede tener su propia configuration, requiriendo una versión diferente de su aplicación con diferentes packages / complementos de aplicaciones adicionales (aquí se indica con el prefijo "aplicación-").

Al final, tiene dos files esenciales para un cliente: un composer.json y un file de configuration.

(La forma en que la aplicación detecta los modules disponibles es otra historia. Al less, la carga automática funcionará de la caja, cuando registra el autocargador Composers durante el arranque de la aplicación).


(Nota: si su aplicación es una aplicación de varios sitios, entonces puede replace "clonación" por "enlace simbólico". Con sitios múltiples, me refiero a una aplicación que se ejecuta desde un lugar central utilizando una identificación del sitio (a menudo identificación del cliente). Si tiene la carpeta de la aplicación con todos los packages para el desarrollo en una carpeta monolítica, cree una carpeta de relase limpiando los elementos de desarrollo, para que obtenga una versión de lanzamiento con una configuration pnetworkingeterminada en blanco. Luego, haga un enlace simbólico de la aplicación, los packages solicitados a la carpeta del cliente y colocar una configuration en la parte superior. Este enfoque puede ahorrar bastante espacio en disco y no involucra Composer en absoluto).

También le animo a utilizar el enfoque propuesto por Jens A. Koch en su respuesta, con un file composer.json para cada cliente y que requiera la aplicación principal y todos los complementos necesarios. Composer es compatible con este escenario bastante bien y quiero señalar los puntos de partida:

Tipos de compositor

Composer permite especificar types para packages. Puede definir su propio tipo para marcar complementos para su aplicación como tal. Muchos proyectos de código abierto (por ejemplo, Symfony con packages) han adoptado este enfoque para su ecosistema de plugins.

Instaladores personalizados

Puede registrar instaladores personalizados que se pueden ejecutar para un type específico de package de compositor (es decir, el tipo que definió para sus complementos). Luego puede personalizar el process de installation de sus complementos, lo que significa que puede:

  • mover sus complementos personalizados a ubicaciones específicas,
  • ajustar automáticamente las configuraciones de los complementos,
  • y lo más importante: proporcione un mecanismo que permita a la aplicación principal ver qué complementos están disponibles.

Hmm … requieren todos los packages.

Significa un gran composer.json Json para todo funciona con su sistema / es compatible con su sistema. Tal vez deberás introducir un sistema de control de versiones también. Así que podrías terminar con v1_composer.json

Pero para cada cliente cargue solo los packages requeridos. Por ejemplo, genere un requires.php para cada cliente con las declaraciones requeridas necesarias que enlazan con sus bibliotecas compartidas. Esta será la solución más rápida y más eficiente, porque usted comparte el código que puede compartir y solo lo carga cuando es necesario.

Conclusión

Comparta la mayor cantidad de código posible … pero no lo use cuando no lo necesite.