Composer - Package Manager PHP

Composer adalah dependency manager untuk PHP yang memungkinkan Anda mengelola library dan package dengan mudah serta otomatis handle autoloading.

Apa itu Composer?

Composer adalah dependency manager untuk PHP. Ini berarti Composer mengelola library dan dependency yang dibutuhkan project Anda dan menginstalnya secara otomatis.

Keuntungan Menggunakan Composer

  • ๐Ÿ“ฆ Dependency Management: Mengelola library secara otomatis
  • ๐Ÿ”„ Autoloading: Auto-load class tanpa require manual
  • โฌ†๏ธ Easy Updates: Update library dengan satu command
  • ๐ŸŽฏ Version Control: Control versi library yang digunakan
  • ๐ŸŒ Packagist: Akses ke ribuan package PHP
  • ๐Ÿ›ก๏ธ Security: Notifikasi vulnerability
  • โšก Performance: Optimized autoloading
  • ๐Ÿ“‹ PSR Standards: Mengikuti standar PHP

Composer vs Manual Include

โŒ Manual Include

require_once 'vendor/monolog/src/Logger.php';
require_once 'vendor/monolog/src/Handler/StreamHandler.php';
require_once 'vendor/monolog/src/Handler/AbstractHandler.php';
require_once 'vendor/monolog/src/Handler/AbstractProcessingHandler.php';
// ... banyak file lainnya

โœ… Dengan Composer

require_once 'vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('app');
$log->pushHandler(new StreamHandler('app.log'));

Struktur Project dengan Composer

my-project/
โ”œโ”€โ”€ composer.json      # Konfigurasi dependencies
โ”œโ”€โ”€ composer.lock      # Lock file dengan versi exact
โ”œโ”€โ”€ vendor/           # Folder library (auto-generated)
โ”‚   โ”œโ”€โ”€ autoload.php  # Autoloader utama
โ”‚   โ”œโ”€โ”€ composer/     # Composer files
โ”‚   โ””โ”€โ”€ package-name/ # Installed packages
โ”œโ”€โ”€ src/             # Source code project
โ””โ”€โ”€ public/          # Public files

Instalasi Composer

Windows

Method 1: Installer (Recommended)

  1. Download Composer-Setup.exe
  2. Jalankan installer dan ikuti petunjuk
  3. Restart command prompt/PowerShell

Method 2: Manual Installation

# Download composer.phar
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

# Move to global location
move composer.phar C:\composer.phar

# Create batch file (composer.bat)
echo @php "C:\composer.phar" %* > composer.bat

Linux/macOS

# Download dan install globally
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer

# Atau via package manager (Ubuntu)
sudo apt update
sudo apt install composer

Verifikasi Instalasi

# Check versi Composer
composer --version

# Output: Composer version 2.x.x

Konfigurasi Global

# Set memory limit
composer config -g process-timeout 2000

# Set preferred install method
composer config -g preferred-install dist

# Lihat konfigurasi
composer config -g -l

Update Composer

# Update ke versi terbaru
composer self-update

# Update ke versi specific
composer self-update 2.4.0

# Rollback ke versi sebelumnya
composer self-update --rollback

Menggunakan Composer

Membuat Project Baru

# Inisialisasi project dengan composer.json
composer init

# Atau buat file composer.json manual
mkdir my-project
cd my-project
composer init

composer.json Dasar

{
    "name": "mycompany/my-project",
    "description": "Deskripsi project",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
            "name": "Nama Anda",
            "email": "email@example.com"
        }
    ],
    "require": {
        "php": ">=7.4",
        "monolog/monolog": "^2.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.0"
    },
    "autoload": {
        "psr-4": {
            "MyProject\\": "src/"
        }
    }
}

Mengelola Dependencies

# Install package
composer require monolog/monolog

# Install package versi specific
composer require "monolog/monolog:^2.0"

# Install development dependency
composer require --dev phpunit/phpunit

# Install semua dependencies dari composer.json
composer install

# Update dependencies
composer update

# Update package specific
composer update monolog/monolog

# Remove package
composer remove monolog/monolog

Version Constraints

Constraint Meaning Example
^1.2.3 Compatible version >=1.2.3 <2.0.0
~1.2.3 Reasonably close >=1.2.3 <1.3.0
1.2.* Wildcard >=1.2.0 <1.3.0
>=1.2.3 Greater or equal >=1.2.3
1.2.3 Exact version 1.2.3 only

Useful Commands

# Lihat daftar packages installed
composer show

# Lihat info package specific
composer show monolog/monolog

# Lihat packages yang bisa diupdate
composer outdated

# Validate composer.json
composer validate

# Search package di Packagist
composer search logging

# Lihat dependency tree
composer depends monolog/monolog

# Check security vulnerabilities
composer audit

Working with composer.lock

# Install exact versions dari composer.lock
composer install

# Update dan regenerate composer.lock
composer update

# Jangan commit vendor/, tapi commit composer.lock
echo "vendor/" >> .gitignore
git add composer.json composer.lock

Autoloading dengan Composer

PSR-4 Autoloading

{
    "autoload": {
        "psr-4": {
            "MyApp\\": "src/",
            "MyApp\\Controllers\\": "src/Controllers/",
            "MyApp\\Models\\": "src/Models/"
        }
    }
}

Struktur Direktori PSR-4

src/
โ”œโ”€โ”€ User.php                    # MyApp\User
โ”œโ”€โ”€ Controllers/
โ”‚   โ”œโ”€โ”€ UserController.php      # MyApp\Controllers\UserController
โ”‚   โ””โ”€โ”€ ProductController.php   # MyApp\Controllers\ProductController
โ”œโ”€โ”€ Models/
โ”‚   โ”œโ”€โ”€ User.php               # MyApp\Models\User
โ”‚   โ””โ”€โ”€ Product.php            # MyApp\Models\Product
โ””โ”€โ”€ Services/
    โ””โ”€โ”€ EmailService.php       # MyApp\Services\EmailService

Contoh Class dengan PSR-4

<?php
// src/Controllers/UserController.php
namespace MyApp\Controllers;

use MyApp\Models\User;
use MyApp\Services\EmailService;

class UserController {
    private $userModel;
    private $emailService;
    
    public function __construct() {
        $this->userModel = new User();
        $this->emailService = new EmailService();
    }
    
    public function create($data) {
        $user = $this->userModel->create($data);
        $this->emailService->sendWelcome($user);
        return $user;
    }
}
?>

File dan Class Autoloading

{
    "autoload": {
        "psr-4": {
            "MyApp\\": "src/"
        },
        "classmap": [
            "database/seeds",
            "database/factories"
        ],
        "files": [
            "app/helpers.php",
            "app/constants.php"
        ]
    }
}

Helper Functions File

<?php
// app/helpers.php
if (!function_exists('dd')) {
    function dd($data) {
        var_dump($data);
        die();
    }
}

if (!function_exists('config')) {
    function config($key, $default = null) {
        static $config;
        
        if (!$config) {
            $config = require 'config/app.php';
        }
        
        return $config[$key] ?? $default;
    }
}

if (!function_exists('view')) {
    function view($template, $data = []) {
        extract($data);
        require "views/{$template}.php";
    }
}
?>

Generate Autoload Files

# Regenerate autoload files setelah menambah class baru
composer dump-autoload

# Optimize untuk production
composer dump-autoload --optimize

# Atau dengan classmap authoritative
composer dump-autoload --classmap-authoritative

Menggunakan Autoloader

<?php
// index.php
require_once 'vendor/autoload.php';

// Sekarang bisa langsung menggunakan class
use MyApp\Controllers\UserController;
use MyApp\Models\User;

$controller = new UserController();
$user = new User();

// Helper functions juga tersedia
dd($user);
echo config('app.name');
view('welcome', ['user' => $user]);
?>

Custom Autoloader

<?php
// Custom autoloader untuk legacy code
spl_autoload_register(function ($class) {
    // Convert namespace to file path
    $file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
    
    // Include file if exists
    if (file_exists($file)) {
        require_once $file;
    }
});

// Register dengan Composer
$loader = require 'vendor/autoload.php';
$loader->addPsr4('Legacy\\', 'legacy/');
?>

Membuat Package Sendiri

Struktur Package

my-package/
โ”œโ”€โ”€ composer.json
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ LICENSE
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ MyPackage.php
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ MyPackageTest.php
โ”œโ”€โ”€ .gitignore
โ””โ”€โ”€ .github/
    โ””โ”€โ”€ workflows/
        โ””โ”€โ”€ ci.yml

composer.json untuk Package

{
    "name": "myvendor/my-package",
    "description": "Deskripsi package yang berguna",
    "type": "library",
    "license": "MIT",
    "keywords": ["php", "utility", "helper"],
    "homepage": "https://github.com/myvendor/my-package",
    "authors": [
        {
            "name": "Nama Anda",
            "email": "email@example.com",
            "homepage": "https://yourwebsite.com",
            "role": "Developer"
        }
    ],
    "require": {
        "php": ">=7.4"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.0",
        "squizlabs/php_codesniffer": "^3.0"
    },
    "autoload": {
        "psr-4": {
            "MyVendor\\MyPackage\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "MyVendor\\MyPackage\\Tests\\": "tests/"
        }
    },
    "scripts": {
        "test": "phpunit",
        "cs-check": "phpcs src/ --standard=PSR12",
        "cs-fix": "phpcbf src/ --standard=PSR12"
    },
    "extra": {
        "branch-alias": {
            "dev-main": "1.0-dev"
        }
    }
}

Contoh Package Class

<?php
// src/StringHelper.php
namespace MyVendor\MyPackage;

class StringHelper {
    /**
     * Convert string to slug
     */
    public static function slug($string, $separator = '-') {
        // Convert to lowercase
        $string = strtolower($string);
        
        // Replace non-alphanumeric with separator
        $string = preg_replace('/[^a-z0-9]+/', $separator, $string);
        
        // Remove leading/trailing separators
        return trim($string, $separator);
    }
    
    /**
     * Truncate string with ellipsis
     */
    public static function truncate($string, $length = 100, $ellipsis = '...') {
        if (strlen($string) <= $length) {
            return $string;
        }
        
        return substr($string, 0, $length) . $ellipsis;
    }
    
    /**
     * Generate random string
     */
    public static function random($length = 10) {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randomString = '';
        
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, strlen($characters) - 1)];
        }
        
        return $randomString;
    }
}
?>

Unit Test

<?php
// tests/StringHelperTest.php
namespace MyVendor\MyPackage\Tests;

use PHPUnit\Framework\TestCase;
use MyVendor\MyPackage\StringHelper;

class StringHelperTest extends TestCase {
    public function testSlug() {
        $this->assertEquals('hello-world', StringHelper::slug('Hello World'));
        $this->assertEquals('hello_world', StringHelper::slug('Hello World', '_'));
        $this->assertEquals('hello-world-123', StringHelper::slug('Hello World 123'));
    }
    
    public function testTruncate() {
        $text = 'This is a very long text that should be truncated';
        $this->assertEquals('This is a very...', StringHelper::truncate($text, 15));
        $this->assertEquals($text, StringHelper::truncate($text, 100));
    }
    
    public function testRandom() {
        $random1 = StringHelper::random(10);
        $random2 = StringHelper::random(10);
        
        $this->assertEquals(10, strlen($random1));
        $this->assertEquals(10, strlen($random2));
        $this->assertNotEquals($random1, $random2);
    }
}
?>

Publish ke Packagist

# 1. Push ke GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/username/my-package.git
git push -u origin main

# 2. Tag version
git tag v1.0.0
git push origin v1.0.0

# 3. Submit ke Packagist
# - Buka https://packagist.org
# - Login dengan GitHub
# - Click "Submit"
# - Masukkan GitHub URL: https://github.com/username/my-package

Local Development

{
    "repositories": [
        {
            "type": "path",
            "url": "../my-package",
            "options": {
                "symlink": true
            }
        }
    ],
    "require": {
        "myvendor/my-package": "@dev"
    }
}

Private Repository

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/mycompany/private-package.git"
        }
    ],
    "require": {
        "mycompany/private-package": "^1.0"
    },
    "config": {
        "github-oauth": {
            "github.com": "your-github-token"
        }
    }
}

๐Ÿ’ก Tips dan Best Practices

  • ๐Ÿ“‹ Semantic Versioning: Gunakan semantic versioning (MAJOR.MINOR.PATCH)
  • ๐Ÿ”’ Lock File: Commit composer.lock untuk dependency consistency
  • โšก Optimize Autoloader: Gunakan --optimize untuk production
  • ๐Ÿ›ก๏ธ Security: Regular update dependencies dan audit vulnerabilities
  • ๐Ÿ“š Documentation: Buat dokumentasi yang jelas untuk package
Tutorial Saat Ini
Level: Lanjutan

Untuk yang sudah mahir PHP dan ingin mendalami

Daftar Isi
Tips Belajar