اگر با زبان PHP برنامهنویسی شیگرا انجام داده و از آبجکتها استفاده کرده باشید، حتما با موضوع لود کردن فایلها (کلاسها) ی مختلف روبرو شدهاید.
به طور عادی کافیست همه کلاسهای مورد نظرمان را در ابتدای اسکریپتمان لود کنیم. مشکل این راه این است که در طول برنامه احتمال دارد بنا بر شرایطی از بعضی از کلاسهایی که لود کردهایم استفاده نکنیم و یا بخواهیم تحت شرایطی خاص کلاسی را لود کنیم. در این صورت به قابلیتی به نام Autoloading نیاز داریم.
فرض کنید دایرکتوریای به نام test داریم و در آن فایلی با نام index.php و دایرکتوری دیگری با نام src داریم که شامل کلاسهای ما شده و در آن دایرکتوری دو کلاس A و B داریم.
برای استفاده از کلاسهای A و B در فایل index.php صرفا کافیست آنها را require کنیم :
<?php require_once "A.php" require_once "B.php" $a = new A(); print_r(get_included_files());
خروجی این کد به این صورت خواهد بود :
Array ( [0] => /home/index.php [1] => /home/A.php [2] => /home/B.php )
همانطور که میبینید کلاس B هم لود شده است درحالیکه از آن استفاده نکردهایم. راه حل بهتر استفاده از Autoloading است.
<?php function autoloader($class) { require_once('src/'.$class.'.php'); } spl_autoload_register('autoloader'); $a = new A(); print_r(get_included_files());
در این حالت Autoloader پیاچپی به صورت خودکار هر زمانی که در اسکریپتمان از کلاس A استفاده کردیم، بر اساس منطقی که در فانکشن `autoloader` نوشتهایم، این کلاس را لود و مورد استفاده قرار میدهد.
خروجی کد بالا به این صورت خواهد بود :
Array ( [0] => /home/index.php [1] => /home/A.php )
نکتهای که در اینجا وجود دارد این است که نام کلاسها و نام فایلها باید یکسان باشند و در هر فایل فقط یک کلاس وجود داشته باشد.
اما Composer چیست و چطور Autoloading را انجام میدهد ؟
یکی از کارهای اصلی Composer مدیریت پکیج ها در PHP بوده که احتمالا در پروژه های مختلف با آن کار کردهاید. اما کار مهم دیگری که Composer انجام میدهد مربوط به Autoload کلاس های مورد استفاده ما در برنامه است.
در مسیر اصلی (دایرکتوری test) فایلی با نام composer.json بسازید و آن را به این صورت کامل کنید :
{ "autoload": { "classmap": [ "src/" ] } }
سپس در ترمینال (خط فرمان) خود دستور `composer update` را وارد کرده تا دایرکتوری vendor ساخته شود.
حال فایل index.php را به این صورت تغییر میدهیم :
<?php require_once __DIR__."/vendor/autoload.php" $a = new A(); $b = new B(); print_r(get_included_files());
اگر به خروجی این کد نگاه کنید میبینید که فایل های A و B به صورت خودکار توسط Composer در اسکریپتمان لود شدهاند.
در واقع Composer از همان فانکشن `spl_autoload_register` استفاده میکند، اما بسیار مفصلتر. برای مشاهده دقیق تر جزئیات در دایرکتوری `vendor/composer` کلاس های autoload.php ، autoload_real.php و ClassLoader.php را مشاهده نمایید.
در اینجا ما از حالت `classmap` در Composer استفاده کردیم (به فایل composer.json توجه کنید). این حالت ساده ترین بوده و جزئیات آن را در کلاس `autoload_classmap.php` میتوانید ببینید. این فایل یک آرایه که شامل نام کلاس ها و مسیرشان است را باز میگرداند و هر بار که کلاس جدید به اسکریپتمان اضافه میکنیم باید یکبار دستور `composer update` را وارد کنیم تا این آرایه بروز شود.
اما روش های دیگری از Autoloading در Composer وجود دارد که فریم ورک معروف Laravel نیز از آن استفاده میکند و آن PSR-4 است.
{ "autoload": { "psr-4": { "Src\\": "src/" } } }
این روش امکان استفاده از از کلید namespace در PHP را به ما میدهد که کار لود کلاس ها را بسیار ساده کرده و هر بار با اضافه کردن کلاسی جدید نیازی به وارد کردن دستور `composer update` نداریم. جزئیات این روش در فایل `autoload_psr4.php` است.
برای نمونه :
<?php namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { ...
در واقع مسیری که جلوی namespace مینویسیم به شکل path پشت نام کلاس مورد نظر قرار گرفته و از یکتا بودن آن اطمینان حاصل میشود و به این ترتیب Composer به صورت داینامیک در زمان ران تایم کلاس مورد نظر را لود میکند (به همین دلیل هر بار با اضافه کردن کلاسی جدید مانند حالت classmap نیازی به وارد کردن دستور `composer update` نداریم).
همینطور دستور use به ما کمک میکند تا در برنامه مجبور نباشیم مسیر و نام کلاسمان را تکرار کنیم و در زمانی که قصد استفاده از از دو کلاس همنام با مسیرهای متفاوت را داریم، با استفاده از use میتوانیم نام مستعاری (alias) به کلاسمان بدهیم و از آن نام در برنامه استفاده کنیم.
منابع :
http://php.net/manual/en/language.oop5.autoload.php
http://php.net/manual/en/function.spl-autoload-register.php
http://php.net/manual/en/function.get-included-files.php
https://getcomposer.org/doc/04-schema.md#autoload
https://www.php-fig.org/psr/psr-4
https://dev.to/blocksbylukas/the-magic-behind-autoloading-php-files-using-composer-1e19
https://medium.com/tech-tajawal/php-composer-the-autoloader-d676a2f103aa