Composer requiere paquete local

106

Tengo un par de bibliotecas [Foo y Bar] que estoy desarrollando en concierto, pero todavía son cosas técnicamente separadas. Anteriormente, acababa de redefinir el cargador automático para "Foo\\": "../Foo/src"que me gustara , pero ahora que agregué una dependencia de Guzzle a Foo, Bar voltea su tapa porque no es una de sus dependencias.

Estructura de directorios:

/home/user/src/
    Foo/
        src/
            FooClient.php
        composer.json
    Bar/
        src/
            BarClient.php
        composer.json

Declaración teórica de carga automática: [en Bar / composer.json]

"require": {
    "local": "../Foo/composer.json"
}

Código de ejemplo:

require('vendor/autoload.php');

$f = new \Bar\BarClient(new \Foo\FooClient());

¿Cómo puedo resolver esto sin configurar un repositorio de Composer local? Quiero mantenerlos como paquetes separados, solo que uno requiere el otro y, por lo tanto, procesa las dependencias del otro.

edición posterior a la respuesta:

Gracias a infomaniac he hecho lo siguiente:

Inicializó el repositorio de git:

cd ~/src/Foo && git init && echo -e "vendor\ncomposer.lock" > .gitignore && git add ./ && git commit -m "Initial Commit"

Añadida la configuración del compositor:

"require": {
    "sammitch/foo": "dev-master"
},
"repositories": [{
    "type": "vcs",
    "url": "/home/sammitch/src/Foo"
}],

¡Y luego composer update!

Sammitch
fuente
¿Cómo especifica este json la identidad entre la referencia a "sammitch / foo" y la dirección de "/ home / sammitch / src / Foo"? ¿Sigue alguna convención?
Sebastián Grignoli
@ SebastiánGrignoli sammitch/fooes el nombre del paquete y literalmente no tiene nada que ver con su ubicación. Construirá una lista de paquetes disponibles basada en sus repositorios configurados, en este caso recuperando el composer.json del repositorio git local especificado, y luego composer maneja el resto. El sammitch/foopaquete se copia en la vendorcarpeta de la aplicación actual al igual que cualquier otro paquete.
Sammitch
Oh, creo que lo entiendo ahora. Es solo un repositorio personalizado, como en APT, que podría contener el paquete "sammit / foo". ¿Lo entendí bien?
Sebastián Grignoli
@ SebastiánGrignoli te
apuesto

Respuestas:

38

Puede utilizar la función de repositorios de Composer

https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository

En lugar de utilizar el formato http, especifique una ruta de archivo en el disco.

Danny Kopping
fuente
11
getcomposer.org/doc/05-repositories.md#path también es potencialmente útil y parece funcionar mejor para mí.
Jasmine Hegman
@JasmineHegman de hecho! También lo he usado, excelente para el desarrollo
Danny Kopping
Para que esta sea una buena respuesta, debe mostrar CÓMO hacerlo, y no solo nombrar la función y vincular los documentos (aunque eso también es importante). Otras respuestas a continuación tienen ejemplos adecuados.
rudolfbyker
172

La forma de vincular a un paquete local en desarrollo es agregar primero composer.jsonun repositorio de su proyecto principal , así:

"repositories": [
    {
        "type": "path",
        "url": "/full/or/relative/path/to/development/package"
    }
]

También necesita tener una versión especificada en su paquete de desarrollo composer.jsono la forma en que lo hago es exigir que el paquete use @dev, así:

composer require "vendorname/packagename @dev"

Debería generar:

- Installing vendor/packagename (dev-develop)
Symlinked from /full/or/relative/path/to/development/package

El @devcomando en require es importante, el compositor lo usa para recoger el código fuente y vincularlo simbólicamente a su nuevo paquete.

Es una marca de estabilidad agregada a la restricción de versión (ver enlace del paquete ).

Estos le permiten restringir o expandir aún más la estabilidad de un paquete más allá del alcance de la configuración de estabilidad mínima .

Las banderas de estabilidad mínima son:

Las opciones disponibles (en orden de estabilidad) son dev, alpha, beta, RC, y stable.

Dhiraj Gupta
fuente
8
Tenga en cuenta que el compositor no le permite especificar una ruta que esté en el mismo directorio en el que se encuentra composer.json.
MaPePeR
Punto interesante, MaPePeR No sabía esto. Sin embargo, supongo que todos los frameworks web ya se encargan de esto colocando todas las dependencias en una carpeta de "proveedor". Yii2 hace esto, al menos.
Dhiraj Gupta
3
composer require "vendorname/packagename @dev"se traduce en "require":{ "vendorname/packagename": "@dev" }en el composer.json de su aplicación si desea ejecutar la instalación del compositor
Sir_Faenor
2
Por favor, agregue esto: repositorios de configuración de compositor.ruta local / completa / o / relativa / ruta / a / desarrollo / paquete como forma correcta de agregar repositorios
basil
1
¿Es posible decirle al compositor que lo instale en la carpeta de proveedores para prod en lugar de crear un enlace simbólico?
BenjaminH
7

Después de pasar un tiempo, finalmente entendí la solución. Tal vez sea útil para alguien como yo y te ahorre algo de tiempo, así que he decidido que tengo que compartirlo aquí.

Suponiendo que tiene la siguiente estructura de directorios (en relación con el directorio raíz de su proyecto):

composer.json
config
config/composition-root.php
local
local/bar-project
local/bar-project/composer.json
local/bar-project/src
local/bar-project/src/Bar.php
public
public/index.php
src
src/Foo.php

En este ejemplo, puede ver que la localcarpeta está destinada a proyectos anidados de su empresa, por ejemplo bar-project. Pero puede configurar cualquier otro diseño, si lo desea.

Cada proyecto debe tener su propio composer.jsonarchivo, por ejemplo, root composer.jsony local/bar-project/composer.json. Entonces su contenido sería el siguiente:

(raíz composer.json:)

{
  "name": "your-company/foo-project",
  "require": {
    "php": "^7",
    "your-company/bar-project": "@dev"
  },
  "autoload": {
    "psr-4": {
      "YourCompany\\FooProject\\": "src/"
    }
  },
  "repositories": [
    {
      "type": "path",
      "url": "local/bar-project"
    }
  ]
}

( local/bar-project/composer.json:)

{
  "name": "your-company/bar-project",
  "autoload": {
    "psr-4": {
      "YourCompany\\BarProject\\": "src/"
    }
  }
}

Si, por ejemplo, desea ubicar cada proyecto en un directorio hermano separado, de la siguiente manera:

your-company
your-company/foo-project
your-company/foo-project/composer.json
your-company/foo-project/config
your-company/foo-project/config/composition-root.php
your-company/foo-project/public
your-company/foo-project/public/index.php
your-company/foo-project/src
your-company/foo-project/src/Foo.php
your-company/bar-project
your-company/bar-project/composer.json
your-company/bar-project/src
your-company/bar-project/src/Bar.php

- entonces necesitas enlazar al directorio respectivo en la repositoriessección:

  "repositories": [
    {
      "type": "path",
      "url": "../bar-project"
    }
  ]

Después de eso, ¡no te olvides de hacerlo composer update(o incluso rm -rf vendor && composer update -vcomo sugieren los documentos )! Bajo el capó, el compositor creará un vendor/your-company/bar-projectenlace simbólico dirigido a local/bar-project(o ../bar-projectrespectivamente).

Suponiendo que tu public/index.phpes solo un front controller, por ejemplo:

<?php
require_once __DIR__ . '/../config/composition-root.php';

Entonces tu config/composition-root.phpserías:

<?php

declare(strict_types=1);

use YourCompany\BarProject\Bar;
use YourCompany\FooProject\Foo;

require_once __DIR__ . '/../vendor/autoload.php';

$bar = new Bar();
$foo = new Foo($bar);
$foo->greet();
por qué
fuente
1
"rm -rf proveedor / empresa / paquete" es importante
Alex83690
@ Alex83690 solo si ya ha ejecutado composer updatecon similar composer.jsony, por lo tanto, necesita eliminar el enlace simbólico anterior creado por el compositor
whyer