Composer'a geçiş: PHP bağımlılıklarını elle yönetmeyi bırakmak
require yığınından modern bağımlılık yönetimine geçişin pratiği: composer.json, autoload ve paket kurma.
Birkaç ay öncesine kadar her yeni projeye başladığımda yaptığım şey şuydu: ihtiyaç duyduğum kütüphanelerin zip dosyasını indirmek, lib/ ya da vendor/ adını verdiğim bir klasöre atmak ve dosyanın tepesine elle require satırı yazmak. Sonra o kütüphane güncelleme aldığında yine aynı işlemi tekrarlamak. Bir projede üç farklı kütüphanenin bağımlılıkları çakışınca ne yapacağımı bilememek.
Bu düzensizliği gidermek için Composer’a geçtim. Şimdiye kadar kullandığım en doğru araç kararlarından biri olduğunu söyleyebilirim. Hâlâ öğreniyorum, ama artık eskiye dönmek istemiyorum.
Composer nedir?
Dependency Manager (bağımlılık yöneticisi), PHP projesinin hangi dış kütüphaneleri kullandığını takip eden, bunları yükleyen ve güncelleyen bir araçtır. Composer, PHP ekosistemi için tam olarak bunu yapar.
Ruby’deki Bundler’dan, Node.js’teki npm’den esinlenilmiş. PHP dünyasına 2012’de geldi; 2014’te artık ciddi projelerde standart sayılıyor.
Kurulumu tek satır:
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
Bundan sonra composer komutu her yerden çalışır.
composer.json nedir ve ne işe yarar?
Projenin kök dizinine koyduğunuz composer.json dosyası, projenin ihtiyaç duyduğu paketleri ve sürüm kısıtlamalarını tanımlar. Önceki elle yönetilen require yığınının yerini alır.
Basit bir örnek:
{
"require": {
"monolog/monolog": "1.11.*",
"guzzlehttp/guzzle": "4.2.*"
}
}
composer install çalıştırdığınızda Composer bu paketleri Packagist’ten indirir ve vendor/ klasörüne yerleştirir. Bir de composer.lock dosyası oluşturur; bu dosya kullandığınız tam sürümleri kaydeder. Takım çalışmasında veya sunucuya taşırken composer install aynı sürümleri kurar, beklenmedik sürüm farklarının önüne geçer.
Paketi güncellemek için:
composer update monolog/monolog
Ya da tüm bağımlılıkları güncellemek için sadece composer update.
Otomatik yükleme (Autoloading)
Composer’ın en büyük kazancı paket kurmanın yanı sıra autoloading sağlamasıdır. Artık her dosyaya require_once yazmak zorunda değilsiniz.
composer.json’a bir autoload bölümü ekleyip projenizin kaynak klasörünü belirtiyorsunuz:
{
"require": {
"monolog/monolog": "1.11.*"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Ardından composer dump-autoload çalıştırıyorsunuz. Bu noktadan itibaren src/ altındaki App\ ad alanıyla (namespace) yazılmış her sınıf otomatik olarak bulunur. Projenizin giriş dosyasına tek satır eklemeniz yeterli:
<?php
require 'vendor/autoload.php';
Tek satır, tüm kütüphaneler ve kendi sınıflarınız kullanılabilir hale gelir.
Yeni paket eklemek
Bir paket kurmak artık şu kadar:
composer require guzzlehttp/guzzle:~4.2
Composer composer.json’ı günceller, paketi indirir ve autoload haritasını yeniler. Elle hiçbir şey yazmıyorsunuz.
Geliştirme bağımlılıkları
Test ve geliştirme araçları canlı ortamda bulunmamalıdır. require-dev ile bunları ayırabilirsiniz:
{
"require": {
"monolog/monolog": "1.11.*"
},
"require-dev": {
"phpunit/phpunit": "4.0.*"
}
}
Canlı sunucuda composer install --no-dev ile geliştirme araçlarını atlamak mümkün.
composer.lock ve sürüm tutarlılığı
composer.lock dosyasını versiyon kontrolüne eklemek önemli. Bu dosya olmadan iki farklı bilgisayarda ya da geliştirme ile canlı sunucuda composer install çalıştırmak farklı küçük sürümler getirebilir. Kütüphanelerin küçük güncellemeleri zaman zaman beklenmedik davranış değişikliğine yol açıyor. composer.lock sayesinde takımdaki herkes ve sunucu aynı bayt-bayt özdeş sürümleri kullanıyor. composer.json niyeti, composer.lock gerçeği temsil ediyor diyebilirim.
Neden bu geçişi geciktirdim?
Dürüst olmak gerekirse, “bende çalışıyor” mantığıyla epey zaman harcadım. Composer’ı öğrenmek birkaç saatlik bir yatırım istiyor ama bir kez alışınca elle bağımlılık yönetiminin ne kadar verimsiz olduğunu fark ediyorsunuz. Özellikle birden fazla projeyi aynı anda yönetiyorsanız bu fark çok belirgin.
Packagist’te on binlerce paket var ve hepsi tek komutla erişilebilir. Bundan böyle bir kütüphane ihtiyacı duyduğumda önce Packagist’te bakıyorum, sonra composer require yazıyorum.
Küçük bir değişiklik gibi görünebilir ama çalışma biçimimi gerçekten değiştirdi.