Composer

require, dependensi dev, dan script Composer.

Daftar isi

Composer adalah pengelola dependensi (dependency manager) untuk PHP yang mengunduh, memasang, dan memuat pustaka pihak ketiga secara teratur. Topik ini membahas alur perintah composer require, isi berkas composer.json yang dihasilkannya, autoloader yang mencakup seluruh pustaka terpasang, pemisahan dependensi pengembangan, serta pendefinisian script yang dapat dijalankan berulang. Setelah membaca, penambahan satu pustaka baru ke proyek menjadi satu perintah yang dapat direproduksi.

Mengunduh dependensi dengan composer require#

Contoh yang digunakan di sini adalah psr/log, yaitu package kecil yang berisi antarmuka log standar PSR-3 beserta trait pendukungnya. Perintah composer require dijalankan dari folder proyek, diikuti nama package dan rentang versinya, serta opsi --no-interaction agar seluruh pertanyaannya dijawab secara otomatis.

bash
# tambahkan psr/log sebagai dependensi proyek
composer require psr/log:^3.0 --no-interaction
text Keluaran
./composer.json has been created
Running composer update psr/log
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking psr/log (3.0.2)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing psr/log (3.0.2): Extracting archive
Generating autoload files
No security vulnerability advisories found.

Keluaran di atas merangkum seluruh siklus kerja Composer. Berkas composer.json dibuat karena folder proyek belum memilikinya, resolusi versi dijalankan terhadap repositori package, keputusannya dicatat di lock file, pustakanya dipasang ke folder vendor/, dan autoloader digenerasi ulang. Pemeriksaan keamanan di baris terakhir melaporkan tidak adanya kerentanan (vulnerability) yang diketahui untuk versi yang terpasang.

Berkas yang dihasilkan#

Proyek yang semula hanya berisi kode sendiri kini memuat tiga artefak baru. Berkas composer.json mendeklarasikan dependensi proyek beserta rentang versi yang ditoleransi.

json Berkas composer.json yang dihasilkan perintah require
{
    "require": {
        "psr/log": "^3.0"
    }
}

Tanda sirkumfleks (^) pada ^3.0 berarti versi 3.0.0 ke atas sampai sebelum 4.0.0 diterima, sehingga rilis perbaikan (patch) dan rilis fitur minor diizinkan tanpa perubahan berkas. Berkas composer.lock mencatat keputusan resolusi yang lebih rinci, yaitu versi persis yang terpasang, dalam hal ini 3.0.2 beserta hash-nya. Folder vendor/ menampung kode pustaka yang terpasang, dan berkas vendor/autoload.php adalah titik masuk autoloader yang mencakup seluruhnya.

Autoloader untuk seluruh dependensi#

Berkas vendor/autoload.php mendaftarkan pemetaan PSR-4 untuk setiap package terpasang, sehingga kelas pustaka dapat langsung digunakan tanpa require tambahan. Satu baris penyertaan di awal skrip sudah mencakup seluruh dependensi proyek.

php pakai-log.php
<?php

declare(strict_types=1);

require_once 'vendor/autoload.php';

var_dump(interface_exists('Psr\Log\LoggerInterface'));
var_dump(trait_exists('Psr\Log\LoggerTrait'));
echo Psr\Log\LogLevel::CRITICAL, "\n";
echo Psr\Log\LogLevel::DEBUG, "\n";
text Keluaran
bool(true)
bool(true)
critical
debug

Panggilan interface_exists() dan trait_exists() memicu autoloader untuk mencari berkas kelas Psr\Log\LoggerInterface dan Psr\Log\LoggerTrait di dalam folder vendor/, dan keduanya ditemukan tanpa perintah pemuatan manual. Konstanta LogLevel::CRITICAL dan LogLevel::DEBUG berasal dari package yang sama. Mekanisme inilah yang membuat penambahan pustaka tidak menambah baris require di setiap skrip.

Memasang ulang dari composer.lock#

Folder vendor/ tidak perlu ikut dipindahkan. Pada komputer lain, atau setelah kode proyek di-clone dari repositori, Composer membangun ulang seluruh folder tersebut dari composer.lock. Penghapusan folder vendor/ berikut meniru keadaan clone yang bersih, lalu composer install memasang dependensinya sesuai keputusan yang sudah tercatat.

bash
# hapus vendor untuk meniru keadaan repository yang baru di-clone
rm -rf vendor
# pasang ulang seluruh dependensi persis seperti tercatat di lock file
composer install --no-interaction
text Keluaran
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 1 install, 0 updates, 0 removals
  - Installing psr/log (3.0.2): Extracting archive
Generating autoload files

Versi yang terpasang diambil dari lock file, bukan dari rentang versi di composer.json, sehingga hasil pemasangannya identik di mesin mana pun. Perbedaan peran keduanya menjelaskan dua perintah yang sering tertukar: composer install mengikuti keputusan yang ada, sedangkan composer update memperbarui lock file ke versi terbaru yang diizinkan rentangnya.

Dependensi pengembangan#

Tidak semua pustaka dibutuhkan pada server produksi. Alat analisis statis, alat gaya kode, dan kerangka pengujian hanya dipakai saat mengembangkan proyek. Bagian require-dev di composer.json menampung dependensi semacam itu, dan Composer memasangnya bersama dependensi lain secara default.

json Contoh: composer.json dengan dependensi pengembangan
{
    "require": {
        "psr/log": "^3.0"
    },
    "require-dev": {
        "phpstan/phpstan": "^2.0"
    }
}

Perintah penambahannya serupa dengan perintah untuk dependensi biasa, ditambah opsi --dev.

bash
# tidak-dijalankan
# phpstan berukuran besar dan versinya sering berubah, sehingga keluaran
# unduhannya tidak dapat direproduksi secara deterministik di sandbox
composer require --dev phpstan/phpstan --no-interaction

Pada server produksi, dependensi pengembangan dilewatkan dengan composer install --no-dev, sehingga hanya pustaka yang benar-benar dibutuhkan aplikasi yang ikut terpasang. Pemisahan ini menjaga ukuran deployment tetap kecil sekaligus mengurangi permukaan serangan dari kode yang tidak dipakai.

Mendefinisikan dan menjalankan script#

Kunci scripts pada composer.json memberi nama pada perintah yang sering diulang. Script biasanya dipakai untuk pintasan perintah pengujian, pemeriksaan gaya kode, atau langkah pasca-pemasangan. Contoh di sini memakai skrip PHP sederhana sebagai perintahnya.

php uji.php
<?php

declare(strict_types=1);

echo 'Skrip uji berjalan dari Composer.', PHP_EOL;
text Keluaran
Skrip uji berjalan dari Composer.

Perintah composer config menambahkan entri script tanpa menyunting composer.json dengan tangan, lalu composer run-script menjalankannya melalui nama yang sudah diberikan.

bash
# daftarkan skrip bernama uji ke dalam composer.json
composer config scripts.uji "php uji.php"
bash
# jalankan skrip bernama uji melalui Composer
composer run-script uji
text Keluaran
> php uji.php
Skrip uji berjalan dari Composer.

Composer mencetak perintah yang dieksekusinya di belakang tanda lebih besar dari (>), kemudian keluaran skripnya mengikuti. Berkas composer.json yang dihasilkan rangkaian ini memuat dua kunci seperti berikut.

json Berkas composer.json dengan kunci scripts
{
    "require": {
        "psr/log": "^3.0"
    },
    "scripts": {
        "uji": "php uji.php"
    }
}

Selain dipanggil manual, script juga dapat dikaitkan dengan peristiwa (event) siklus hidup Composer seperti post-autoload-dump, sehingga langkah tertentu dijalankan otomatis setiap kali autoloader digenerasi ulang.

Kesalahan umum#

  • Menyunting composer.json dengan tangan lalu mengharapkan efeknya langsung terasa. Perubahan rentang versi berlaku setelah composer update dijalankan, dan perubahan pemetaan autoload berlaku setelah composer dump-autoload. Tanpa salah satu dari dua perintah tersebut, kelas pustaka yang ditambahkan tidak ditemukan.
  • Menyertakan folder vendor/ ke repositori. Folder itu berukuran besar dan bisa dibangun ulang dari composer.json beserta composer.lock. Sertakan kedua berkas itu saja, lalu biarkan composer install mengembalikan sisanya.
  • Menjalankan composer update pada server produksi. Perintah itu menarik versi terbaru yang diizinkan rentangnya, sehingga perilaku aplikasi dapat berubah tanpa disadari. Pada server produksi, gunakan composer install --no-dev yang mengikuti keputusan di lock file.

Ringkasan#

  • composer require menambahkan dependensi ke composer.json, mengunci versinya di composer.lock, memasang kodenya di vendor/, dan menggenerasi autoloader dalam satu langkah.
  • vendor/autoload.php memetakan namespace seluruh package terpasang, sehingga satu baris penyertaan sudah mengaktifkan semua pustaka proyek.
  • composer install memasang dependensi persis sesuai composer.lock, sedangkan composer update memperbarui keputusan tersebut, dan require-dev menampung dependensi yang dilewatkan produksi lewat --no-dev.
  • Kunci scripts memberi nama pada perintah berulang yang dijalankan dengan composer run-script, dan dapat pula terikat pada event siklus hidup Composer.

Referensi#