Composer: wskazówki dotyczące użytkowania

Composer to narzędzie do zarządzania zależnościami w PHP. Umożliwia nam zdefiniowanie bibliotek, od których zależy nasz projekt, i będzie je za nas instalować oraz aktualizować. Pokażemy:

  • jak zainstalować Composer
  • jego użycie w nowym lub istniejącym projekcie

Instalacja

Composer to plik wykonywalny .phar, który pobierzesz i zainstalujesz w następujący sposób:

Windows

Użyj oficjalnego instalatora Composer-Setup.exe.

Linux, macOS

Wystarczą 4 polecenia, które skopiujesz z tej strony.

Następnie, umieszczając go w folderze, który znajduje się w systemowym PATH, Composer stanie się dostępny globalnie:

$ mv ./composer.phar ~/bin/composer # lub /usr/local/bin/composer

Użycie w projekcie

Aby móc w swoim projekcie zacząć używać Composera, potrzebujesz tylko pliku composer.json. Opisuje on zależności naszego projektu i może również zawierać inne metadane. Podstawowy composer.json może więc wyglądać tak:

{
	"require": {
		"nette/database": "^3.0"
	}
}

Mówimy tutaj, że nasza aplikacja (lub biblioteka) wymaga pakietu nette/database (nazwa pakietu składa się z nazwy organizacji i nazwy projektu) i chce wersji, która odpowiada warunkowi ^3.0 (tj. najnowszej wersji 3).

Mamy więc w katalogu głównym projektu plik composer.json i uruchamiamy instalację:

composer update

Composer pobierze Nette Database do folderu vendor/. Następnie utworzy plik composer.lock, który zawiera informacje o tym, które wersje bibliotek dokładnie zainstalował.

Composer wygeneruje plik vendor/autoload.php, który możemy po prostu dołączyć i zacząć używać bibliotek bez żadnej dodatkowej pracy:

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

$db = new Nette\Database\Connection('sqlite::memory:');

Aktualizacja pakietów do najnowszych wersji

Za aktualizację używanych bibliotek do najnowszych wersji zgodnie z warunkami zdefiniowanymi w composer.json odpowiada polecenie composer update. Np. przy zależności "nette/database": "^3.0" zainstaluje najnowszą wersję 3.x.x, ale już nie wersję 4.

Aby zaktualizować warunki w pliku composer.json, na przykład na "nette/database": "^4.1", aby można było zainstalować najnowszą wersję, użyj polecenia composer require nette/database.

Aby zaktualizować wszystkie używane pakiety Nette, trzeba by je wszystkie wymienić w wierszu poleceń, np.:

composer require nette/application nette/forms latte/latte tracy/tracy ...

Co jest niepraktyczne. Użyj dlatego prostego skryptu Composer Frontline, który to zrobi za Ciebie:

php composer-frontline.php

Tworzenie nowego projektu

Nowy projekt Nette utworzysz za pomocą jednego polecenia:

composer create-project nette/web-project nazwa-projektu

Jako nazwa-projektu wstaw nazwę katalogu dla swojego projektu i potwierdź. Composer pobierze repozytorium nette/web-project z GitHubu, które już zawiera plik composer.json, a zaraz potem Nette Framework. Powinno już wystarczyć tylko ustawić uprawnienia do zapisu w folderach temp/ i log/, a projekt powinien ożyć.

Jeśli wiesz, na jakiej wersji PHP projekt będzie hostowany, nie zapomnij jej ustawić.

Wersja PHP

Composer zawsze instaluje te wersje pakietów, które są kompatybilne z wersją PHP, której właśnie używasz (a raczej z wersją PHP używaną w wierszu poleceń podczas uruchamiania Composera). Co jednak najprawdopodobniej nie jest tą samą wersją, której używa Twój hosting. Dlatego bardzo ważne jest dodanie do pliku composer.json informacji o wersji PHP na hostingu. Wtedy będą instalowane tylko wersje pakietów kompatybilne z hostingiem.

To, że projekt będzie działał na przykład na PHP 8.2.3, ustawimy poleceniem:

composer config platform.php 8.2.3

W ten sposób wersja zostanie zapisana do pliku composer.json:

{
	"config": {
		"platform": {
			"php": "8.2.3"
		}
	}
}

Jednak numer wersji PHP podaje się jeszcze w innym miejscu pliku, a mianowicie w sekcji require. Podczas gdy pierwszy numer określa, dla jakiej wersji będą instalowane pakiety, drugi numer mówi, dla jakiej wersji jest napisana sama aplikacja. A według niego na przykład PhpStorm ustawia PHP language level. (Oczywiście nie ma sensu, aby te wersje się różniły, więc podwójny zapis jest niedopatrzeniem.) Tę wersję ustawisz poleceniem:

composer require php 8.2.3 --no-update

Lub bezpośrednio w pliku composer.json:

{
	"require": {
		"php": "8.2.3"
	}
}

Ignorowanie wersji PHP

Pakiety zazwyczaj mają podaną zarówno najniższą wersję PHP, z którą są kompatybilne, jak i najwyższą, z którą są testowane. Jeśli zamierzasz używać wersji PHP jeszcze nowszej, na przykład w celu testowania, Composer odmówi zainstalowania takiego pakietu. Rozwiązaniem jest opcja --ignore-platform-req=php+, która spowoduje, że Composer będzie ignorować górne limity wymaganej wersji PHP.

Fałszywe komunikaty

Podczas aktualizacji pakietów lub zmian numerów wersji zdarza się, że dochodzi do konfliktu. Jeden pakiet ma wymagania, które są sprzeczne z innym i podobnie. Composer jednak czasami wypisuje fałszywe komunikaty. Zgłasza konflikt, który realnie nie istnieje. W takim przypadku pomaga usunięcie pliku composer.lock i spróbowanie ponownie.

Jeśli komunikat błędu nadal się pojawia, to jest on myśleny poważnie i trzeba z niego wyczytać, co i jak zmodyfikować.

Packagist.org – centralne repozytorium

Packagist to główne repozytorium, w którym Composer stara się wyszukiwać pakiety, jeśli mu nie powiemy inaczej. Możemy tutaj publikować również własne pakiety.

Co jeśli nie chcemy używać centralnego repozytorium?

Jeśli mamy wewnętrzne aplikacje firmowe, których po prostu nie możemy hostować publicznie, to stworzymy dla nich firmowe repozytorium.

Więcej na temat repozytoriów w oficjalnej dokumentacji.

Autoloading

Zasadniczą cechą Composera jest to, że zapewnia autoloading dla wszystkich przez niego zainstalowanych klas, który uruchamiasz przez dołączenie pliku vendor/autoload.php.

Jednak możliwe jest używanie Composera również do ładowania innych klas spoza folderu vendor. Pierwszą możliwością jest pozwolenie Composerowi przeszukać zdefiniowane foldery i podfoldery, znaleźć wszystkie klasy i dołączyć je do autoloadera. Osiągniesz to ustawiając autoload > classmap w composer.json:

{
	"autoload": {
		"classmap": [
			"src/",      #  dołączy folder src/ i jego podfoldery
		]
	}
}

Następnie przy każdej zmianie trzeba uruchomić polecenie composer dumpautoload i pozwolić na przegenerowanie tabel autoloadingu. To jest niezwykle niewygodne i znacznie lepiej jest powierzyć to zadanie RobotLoaderowi, który tę samą czynność wykonuje automatycznie w tle i znacznie szybciej.

Drugą możliwością jest przestrzeganie PSR-4. Uproszczając, chodzi o system, w którym przestrzenie nazw i nazwy klas odpowiadają strukturze katalogów i nazwom plików, czyli np. App\Core\RouterFactory będzie w pliku /path/to/App/Core/RouterFactory.php. Przykład konfiguracji:

{
	"autoload": {
		"psr-4": {
			"App\\": "app/"   # przestrzeń nazw App\ jest w katalogu app/
		}
	}
}

Jak dokładnie skonfigurować zachowanie dowiesz się w dokumentacji Composera.

Testowanie nowych wersji

Chcesz przetestować nową wersję rozwojową pakietu. Jak to zrobić? Najpierw do pliku composer.json dodaj tę parę opcji, która pozwoli instalować wersje rozwojowe pakietów, jednak ucieknie się do tego tylko w przypadku, gdy nie istnieje żadna kombinacja stabilnych wersji, która spełniałaby wymagania:

{
	"minimum-stability": "dev",
	"prefer-stable": true,
}

Następnie zalecamy usunięcie pliku composer.lock, czasami bowiem Composer niezrozumiale odmawia instalacji i to rozwiązuje problem.

Powiedzmy, że chodzi o pakiet nette/utils i nowa wersja ma numer 4.0. Zainstalujesz ją poleceniem:

composer require nette/utils:4.0.x-dev

Lub możesz zainstalować konkretną wersję, na przykład 4.0.0-RC2:

composer require nette/utils:4.0.0-RC2

Gdy jednak od biblioteki zależy inny pakiet, który jest zablokowany na starszej wersji (np. ^3.1), to idealnie jest zaktualizować pakiet, aby działał z nową wersją. Jeśli jednak chcesz tylko obejść ograniczenie i zmusić Composera do zainstalowania wersji rozwojowej i udawania, że jest to wersja starsza (np. 3.1.6), możesz użyć słowa kluczowego as:

composer require nette/utils "4.0.x-dev as 3.1.6"

Wywoływanie poleceń

Przez Composer można wywoływać własne przygotowane polecenia i skrypty, jakby były to natywne polecenia Composera. W przypadku skryptów, które znajdują się w folderze vendor/bin, nie trzeba podawać tego folderu.

Jako przykład zdefiniujemy w pliku composer.json skrypt, który za pomocą Nette Testera uruchomi testy:

{
	"scripts": {
		"tester": "tester tests -s"
	}
}

Testy następnie uruchomimy za pomocą composer tester. Polecenie możemy wywołać również w przypadku, gdy nie jesteśmy w folderze głównym projektu, ale w którymś podkatalogu.

Wyślij podziękowania

Pokażemy Ci sztuczkę, którą ucieszysz autorów open source. W prosty sposób dasz na GitHubie gwiazdkę bibliotekom, których używa Twój projekt. Wystarczy zainstalować bibliotekę symfony/thanks:

composer global require symfony/thanks

A następnie uruchomić:

composer thanks

Spróbuj!

Konfiguracja

Composer jest ściśle powiązany z narzędziem do wersjonowania Git. Jeśli go nie masz zainstalowanego, trzeba powiedzieć Composerowi, aby go nie używał:

composer -g config preferred-install dist