Composer, trình quản lý gói phổ biến cho PHP, không chỉ đơn thuần là công cụ quản lý các thư viện mà dự án của bạn phụ thuộc. Nó còn cung cấp một cơ chế mạnh mẽ để xử lý các script thực thi (binaries) đi kèm với các gói thư viện đó, giúp đơn giản hóa việc sử dụng các công cụ dòng lệnh trong quá trình phát triển. Bài viết này sẽ đi sâu vào cách hoạt động của tính năng "Vendor Binaries" của Composer, cách bạn có thể định nghĩa và sử dụng chúng một cách hiệu quả.
Vendor Binary là gì?
Một "Vendor Binary" (hay "công cụ nhị phân của nhà cung cấp") là một script dòng lệnh hoặc một chương trình thực thi mà một gói Composer muốn cung cấp cho người dùng của nó. Các script này thường là những tiện ích hữu ích như bộ kiểm tra mã, công cụ phân tích tĩnh, hoặc các ứng dụng dòng lệnh đặc thù. Chúng khác với các script xây dựng nội bộ của gói vì mục đích chính là để người dùng gói thực thi trực tiếp.
Ví dụ điển hình là khi bạn cài đặt PHPUnit, lệnh phpunit được cung cấp chính là một Vendor Binary. Composer sẽ tự động thiết lập để bạn có thể dễ dàng gọi lệnh này từ dự án của mình.
Cách định nghĩa Vendor Binary
Trong tệp composer.json của gói thư viện, bạn có thể định nghĩa các công cụ nhị phân bằng khóa bin. Khóa này nhận một mảng các đường dẫn tới các tệp script thực thi:
{
"bin": ["bin/my-util", "bin/other-tool"]
}
Cấu hình này chỉ dẫn Composer rằng khi gói này được cài đặt làm một dependency trong dự án khác, các script bin/my-util và bin/other-tool cần được đưa vào thư mục chứa các binary của dự án phụ thuộc.
Cơ chế hoạt động của Vendor Binaries
Sự khác biệt giữa gói định nghĩa và gói phụ thuộc
- Gói tự định nghĩa: Khi bạn cấu hình khóa
bintrong tệpcomposer.jsoncủa chính dự án hoặc gói mà bạn đang phát triển, Composer sẽ không thực hiện bất kỳ xử lý đặc biệt nào đối với các script này. Chúng chỉ đơn giản là một phần của gói. - Gói phụ thuộc: Khi dự án của bạn yêu cầu một gói thư viện có cấu hình
bin, Composer sẽ tạo các tệp proxy (hoặc symlink trên hệ điều hành tương thích) cho các script này và đặt chúng vào thư mụcvendor/bincủa dự án hiện tại. Điều này cho phép bạn thực thi các script đó trực tiếp từ thư mục dự án của mình.
Ví dụ minh họa
Hãy xem xét hai gói thư viện:
Gói A (nguonphu/utility-package) với cấu hình:
{
"name": "nguonphu/utility-package",
"bin": ["bin/utility-command"]
}
Khi bạn chạy composer install trực tiếp trong thư mục của utility-package, tệp bin/utility-command sẽ không được xử lý theo cách đặc biệt nào.
Gói B (duan/my-application) với cấu hình:
{
"name": "duan/my-application",
"require": {
"nguonphu/utility-package": "*"
}
}
Khi bạn chạy composer install trong thư mục của duan/my-application, Composer sẽ tự động tạo một tệp proxy cho bin/utility-command của utility-package và đặt nó tại duan/my-application/vendor/bin/utility-command. Nhờ đó, bạn có thể gọi lệnh vendor/bin/utility-command trực tiếp từ dự án của mình.
Tìm vị trí trình tự động nạp của Composer
Với Composer 2.2 trở lên, bạn có thể dễ dàng định vị tệp tự động nạp (autoloader) của dự án thông qua biến toàn cục $_composer_autoload_path:
<?php
// Nạp trình tự động nạp của Composer
include $_composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php';
// ... mã script của bạn ...
Để đảm bảo tính tương thích và tận dụng tính năng này, bạn nên thêm ràng buộc phiên bản Composer vào tệp composer.json của gói:
{
"require": {
"composer-runtime-api": "^2.2"
}
}
Xác định thư mục bin của Composer
Composer 2.2.2 trở lên cung cấp biến toàn cục $_composer_bin_dir để lấy đường dẫn đến thư mục chứa các binary:
<?php
$binDirectory = $_composer_bin_dir ?? __DIR__ . '/../vendor/bin';
// ... sử dụng $binDirectory ...
Đối với các script không phải PHP (ví dụ: Bash), Composer 2.2.6 trở lên hỗ trợ biến môi trường COMPOSER_RUNTIME_BIN_DIR:
#!/bin/bash
currentBinDir=""
if [[ -z "$COMPOSER_RUNTIME_BIN_DIR" ]]; then
currentBinDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
else
currentBinDir="$COMPOSER_RUNTIME_BIN_DIR"
fi
# ... sử dụng $currentBinDir ...
Tương tự, hãy thêm ràng buộc phiên bản Composer thích hợp:
{
"require": {
"composer-runtime-api": "^2.2.2"
}
}
Xử lý tương thích trên hệ điều hành Windows
Trên môi trường Windows, Composer tự động tạo các tệp .bat tương ứng cho các binary để chúng có thể được thực thi dễ dàng từ Command Prompt hoặc PowerShell. Bạn không cần phải tự mình cung cấp các tệp .bat này trong gói của mình.
Đồng thời, Composer vẫn tạo các tệp proxy theo phong cách Unix, đảm bảo khả năng tương thích khi sử dụng Windows Subsystem for Linux (WSL) hoặc các máy ảo Linux.
Tùy chỉnh thư mục cài đặt Vendor Binaries
Ngoài thư mục mặc định là vendor/bin, bạn có thể thay đổi vị trí cài đặt các công cụ nhị phân theo hai cách:
1. Cấu hình bin-dir trong composer.json
{
"config": {
"bin-dir": "scripts"
}
}
Thiết lập này sẽ khiến Composer đặt tất cả các Vendor Binaries vào thư mục scripts tại gốc dự án của bạn.
2. Sử dụng biến môi trường COMPOSER_BIN_DIR
export COMPOSER_BIN_DIR=tools
composer install
Trong trường hợp cả hai được cấu hình, biến môi trường COMPOSER_BIN_DIR sẽ ưu tiên hơn so với cài đặt trong composer.json. Bạn thậm chí có thể đặt "bin-dir": "./" để cài đặt các binary trực tiếp vào thư mục gốc của dự án.