Jdi na navigaci předmětu

Composer

https://getcomposer.org

K čemu je to dobré?

  • nástroj na správu závislostí v PHP.
  • určíte na jakých knihovnách závisí vaše aplikace a composer se postará o potřebné verze
  • správa balíčků pro každý projekt zvlášť (adresář vendor)

instalace

composer.json (format)

composer init
{
    "name": "author/my-project",
    "description": "My project",
    "type": "project",
    "authors": [
        {
            "name": "Vojtěch Jirkovský",
            "email": "jirkovoj@fit.cvut.cz"
        }
    ],
    "require": {}
}

omezení verzí balíčků

  • verze balíčků se řídí sémantickým verzováním – MAJOR.MINOR.PATCH
    • MAJOR – zpětně nekompatibilní změna
    • MINOR – nová funkcionalita, zpětně kompatibilní
    • PATCH – oprava chyby
  • v require se neuvádí konkrétní verze, ale omezení (constraint) – rozsah verzí, které aplikaci vyhovují
  • omezení doplní composer require automaticky (zpravidla ^)

    "require": {
        "symfony/validator": "^7.3",
        "tracy/tracy": "~2.10.0",
        "nette/utils": "4.*",
        "some/package": "1.2.3"
    }
  • ^7.3 – caret, nejčastější volba: vše až do další MAJOR verze, tj. >=7.3.0 <8.0.0
  • ~2.10.0 – tilde, smí se měnit poslední uvedená část, tj. >=2.10.0 <2.11.0 (zatímco ~2.10 znamená >=2.10 <3.0)
  • 4.* – jakákoli verze s MAJOR 4
  • 1.2.3 – přesně jedna verze; nedoporučeno, blokuje i bezpečnostní opravy
  • omezení lze i kombinovat – >=7.3 <8.0, ^7.3 || ^8.0
  • omezení určuje, co smí nainstalovat composer update; co se nainstaluje doopravdy při composer install, určuje composer.lock (viz níže)
  • více viz dokumentace omezení verzí

závislosti pouze pro vývojáře

  • require – balíčky, které potřebuje samotná aplikace za běhu
  • require-dev – balíčky potřebné jen při vývoji: testovací frameworky, debuggery, lintery, generátory dokumentace

    composer require --dev phpunit/phpunit
    "require": {
        "symfony/validator": "^7.3"
    },
    "require-dev": {
        "phpunit/phpunit": "^12.0"
    },
  • composer install nainstaluje obojí
  • composer install --no-dev nainstaluje pouze require – použijte při nasazení na produkci (menší vendor, méně cizího kódu na serveru)
  • kód z require-dev proto nesmí být volán z aplikace – na produkci tam nebude

požadavky na platformu

  • kromě balíčků se do require uvádí i to, co aplikace potřebuje od prostředí – verzi PHP a rozšíření (extensions)

    "require": {
        "php": ">=8.3",
        "ext-gd": "*",
        "ext-pdo": "*"
    }
  • php – minimální, případně i maximální verze PHP
  • ext-* – vyžadované rozšíření PHP; název odpovídá výpisu php -m
  • Composer požadavky ověřuje při instalaci a jinak instalaci odmítne:

    Problem 1
        - Root composer.json requires PHP extension ext-gd * but it is missing from your system.
  • správné řešení je rozšíření doinstalovat a ověřit pomocí php -m, že je načtené
  • --ignore-platform-reqs kontrolu vypne, ale aplikace pak (nejspíš) spadne až za běhu
  • co prostředí nabízí, vypíše composer check-platform-reqs

příkazy

  • require - přidá novou závislost do composer.json
  • require --dev - přidá závislost potřebnou jen pro vývoj (do require-dev)
  • remove - odebere závislost z composer.json a smaže ji z adresáře vendor
  • install - nainstaluje závislosti dle composer.lock nebo composer.json
  • install --no-dev - nainstaluje bez vývojových závislostí (produkční nasazení)
  • update - nainstaluje/aktualizuje závislosti dle composer.json
  • update vendor/balicek - aktualizuje pouze uvedený balíček; ostatní zůstanou na verzích zapsaných v composer.lock
    • hodí se, když potřebujete opravu v jedné knihovně a nechcete sahat na zbytek projektu
  • dump-autoload - vygeneruje vendor/autoload.php (po instalaci balíčků automaticky)

skripty

  • direktiva scripts v composer.json pojmenuje často používané příkazy

    "scripts": {
        "test": "phpunit",
        "lint": "phpcs src tests",
        "check": ["@lint", "@test"]
    },
  • skript se spustí jako composer test, případně composer run test
  • hodnotou je jeden příkaz, nebo pole příkazů, které se provedou po sobě
  • @nazev odkazuje na jiný skript ve stejném souboru
  • při běhu skriptu je adresář vendor/bin v proměnné PATH – stačí tedy napsat phpunit místo vendor/bin/phpunit
  • dostupné skripty vypíše composer run-script --list
  • skript lze navázat i na událost Composeru (post-install-cmd, post-update-cmd, aj.), více viz oficiální dokumentace skriptů

adresář vendor

  • obsahuje nainstalované balíčky, vygenerovaný autoloader a spustitelné soubory
  • do gitu nepatří – jeho obsah je plně rekonstruovatelný příkazem composer install z composer.json a composer.lock

    # .gitignore
    /vendor/
  • vendor/bin/ – spustitelné soubory balíčků, např. vendor/bin/phpunit
    • odkaz sem Composer vytvoří podle direktivy bin, kterou deklaruje balíček
    • totéž lze spustit i jako composer exec phpunit

composer.lock

  • zafixované konkrétní verze balíčků pro pozdější composer install
  • lze verzovat v gitu či jiném systému
  • composer update může změnit composer.lock

autoloading

  • pro nainstalované závislosti generuje autoloader (dump-autoload)
  • lze nastavit i pro vlastní aplikaci, pro aplikaci dodržující standard PSR-4 např.

    "autoload": {
        "psr-4": {"Eshop\\": "src/"}
    },
  • Composerem lze automaticky načítat kód i podle jiných pravidel
    • file: automaticky načte všechny specifikované soubory (př. pro registraci vlastního autoloaderu)
    • classmap: Composer naskenuje všechny existující třídy, vytvoří mapování název třídy → název souboru a autoloader tuto mapu využívá
    • aj., více viz oficiální dokumentace direktivy autoload
  • po každé změně direktivy autoload je nutné autoloader vygenerovat znovu (composer dump-autoload) – sám se obnoví jen při instalaci balíčků
  • autoload-dev – pravidla platná jen při vývoji, typicky jmenný prostor testů

    "autoload": {
        "psr-4": {"Eshop\\": "src/"}
    },
    "autoload-dev": {
        "psr-4": {"Eshop\\Tests\\": "tests/"}
    },
    • při composer install --no-dev se tato pravidla do autoloaderu nezahrnou
  • v závislosti na aplikaci může být dostačující autoloader vygenerovaný Composerem, případně může být zapotřebí definovat si autoloader i vlastní

optimalizace autoloaderu

  • výchozí autoloader PSR-4 odvodí z názvu třídy cestu a při každém hledání ověřuje, zda soubor na disku existuje – to stojí čas
  • dump-autoload -o (--optimize)
    • z pravidel PSR-4 předem vygeneruje statickou classmapu (název třídy → soubor), hledání je pak jen pohled do pole
    • třída, která v mapě není (např. přidaná až po vygenerování), se stále dohledá podle pravidel PSR-4
  • dump-autoload -a (--classmap-authoritative)
    • zahrnuje -o a navíc prohlásí classmapu za úplnou: co v ní není, autoloader rovnou považuje za neexistující a na disk se už nepodívá
    • nejrychlejší varianta, ale po přidání každé nové třídy je nutné autoloader vygenerovat znovu
    • nepoužitelné, pokud aplikace generuje třídy až za běhu
  • obě volby patří na produkci (composer install --no-dev -o); při vývoji je vynechte, jinak vás každá nová třída donutí spustit dump-autoload
  • více viz dokumentace optimalizace autoloaderu

packagist

  • repozitář balíčků pro composer
  • na titulní stránce zároveň rychlokurz composeru
  • http://packagist.org