آموزش استفاده از Composer در PHP

چرخ را دوباره اختراع نکنید! همه ما توسعه دهنده های نرم افزار در پروژه هایی که توسعه می‌دهیم به ابزاری نیاز داریم که توسط دیگر توسعه دهنده ها از پیش ساخته و منتشر شده. ما می‌توانیم به جای بازطراحی آنها فقط تصمیم بگیریم که از آنها استفاده کنیم! اما استفاده از این ابزار ها یا به اصطلاح پکیج ها خودش به پیچیدگی هایی ختم می‌شود که مجبور می‌شویم به دنبال راهکار هایی برای آن بگردیم که البته راه حل مناسب استفاده از یک ابزار مدیریت وابستگی است و در این باره نیز باید گفت چرخ را دوباره اختراع نکنید!

Composer the PHP Depebdency Manager
Composer the PHP Depebdency Manager

مدیریت وابستگی

همانطور که پیشتر اشاره کردیم وقتی برای توسعه یک پروژه از پکیج های آماده که توسط دیگران ساخته شده استفاده می کنیم پیچیدگی هایی پیش می آید که نیازمند مدیریت هستند. در ادامه دو مورد از این پیچیدگی ها را بررسی می کنیم.

بروزرسانی وابستگی ها

پکیج ها همانند نرم افزار ها در طول زمان توسعه داده می‌شوند و یا باگ های موجود در آنها رفع می شود و نسخه های جدیدی از آنها منتشر می‌شود. به عنوان مصرف کننده باید آنها را به روز نگه داشته تا کیفیت و امنیت محصول خود را تضمین کنیم. علاوه بر به بروزرسانی مداوم پکیج های مورد استفاده باید به هنگام بروزرسانی به نسخه جدید سازگاری نسخه جدید با پروژه خود را بررسی کنیم تا مبادا پروژه دچار مشکل شود.

وابستگی های تو در تو

پکیج های مورد نیاز پروژه (وابستگی های سطح اول) برای ارائه کاربرد مورد نظر ممکن است از پکیج های دیگر استفاده کنند و خود وابستگی هایی که آنرا وابستگی های سطح دوم می‌نامیم داشته باشند. این داستان ممکن است ادامه دار باشد و حتی وابستگی های سطح سوم، چهارم و … هم به وجود بیایند. برای مدیریت این مسئله دو راهکار را می‌توان در نظر گرفت: ۱) برای هر پکیج وابستگی های آن را در دایرکتوری همان پکیج قرار بدهیم و سلسله مراتبی از وابستگی ها به وجود بیاوریم. ۲) همه پکیج ها از همه سطوح وابستگی را بدون اینکه تفاوتی برای سطح آنها قائل شویم را در کنار هم قرار دهیم.

در راهکار اول مدیریت بسیار ساده تر می‌باشد اما با توجه به اینکه در واقعیت بسیاری از وابستگی ها مشترک هستند حجم بسیار زیادی از پکیج تکراری خواهیم داشت و عملا این راهکار ناکارآمد است.

در راهکار دوم که معمولا راهکار برگزیده ابزار های مدیریت وابستگی می‌باشد، همه وابستگی ها از سطوح مختلف در کنار هم نگهداری می‌شوند تا از دانلود مجدد و نگهداری آنها در مکان های مختلف جلوگیری شود. در این راهکار باید نسخه پکیج مورد نظر را با دقت انتخاب کنیم که سازگار با تمام پکیج های دیگر و پروژه اصلی باشد.

ابزار مدیریت وابستگی

با توجه توضیحاتی که شرح دادیم لزوم وجود یک ابزار نیرومند برای مدیریت وابستگی ها در پروژه های نرم افزاری کاملا احساس می‌شود. مهمترین وظیفه این ابزار دانلود نسخه مناسب از پکیج های مورد نیاز از مخزن های تعریف شده و قرار دادن آنها در اختیار توسعه دهنده و پروژه است.

برای زبان های برنامه نویسی مختلف ابزار های مختلفی طراحی شده است؛ برای مثال Maven و Gradle برای جاوا، pip برای پایتون، SBT برای اسکالا و Dep برای Go را می توان نام برد. برای زبان برنامه نویسی PHP در گذشته از ابزار Pear استفاده می‌شد اما سال ‌هاست که Composer نه به عنوان ابزار رسمی اما به عنوان محبوب ترین ابزار مدیریت وابستگی در پروژه های PHP استفاده می‌شود.

قرارداد نامگذاری نسخه ها

یکی از مباحث مهمی که باید در استفاده و توسعه وابستگی ها به آن توجه کنیم قرارداد نامگذاری نسخه ها است. قرارداد های مختلفی در این زمینه وجود دارد. محبوب ترین این قرارداد ها که توسط سایت semver.org تعریف شده به این صورت است:

MAJOR.MINOR.PATCH

در این قرارداد نامگذاری، نسخه پکیج (یا نرم افزار) از سه بخش تشکیل می‌شود که ادامه هر کدام را توضیح می‌دهیم.

بخش MAJOR در نسخه ها

بخش اول در نام نسخه Major نام دارد که بخش اصلی نسخه پکیج به حساب می آید و تغییر آن به معنی وجود تغییرات بنیادی یا مهم در نسخه جدید پکیج است و لزوما با نسخه قبلی سازگار نمی‌باشد. در صورتی که ما توسعه دهنده پکیج هستیم و در نسخه جدید تغییراتی در رابط کاربری (API) پکیج ایجاد کرده‌ایم که کاربران نسخه قبلی بدون تغییر نمی‌توانند از این نسخه استفاده کنند، ما این بخش از نسخه را یک واحد افزایش می دهیم. برای مثال اگر نسخه قبلی پکیج ما 2.6.1 بوده نسخه جدید را باید 3.0.0 نامگذاری کنیم. در صورتی که ما کاربر یک پکیج هستیم باید به هنگام بروزرسانی پکیج توجه کنیم که با بروزرسانی به نسخه با Major بالاتر، ممکن است به تغییراتی در پروژه برای سازگاری با نسخه جدید نیازمند باشیم.

بخش MINOR در نسخه

بخش دوم در نام نسخه Minor نام دارد که بخش فرعی پکیج به حساب می‌آید و تغییر آن به معنی معرفی شدن فیچر (قابلیت) جدید یا بهبود قابل توجه با حفظ سازگاری با نسخه قبلی است. برای مثال اگر نسخه پکیج 2.6.1 است، چنین تغییری می‌تواند به نسخه 2.7.0 منجر شود. با توجه توضیحات ذکر شده می توان با خاطری نسبتا آسوده پکیج ها را به نسخه با Minor بالاتر بروزرسانی کنیم.

بخش PATCH در نسخه

بخش سوم نام نسخه Patch نام دارد که تغییر آن معمولا بخاطر تغییرات کوچک (برای مثال رفع باگ) است و معمولا هیچ قابلیت جدیدی برای معرفی وجود ندارد. Patch های جدید با نسخه قبلی باید کاملا سازگار باشند.

ابزار Composer

همانطور که اشاره کردیم Composer محبوب ترین ابزار مدیریت وابستگی برای پروژه های مبتنی بر زبان برنامه نویسی PHP می‌باشد که فریم ورک های معروف PHP از جمله Laravel و Symfony از این ابزار استفاده می‌کنند. این ابزار امکانات بسیاری را در اختیار توسعه دهنده ها قرار می‌دهد و ما سعی کردیم در این مقاله تعدادی از آنها را معرفی کنیم.

کمپوزر بطور پیشفرض از مخزن packagist.org برای دانلود پکیج ها استفاده می‌کند. در سایت مربوط به این مخزن می‌توانید پکیج های قابل استفاده را مشاهده کنید.

نصب Composer

کومپوزر را می توانید از سایت getcomposer.org دانلود و نصب کنید. در ادامه روش نصب این ابزار را در سیستم عامل های مک، ویندوز و توزیع های لینوکس را توضیح می‌دهیم.

در سیستم عامل Mac OS می‌توانید از ابزار Homebrew استفاده کنید و با اجرای فرمان زیر در ترمینال Composer را نصب کنید.

brew install composer

در سیستم عامل ویندوز می‌توانید فایل نصب را از سایت getcomposer.org دانلود و اجرا کنید. پس از نصب آن باید مسیر (آدرس فولدر) فایل اجرایی Composer را به Path های سیستم اضافه کنید.

در توزیع های لینوکس با اجرای دستورات زیر می‌توایند Composer را نصب کنید.

curl -sS https://getcomposer.org/installer -o composer-setup.php
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer

پس از نصب Composer می توانید صحت نصب را با اجرای دستور زیر در خط فرمان (ترمینال) بررسی کنید.

composer --version

نصب وابستگی های پروژه

در صورتی که در پروژه خود به یک پکیج نیاز دارید ابتدا باید آنرا در مخزن packagist.org پیدا کنید. در صفحه مربوط به پکیج در سایت Packagist می توانید روند افزودن آن به پروژه مشاهده کنید. برای مثال برای افزودن پکیج miladrahimi/phprouter به پروژه می‌توانید دستور زیر را در دایرکتوری پروژه اجرا کنید.

composer require miladrahimi/phprouter

با افزودن اولین وابستگی به پروژه، Composer دو فایل composer.lock و composer.json و همچنین دایرکتوری vendor را به پروژه شما اضافه می‌کند و در صورت وجود این فایل ها و دایرکتوری، آنها را بروزرسانی می‌کند.

برای افزوده شدن وابستگی به پروژه، Composer آنرا از مخزن packagist.org دانلود کرده و در دایرکتوری vendor قرار می‌دهد. در ادامه وابستگی مورد نظر را به بخش require در فایل composer.json اضافه می‌کند و نهایتا composer.lock را هم مطابق با composer.json و نسخه دقیق نصب شده بروزرسانی می‌کند.

در صورتی که پکیج مورد نظر تنها در روند توسعه پروژه کاربرد دارد و در سرور اصلی نیازی به نصب آن نیست، می‌توانید با دستوری مشابه دستور زیر آنرا به پروژه اضافه کنید.

composer require phpunit/phpunit --dev

دستور بالا پکیج phpunit/phpunit را به بخش require-dev در composer.json اضافه خواهد کرد.

چنانچه نسخه خاصی از پکیج مد نظرتان هست می‌توانید همانند دستور زیر آنرا به پروژه به اضافه کنید:

composer require miladrahimi/phprouter:&quot5.0&quot

با اجرای دستور بالا نسخه 5.0 از پکیج مورد نظر نصب می‌شود. از آنجایی که نسخه ذکر شده فاقد بخش Patch می‌باشد، کمپورز آخرین Patch (برای مثال 5.0.2) نصب می‌کند.

به مثال دیگری که در ادامه آورده ایم هم توجه کنید.

composer require miladrahimi/phprouter:&quot5.*&quot

با اجرای این دستور نسخه *.5 از پکیج نصب خواهد شد. Composer جدیدترین نسخه از پکیج که بخش Major آن 5 می‌باشد (برای مثال نسخه 5.1.0) را نصب خواهد کرد.

برای مشاهده دیگر فرمت های نوشتن نسخه که توسط Composer معرفی شده است می تواند به مقاله رسمی سایت Composer با نام Versions and constraints مراجعه کنید.

فایل composer.json

فایل composer.json پس از اجرای دستور init یا افزودن اولین وابستگی به پروژه در دایرکتوری پروژه ایجاد می‌شود. این فایل را که می‌توان به طور دستی و با یک Text Editor هم ساخت، شامل لیست وابستگی ها (پکیج ها مورد نیاز پروژه)، مخزن ها، Auto-loader ها و همه اطلاعاتی است که Composer از پروژه شما نیاز دارد که بداند.

در این فایل نسخه پکیج ها را می توان بصورت انعطاف پذیر همانند *.v3 یا *.v3.6 نوشت تا بروزرسانی پکیج ها و همچنین جلوگیری از نصب نسخه غیر قابل سازگار ممکن باشد.

فایل composer.lock

فایل composer.lock که در کنار فایل composer.json قرار می‌گیرد شامل اطلاعات دقیق از آخرین نصب یا بروزرسانی وابستگی ها می باشد. این فایل به هنگام اجرای دستور install مورد استفاده قرار می‌گیرد تا از نصب ناخواسته نسخه های جدید در محیط های حساس جلوگیری شود. پیشنهاد می شود این فایل به همراه پروژه به سرور منتقل شود تا با نصب وابستگی ها در سرور مطمئن باشیم همان نسخه استفاده شده در محیط تست (یا توسعه) بر روی سرور نصب می‌شود.

دایرکتوری vendor

این دایرکتوری حاوی تمام پکیج های دانلود شده توسط Composer می‌ باشد که مورد نیاز پروژه است. علاوه بر پکیج های نصب شده، اطلاعات مربوط به نحوه بارگذاری آنها و همچنین فایل autoload.php در این دایرکتوری نگهداری می شود.

با توجه به اینکه با استفاده از اطلاعات موجود در فایل های composer.json و composer.lock و نرم افزار Composer هر زمان و هر کجا می توان مجددا تمام پکیج های مورد نیاز پروژه را نصب کرد به هنگام به اشتراک گذاری، آپلود به سرور یا مخزن Git و Deploy این دایرکتوری را می‌توان git ignore کرد.

بارگذاری خودکار (Autoload) پکیج ها

همانطور که قبلا گفتیم Composer پکیج های مورد نیاز پروژه را پس از دانلود در دایرکتوری vendor قرار می‌دهد. Composer همچنین فایلی به نام autoload.php در این دایرکتوری ایجاد می‌کند. این فایل حاوی Auto-loader برای تمام پکیج های نصب شده توسط Composer است و با require کردن آن در پروژه می‌توان از پکیج های نصب شده استفاده کرد. مثال زیر نحوه استفاده از پکیج miladrahimi/phprouter را نشان می‌دهد:

<?php

require &quotvendor/autoload.php&quot

use MiladRahimi\PhpRouter\Router;

$router = Router::create();
$router->get('/', function () {
    return 'Hello World!';
});
$router->dispatch();

بروزرسانی وابستگی ها

پس از نصب وابستگی ها ممکن است نیاز باشد که آنها را بروزرسانی کنیم. در این صورت می‌توانید از دستوری مشابه دستور زیر استفاده کنید.

composer update miladrahimi/phprouter

پس از اجرای دستور بالا جدیدترین نسخه سازگار (مطابق با composer.json) از پکیج مورد نظر توسط Composer دانلود و جایگزین نسخه قبلی آن در دایرکتوری vendor می‌شود. همچنین فایل composer.lock هم بروزرسانی می شود اما هیچ تغییر در فایل composer.json نخواهیم داشت.

در صورتی که می‌خواهید همه وابستگی ها را بروزرسانی کنید می‌توانید از دستور زیر استفاده کنید.

composer update

این دستور تمام وابستگی ها، دایرکتوری vendor و فایل composer.lock را بروزرسانی می‌کند. این دستور را با دستور زیر که خود نرم افزار Composer را بروزرسانی می‌کند اشتباه نگیرید.

composer self-update

نصب وابستگی ها در سرور

همانطور که قبلا توضیح دادیم بهتر است دایرکتوری vendor را به هنگام آپلود پروژه در سرور یا در مخزن هایی مانند گیتهاب ignore کرد. همچنین در صورتی که بطور کلاسیک برای Deploy پروژه روی سرور آنرا آپلود می کنید. در این صورت به هنگام دریافت پروژه، دایرکتوری vendor را نداریم اما می‌توان با دستور زیر مجددا وابستگی ها را نصب کنیم.

composer install

دستور بالا در صورتی که فایل composer.lock وجود داشته باشد، پکیج ها را مطابق با نسخه دقیق ثبت شده در آن نصب می‌کند و در غیر این صورت با استفاده از اطلاعات موجود در فایل composer.json آخرین نسخه سازگار با پروژه را نصب خواهد کرد.

در محیط هایی همانند سرور اصلی با استفاده از پارامتر no-dev-- می‌توانید از نصب پکیج های مورد نیاز محیط های تستی جلو گیری کنید.

composer install --no-dev

تعریف autoload پروژه

یکی از قابلیت های مفیدی که Composer ارائه می دهد، امکان تعریف autoload برای پروژه است. در بخش های قبل متوجه شدیم که برای بارگذاری پکیج های دانلود شده توسط Composer باید فایل vendor/autoload.php در پروژه خود require کنید. از طرفی پروژه شما هم به یک Auto-loader برای بارگذاری کلاس های پروژه نیاز دارد. با قابلیت مورد نظر نیاز نیست که شما به طور جداگانه یک Auto-loader طراحی کنید، تنها کافیست تا اطلاعات بارگذاری پروژه را به composer.json اضافه کنید تا همان autoload موجود در دایرکتوری vendor کلاس های پروژه شما را هم بارگذاری کند.

&quotautoload&quot: {
    &quotpsr-4&quot: {&quotApp\\&quot: &quotapp/&quot}
 }

با افزودن بخش بالا به فایل composer.json، کمپوزر مطابق با استاندارد PSR-4 کلاس هایی که namespace آنها با عبارت App شروع می‌شود را از دایرکتوری app درون دایرکتوری پروژه بارگذاری میکند. برای مثال:

App\Models\User => ./app/Models/User.php
App\Controllers\Admin\UsersController => ./app/Controllers/Admin/UsersController.php

مخزن ها

سرور Packagist مخزن رسمی و عمومی Composer است و Composer برای نصب پکیج ها به این مخزن رجوع می کند. با وجود مخزن Packagist برای پکیج های خصوصی و یا پکیج هایی که در این مخزن رجیستر نشده‌اند ما به مخزن های ثانویه نیازمندیم که خوشبختانه Composer به راحتی به ما اجازه می‌دهد تا این مخزن ها را برای پروژه تعریف کنیم.

در صورتی که مخزن مورد یک مخزن خصوصی در یک سرور Git همانند GitHub یا GitLab است، می‌توانید با آنرا همانند کد زیر به فایل composer.json اضافه کنید.

&quotrepositories&quot: [
    {
            &quottype&quot: &quotgit&quot,
            &quoturl&quot: &quothttps://github.com/private-company/foo&quot
    }
],
&quotrequire&quot: {
    &quotprivate-company/foo&quot: &quot1.*&quot
}

در صورتی که پکیج مورد نظر شما فقط در قالب تعدادی فایل در کامپیوتر دسترس است می‌توانید به شکل زیر آنرا در composer.json اضافه کنید.

&quotrepositories&quot: [
    {
        &quottype&quot: &quotpath&quot,
        &quoturl&quot: &quot../../packages/my-package&quot
    }
],
&quotrequire&quot: {
      &quotmy/package&quot: &quot*&quot
}

برای اطلاعات بیشتر در زمینه مخزن ها می توانید بخش Repositories از مستندات رسمی Composer را مطالعه کنید.

گفتار پایانی

در این مقاله با مفاهیم مقدماتی از Composer آشنا شدید اما برای مطالعه بیشتر و آشنایی بیشتر با قابلیت های این ابزار مفید می توانید به مستندات رسمی مراجعه کنید.