Composer, nejdůležitější nástroj pro PHP vývojáře, umožňuje 3 způsoby, jak instalovat balíčky:
- lokální
composer require vendor/name
- globální
composer global require vendor/name
- jako projekt
composer create-project vendor/name
Lokálně
Lokální instalace se používá nejčastěji. Mám projekt, ve kterém chci třeba použít Tracy, tak v kořenovém adresáři projektu zadám:
composer require tracy/tracy
a Composer zaktualizuje (nebo vytvoří) soubor composer.json
a
stáhne Tracy do podsložky vendor
. Zároveň vygeneruje
autoloader, takže v kódu jej stačí inkludovat a můžu rovnou Tracy
použít:
require __DIR__ . '/vendor/autoload.php';
Tracy\Debugger::enable();
Jako projekt
Diametrálně odlišná situace nastává tehdy, pokud místo knihovny, jejíž třídy ve svém projektu používám, instaluji nástroj, který jen spouštím z příkazové řádky.
Příkladem může být třeba ApiGen pro generování přehledných API dokumentací. V takovém případě se použije třetí způsob:
composer create-project apigen/apigen
Composer vytvoří novou složku (a tedy i nový projekt)
apigen
a do ní stáhne celý nástroj a nainstaluje jeho
závislosti.
Bude mít vlastní composer.json
a vlastní podsložku
vendor
.
Tímto způsobem se instaluje i třeba Nette Sandbox nebo CodeChecker. Nikoliv však
testovací nástroje jako je Nette Tester
nebo PHPUnit, protože jejich třídy naopak
v testech používáme, voláme Tester\Assert::same()
nebo
dědíme od PHPUnit_Framework_TestCase
.
Bohužel Composer umožňuje instalovat nástroje jako je ApiGen i pomocí
composer require
a nevypíše ani žádné varování.
Což je totéž, jako když donutíte dva vývojáře, kteří se ani
neznají a kteří pracují na úplně jiném projektu, aby sdíleli společnou
složku vendor
. Na to se dá říci:
- Proboha proč by to měli dělat?
- Vždyť to přece nemůže fungovat!
Ano, není žádný rozumný důvod to dělat, nic to nepřinese, naopak to přestane fungovat v momentě, kdy dojde ke kolizi používaných knihoven. Je to jen otázka času, stavění domečku z karet, který se dřív nebo později sesype. Jeden projekt bude vyžadovat knihovnu XY ve verzi 1.0, druhý ve verzi 2.0 a v tu chvíli to přestane fungovat.
Globálně
Rozdíl mezi variantou 1) a 2), tj. mezi composer require
a
composer global require
, je pak v tom, že nepůjde o dva cizí
vývojáře, ale o deset cizích vývojářů a deset nesouvisejících
projektů. Tedy je to nesmysl na druhou.
Totiž composer global
je špatné řešení úplně vždy,
neexistuje use case, kdy by bylo vhodné jej použít. Výhodou je jen to, že
když si globální adresář vendor/bin
přidáte do PATH,
můžete snadno spouštět takto nainstalované knihovny.
Rekapitulace
composer require vendor/name
pokud chcete používat třídy knihovnycomposer global require vendor/name
nikdy!composer create-project vendor/name
pro nástroje volané jen z příkazové řádky
Poznámka: npm používá odlišnou
filosofii danou možnostmi JavaScriptu a každou knihovnu instaluje jako
„samostatný projekt“, s vlastním adresářem vendor
(resp.
node_modules
). Ke konfliktu verzí tak dojít nemůže.
V případě npm
naopak platí, že globální instalace
nástrojů, jako je například LESS CSS, jsou
velmi užitečná a příjemná věc.
Komentáře
Milo #1
Nedávno jsem nad tím dumal. On parametr global není tak parametr, jako přepínač. Dá se použít s jakýmkoliv příkazem, tedy i create-project.
Jeho magie spočívá v tom, že změní pracovní adresář na globální (na Linuxu
/home/milo/.composer
) a dál se chová stejně. Při require vytvoří composer.json, stáhne závislosti, vytvořívendor/bin
.A tohle, spekuluji, má fungovat tak, že si člověk přidá
/home/milo/.composer/vendor/bin
do$PATH
a může volat binárky globálně. Jenže je to na nic, přesně z důvodů které píšeš.Dává mi smysl
composer global create-project apigen/apigen
. Jako že chci mít globálně Apigen. Jenže, tam je adresář s binárkou v/home/milo/.composer/apigen/apigen/vendor/bin
a to je blbost přidávat do $PATH pro každý nový globální projekt. Zkrátka, buď to podělali nebo nedotáhli.bazo #2
global vobec nie je nanic. napriklad tester tak mam nainstalovany. aby som nemusel pre kazdy projekt menit cestu k spustaciemu skriptu v netbeans. tester je pritom nainstalovany aj lokalne.
je to ten isty princip ako s gulpom, tiez musi byt lokalne aj globalne nainstalovany.
pre nastroje ktorych triedy v projekte nevyuzijeme, napr nejaky staticky analyzator, nema lokalna instalacia vobec vyznam a jedina spravna instalacia je cez global.
dalsi priklad su dev nastroje pre phalcon framework, ktore maju tiez vyznam jedine globalne.
ps: policko web musi obsahovat http:// trosku zbytocne, nie?
ujovlado #3
#1 Milo, Myslím, že riešením môže byť projekt, nazvime ho
composer-bin
, ktorý bude mať zadefinované závislosti na konkrétnych balíčkoch.Tento projekt si naklonuješ ty, tvoji kolegovia, a všetci, ktorí pracujú. Dáš si ho napríklad do
/home/milo/composer-bin/
.Následne si do path pridáš bin priečinok tohto projektu – t.j.
/home/milo/composer-bin/vendor/bin
.Všetci tak dostanete tie isté závislosti a je úplne jedno, kde si ho kto naklonuje.
Jednoducho povedané, zvlášť projekt pre php binárky.
Milo #4
#3 ujovlado, Snad jsem Tě pochopil… ale je to to samé, jako composer global require, jen do jiného adresáře. Tím se případné kolizi závislostí nevyhneš.
Osobně na composer global kašlu. V $PATH mám adresář
/home/milo/bin
a do něj si linkuji. Např:Pak už je jedno, kde co je.
David Grudl #5
#2 bazo, tak si schválně zkus globálně nainstalovat třeba tohle:
https://web.archive.org/…l-is-useless
ps: že adresa musí obsahovat http:// zbytečné je, ale hlásí to prohlížeč, nikoliv web.
ujovlado #6
#4 Milo, áno, pochopil si to správne. Ja som to najprv pochopil trošku inak, t.j., že riešime rôzne verzie balíčkov rôznych developerov, a nie kolízie balíčkov medzi sebou. Pardon. :)
Vyriešil by som to asi nejako takto, custom
install.sh
skriptom:https://github.com/…poser-global
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.