قبلاً برای استفاده از یک کتابخانه، فایلش را دانلود می‌کردیم، در پوشه‌ای می‌انداختیم و با require صدا می‌زدیم. نتیجه‌اش نسخه‌های قدیمی فراموش‌شده بود که هیچ‌کس نمی‌دانست کجا هستند. Composer این کار را سامان می‌دهد: بگویید چه بسته‌هایی لازم دارید و کدام نسخه‌ها قابل‌قبول‌اند؛ بقیه‌اش را خودش انجام می‌دهد.

لاراول کاملاً روی Composer ساخته شده و حتی در وردپرس هم بیشتر ابزارهای حرفه‌ای با آن نصب می‌شوند. پس یاد گرفتنش یکی از اولین سرمایه‌گذاری‌های یک برنامه‌نویس PHP است.

Composer دقیقاً چه می‌کند#

Composer مدیر بسته‌ی PHP است. سه کار اصلی دارد:

  1. بسته‌های موردنیاز و وابستگی‌های آن‌ها را از مخزن عمومی Packagist دانلود می‌کند.
  2. نسخه‌های سازگار را پیدا و دقیقاً ثبت می‌کند.
  3. یک autoloader می‌سازد تا کلاس‌ها بدون require دستی بارگذاری شوند.

نصب را از راهنمای رسمی getcomposer.org انجام دهید، چون روش نصب بسته به سیستم‌عامل فرق می‌کند. بعد از نصب، composer --version باید جواب بدهد.

شروع یک پروژه و نصب بسته#

در پوشه‌ی پروژه این را اجرا کنید:

Bash
composer init
composer require monolog/monolog

دستور اول فایل composer.json را می‌سازد و دومی بسته را نصب می‌کند. حالا سه چیز پدید می‌آید: composer.json، composer.lock و پوشه‌ی vendor. استفاده‌ی ساده:

PHP
<?php
declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

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

$log = new Logger('app');
$log->pushHandler(new StreamHandler(__DIR__ . '/app.log'));
$log->warning('کاربر وارد شد');

تنها یک require برای autoload کافی است؛ بقیه‌ی کلاس‌ها خودکار پیدا می‌شوند.

composer.json و composer.lock#

فایل composer.json را شما می‌نویسید و می‌گوید چه می‌خواهید:

JSON
{
    "name": "acme/shop",
    "require": {
        "php": "^8.1",
        "monolog/monolog": "^3.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^10.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

علامت ^3.0 یعنی هر نسخه‌ی سازگار با ۳ که تغییر ناسازگار نداشته باشد. فایل composer.lock را خود Composer می‌نویسد و نسخه‌ی دقیق هر بسته را ثبت می‌کند. قاعده‌ی طلایی این است:

فایلچه کسی می‌نویسددر گیت باشد؟
composer.jsonشمابله
composer.lockComposerبله (برای اپلیکیشن)
vendor/Composerمعمولاً نه

lock تضمین می‌کند سرور و سیستم شما دقیقاً یک نسخه را اجرا کنند. برای مدیریت این فایل‌ها در گیت، گیت برای شروع را ببینید.

autoload با PSR-4#

بخش autoload در مثال بالا می‌گوید کلاس‌های namespace با نام App در پوشه‌ی src هستند. یعنی کلاس App\Service\Mailer باید در src/Service/Mailer.php باشد:

PHP
<?php
declare(strict_types=1);

namespace App\Service;

final class Mailer
{
    public function send(string $to, string $subject): bool
    {
        // منطق ارسال
        return true;
    }
}

بعد از تغییر بخش autoload، دستور composer dump-autoload را اجرا کنید تا نقشه دوباره ساخته شود. نام فایل باید با نام کلاس یکی باشد، با همان حروف بزرگ و کوچک، چون سرور لینوکس به آن حساس است.

دستورهای روزمره#

  • composer install: نسخه‌های ثبت‌شده در lock را نصب می‌کند. روی سرور و برای هم‌تیمی‌ها.
  • composer update: بسته‌ها را طبق قیدها به‌روز می‌کند و lock را عوض می‌کند. روی سیستم توسعه.
  • composer require vendor/pkg: بسته‌ی جدید اضافه می‌کند.
  • composer remove vendor/pkg: بسته را حذف می‌کند.
  • composer outdated: بسته‌های دارای نسخه‌ی تازه را فهرست می‌کند.
  • composer audit: وابستگی‌ها را با فهرست شکاف‌های امنیتی شناخته‌شده می‌سنجد.

هر چند وقت یک‌بار composer audit را اجرا کنید؛ بسته‌ی قدیمی یکی از راه‌های رایج ورود مهاجم است. درباره‌ی بقیه‌ی راه‌ها در امنیت کد PHP نوشته‌ایم.

استقرار روی هاست اشتراکی#

روی سرور تولید، بسته‌های توسعه را نصب نکنید و autoloader را بهینه کنید:

Bash
composer install --no-dev --optimize-autoloader

اگر هاست دسترسی ترمینال ندارد، همین دستور را روی سیستم خودتان اجرا کنید و پوشه‌ی vendor را آپلود کنید. نسخه‌ی PHP سیستم خودتان را نزدیک نسخه‌ی هاست نگه دارید. نکته‌های دیگر هاست اشتراکی در چک‌لیست هاست اشتراکی برای لاراول آمده است.

هرگز پوشه‌ی vendor را قابل‌دسترسی مستقیم از وب نگذارید. بهتر است بیرون از ریشه‌ی عمومی سایت باشد.

نکته‌های ایمنی#

بسته‌ی ناشناس نصب نکنید: نام مخزن، تعداد کاربران و تاریخ آخرین به‌روزرسانی را نگاه کنید. نصب همه‌ی بسته‌ها یعنی اجرای کدی که خودتان ننوشته‌اید. اگر Composer را با root اجرا کنید، همین اسکریپت‌ها با دسترسی کامل اجرا می‌شوند. همچنین رمز و کلید API را در composer.json ننویسید.

وقتی چیزی خراب شد#

سه مشکل را بیشتر از بقیه می‌بینید. اول، پیام «Class not found» که تقریباً همیشه یعنی namespace با مسیر فایل نمی‌خواند یا بعد از تغییر autoload، composer dump-autoload اجرا نشده است. دوم، تعارض نسخه: دو بسته نسخه‌های ناسازگار از یک وابستگی می‌خواهند. دستور composer why-not vendor/pkg 2.0 توضیح می‌دهد چه چیزی جلوی نصب را گرفته. سوم، ناسازگاری نسخه‌ی PHP؛ بخش config.platform.php در composer.json به Composer می‌گوید نسخه‌ها را برای PHP هاست حل کند، نه PHP سیستم شما.

JSON
{
    "config": {
        "platform": { "php": "8.1.0" },
        "sort-packages": true
    }
}

چطور بسته‌ی خوب را تشخیص دهیم#

پیش از composer require دو دقیقه وقت بگذارید. ببینید مخزن هنوز نگهداری می‌شود یا نه، مشکلات باز چقدر بی‌پاسخ مانده‌اند، چند بسته‌ی دیگر به آن وابسته‌اند و مجوزش با پروژه‌ی شما جور است یا نه. بسته‌ای که برای یک کار ده‌خطی صد وابستگی می‌آورد، معمولاً ارزشش را ندارد. هر وابستگی تازه یعنی کدی که باید به‌روز نگه دارید و ریسکی که باید بپذیرید.

خلاصه#

  • Composer بسته‌ها، نسخه‌ها و autoload را مدیریت می‌کند.
  • composer.json خواسته‌ی شماست و composer.lock نسخه‌ی دقیق نصب‌شده؛ هر دو را در گیت نگه دارید.
  • روی سرور composer install بزنید و update را فقط روی سیستم توسعه اجرا کنید.
  • autoload با PSR-4 یعنی نام فایل، پوشه و namespace باید با هم بخوانند.
  • روی تولید از --no-dev --optimize-autoloader استفاده کنید.
  • composer audit را مرتب اجرا کنید و فقط بسته‌های معتبر نصب کنید.