Le compositeur nécessite un package local

106

J'ai quelques bibliothèques [Foo et Bar] que je développe en concert, mais qui sont toujours des choses techniquement séparées. Auparavant, je viens de redéfinir l'autochargeur pour aimer "Foo\\": "../Foo/src", mais maintenant que j'ai ajouté une dépendance Guzzle à Foo, Bar retourne son couvercle car ce n'est pas l'une de ses dépendances.

Structure du répertoire:

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

Instruction de chargement automatique théorique: [dans Bar / composer.json]

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

Exemple de code:

require('vendor/autoload.php');

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

Comment puis-je résoudre ce problème sans configurer un référentiel Composer local? Je veux les maintenir en tant que packages séparés, juste que l'un nécessite l'autre, et pour cela traite les dépendances de l'autre.

modification après réponse:

Grâce à infomaniac, j'ai fait ce qui suit:

Initialisation du repo git:

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

Ajout de la configuration du compositeur:

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

Et puis composer update!

Sammitch
la source
Comment ce json spécifie-t-il l'identité entre la référence à "sammitch / foo" et l'adresse de "/ home / sammitch / src / Foo"? Est-ce que cela suit une convention?
Sebastián Grignoli
@ SebastiánGrignoli sammitch/fooest le nom du package et n'a littéralement rien à voir avec où il se trouve. Construira une liste des packages disponibles en fonction de ses dépôts configurés, dans ce cas en récupérant le composer.json à partir du dépôt git local spécifié, puis composer gère le reste. Le sammitch/foopackage est copié dans le vendordossier de l' application actuelle de la même manière que tout autre package.
Sammitch
Oh, je pense que je comprends maintenant. C'est juste un dépôt personnalisé, comme dans APT, qui peut contenir le paquet "sammit / foo". Ai-je bien compris?
Sebastián Grignoli
@ SebastiánGrignoli vous pariez
Sammitch

Réponses:

38

Vous pouvez utiliser la fonction de référentiels de Compositeur

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

Au lieu d'utiliser le format http, spécifiez un chemin de fichier sur le disque.

Danny Kopping
la source
11
getcomposer.org/doc/05-repositories.md#path est également potentiellement utile et semble mieux fonctionner pour moi.
Jasmine Hegman
@JasmineHegman en effet! Je l'ai aussi utilisé - idéal pour le développement
Danny Kopping
Pour en faire une bonne réponse, vous devez montrer COMMENT le faire, et pas seulement nommer la fonctionnalité et lier les documents (bien que cela soit également important). D'autres réponses ci-dessous ont des exemples appropriés.
rudolfbyker
173

La façon de créer un lien vers un package local en développement consiste à ajouter d'abord dans votre projet principal composer.jsonun référentiel , comme ceci:

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

Vous devez également avoir une version spécifiée dans votre package de développement composer.jsonou la façon dont je le fais est d'exiger que le package utilise @dev, comme ceci:

composer require "vendorname/packagename @dev"

Il devrait afficher:

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

La @devcommande dans la commande require est importante, composer l'utilise pour récupérer le code source et le lien symbolique vers votre nouveau package.

C'est un indicateur de stabilité ajouté à la contrainte de version (voir le lien du package ).

Ceux-ci vous permettent de restreindre ou d'étendre davantage la stabilité d'un package au-delà de la portée du paramètre de stabilité minimale .

Les indicateurs de stabilité minimale sont:

Sont les options disponibles (dans l' ordre de la stabilité) dev, alpha, beta, RCet stable.

Dhiraj Gupta
la source
8
Notez que vous n'êtes pas autorisé par composer à spécifier un chemin qui se trouve dans le même répertoire que composer.json est placé.
MaPePeR
Point intéressant, MaPePeR Je ne le savais pas. Cependant, je suppose que tous les frameworks Web prennent déjà en charge cela en mettant toutes les dépendances dans un dossier "fournisseur"? Yii2 fait cela, au moins.
Dhiraj Gupta
3
composer require "vendorname/packagename @dev"se traduit par "require":{ "vendorname/packagename": "@dev" }le composer.json de votre application si vous souhaitez exécuter l'installation de composer
Sir_Faenor
2
S'il vous plaît, ajoutez ceci: composer config repositories.local path / full / ou / relative / path / to / development / package comme moyen correct d'ajouter des dépôts
basil
1
Est-il possible de dire à composer de l'installer dans le dossier des fournisseurs pour produire au lieu de créer un lien symbolique?
BenjaminH le
7

Après avoir passé du temps, j'ai enfin compris la solution. Peut-être que cela sera utile pour quelqu'un comme moi et vous fera gagner du temps, alors j'ai décidé de le partager ici.

En supposant que vous disposez de la structure de répertoires suivante (par rapport au répertoire racine de votre projet):

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

Dans cet exemple, vous pouvez voir que le localdossier est destiné aux projets imbriqués de votre entreprise, par exemple bar-project. Mais vous pouvez configurer n'importe quelle autre disposition, si vous le souhaitez.

Chaque projet doit avoir son propre composer.jsonfichier, par exemple root composer.jsonet local/bar-project/composer.json. Ensuite, leur contenu serait le suivant:

(racine 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, par exemple, vous souhaitez localiser chaque projet dans un répertoire frère distinct, comme suit:

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

- alors vous devez créer un lien vers le répertoire respectif dans la repositoriessection:

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

Après cela, n'oubliez pas composer update(ou même rm -rf vendor && composer update -vcomme le suggèrent les documents )! Sous le capot, composer créera un vendor/your-company/bar-projectlien symbolique qui cible local/bar-project(ou ../bar-projectrespectivement).

En supposant que vous public/index.phpêtes juste un front controller, par exemple:

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

Alors votre config/composition-root.phpserait:

<?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();
pourquoi
la source
1
"rm -rf vendeur / société / package" est important
Alex83690
@ Alex83690 uniquement si vous avez déjà exécuté composer updateavec similaire composer.jsonet que vous devez donc supprimer le lien symbolique précédent créé par le compositeur
pourquoi