Composer wymaga pakietu lokalnego

106

Mam kilka bibliotek [Foo i Bar], które rozwijam wspólnie, ale technicznie wciąż są oddzielnymi rzeczami. Wcześniej właśnie ponownie zdefiniowałem autoloader "Foo\\": "../Foo/src", aby polubił, ale teraz, gdy dodałem zależność Guzzle do Foo, Bar odwraca jego pokrywę, ponieważ nie jest jedną z jego zależności.

Struktura katalogów:

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

Teoretyczna instrukcja automatycznego ładowania: [w Bar / composer.json]

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

Przykładowy kod:

require('vendor/autoload.php');

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

Jak mogę rozwiązać ten problem bez konfigurowania lokalnego repozytorium Composer? Chcę utrzymywać je jako oddzielne pakiety, tylko że jeden wymaga drugiego i dlatego przetwarza zależności drugiego.

edycja po odpowiedzi:

Dzięki infomaniac wykonałem następujące czynności:

Zainicjowałem repozytorium git:

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

Dodano konfigurację kompozytora:

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

A potem composer update!

Sammitch
źródło
W jaki sposób ten json określa tożsamość między odwołaniem do „sammitch / foo” a adresem „/ home / sammitch / src / Foo”? Czy przestrzega jakiejś konwencji?
Sebastián Grignoli
@ SebastiánGrignoli sammitch/footo nazwa pakietu i nie ma dosłownie nic wspólnego z tym, gdzie się znajduje. Utworzy listę dostępnych pakietów na podstawie skonfigurowanych repozytoriów, w tym przypadku pobierając plik composer.json z określonego lokalnego repozytorium git, a następnie composer zajmie się resztą. sammitch/fooPakiet jest kopiowany do bieżącej aplikacji vendorfolderu takie same jak każdy inny pakiet.
Sammitch
Och, myślę, że teraz rozumiem. To tylko niestandardowe repozytorium, jak w APT, które może zawierać pakiet „sammit / foo”. Czy dobrze to zrobiłem?
Sebastián Grignoli
@ SebastiánGrignoli you
betcha

Odpowiedzi:

38

Możesz skorzystać z funkcji repozytoriów Composera

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

Zamiast używać formatu http, określ ścieżkę do pliku na dysku.

Danny Kopping
źródło
11
getcomposer.org/doc/05-repositories.md#path jest również potencjalnie przydatny i wydaje mi się, że działa lepiej.
Jasmine Hegman
@JasmineHegman rzeczywiście! Ja też tego użyłem - świetne do rozwoju
Danny Kopping
Aby to była dobra odpowiedź, powinieneś pokazać JAK to zrobić, a nie tylko nazwać funkcję i połączyć dokumenty (chociaż jest to również ważne). Inne odpowiedzi poniżej mają odpowiednie przykłady.
rudolfbyker
173

Sposobem na link lokalnym, pakiet w-rozwoju jest najpierw dodać w swoim głównym projektu jest repozytorium , jak poniżej:composer.json

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

Musisz również mieć wersję określoną w pakiecie deweloperskim composer.jsonlub sposób, w jaki to robię, to wymagać, aby pakiet używał @dev, na przykład:

composer require "vendorname/packagename @dev"

Powinien wyświetlić:

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

W @devpoleceniu require jest ważne, kompozytor używa go do pobrania kodu źródłowego i dowiązania symbolicznego do nowego pakietu.

Jest to flaga stabilności dodana do ograniczenia wersji (zobacz link do pakietu ).

Umożliwiają one dalsze ograniczenie lub rozszerzenie stabilności pakietu poza zakres ustawienia minimalnej stabilności .

Flagi minimalnej stabilności to:

Dostępne opcje (w kolejności) są stabilność dev, alpha, beta, RC, i stable.

Dhiraj Gupta
źródło
8
Pamiętaj, że kompozytor nie może określić ścieżki, która znajduje się w tym samym katalogu, w którym znajduje się plik composer.json.
MaPePeR
Ciekawostka, MaPePeR Nie wiedziałem o tym. Jednak wydaje mi się, że wszystkie frameworki internetowe już się tym zajmują, umieszczając wszystkie zależności w folderze „dostawca”? Przynajmniej tak robi Yii2.
Dhiraj Gupta,
3
composer require "vendorname/packagename @dev"tłumaczy się na "require":{ "vendorname/packagename": "@dev" }w
pliku composer.json
2
Proszę, dodaj to: repozytoria konfiguracji kompozytora. Ścieżka lokalna / pełna / lub / względna / ścieżka / do / programowanie / pakiet jako poprawny sposób dodawania repozytoriów
bazylia
1
Czy można powiedzieć kompozytorowi, aby zainstalował go w folderze dostawców dla produktu zamiast tworzyć dowiązanie symboliczne?
BenjaminH
7

Po jakimś czasie w końcu zrozumiałem rozwiązanie. Może przyda się komuś takiemu jak ja i zaoszczędzi Ci trochę czasu, więc zdecydowałem, że muszę się tym tutaj podzielić.

Zakładając, że masz następującą strukturę katalogów (względem katalogu głównego projektu):

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

W tym przykładzie możesz zobaczyć, że localfolder jest przeznaczony dla zagnieżdżonych projektów Twojej firmy, np bar-project. Ale jeśli chcesz, możesz skonfigurować dowolny inny układ.

Każdy projekt musi mieć własny composer.jsonplik, np. Root composer.jsoni local/bar-project/composer.json. Wtedy ich zawartość wyglądałaby następująco:

(root 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/"
    }
  }
}

Jeśli, na przykład, chcesz zlokalizować każdy projekt w oddzielnym katalogu siostrzanym, w następujący sposób:

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

- wtedy musisz przejść do odpowiedniego katalogu w repositoriessekcji:

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

Po tym nie zapomnij composer update(a nawet rm -rf vendor && composer update -vjak sugerują doktorzy )! Pod maską kompozytor utworzy vendor/your-company/bar-projectłącze symboliczne skierowane do local/bar-project(lub../bar-project odpowiednio).

Zakładając, że public/index.phpjest to tylko front controllernp .:

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

Wtedy config/composition-root.phpbyłoby:

<?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();
dlaczego
źródło
1
„rm -rf sprzedawca / firma / pakiet” jest ważne
Alex83690
@ Alex83690 tylko jeśli już uruchomiłeś composer updatez podobnym composer.jsoni dlatego musisz usunąć poprzednie dowiązanie symboliczne utworzone przez kompozytora
whyer