شرح Autoload Classes With Composer in PHP

إحنا ليه محتاجين نستخدم الـ Autoloading?

لو أنت بتبني مشروع بلغة PHP ، غالباً هتحتاج تستخدم Libraries أو Classes أو حتى Functions  موجود جوة ملف تاني.
عشان تستخدم الـThird-Party أو كود من ملف تاني غير الملف الحالي فأنت هنا محتاج تدمج الملفين في بعض أو بصورة أدق، أنت محتاج تضمنهم في الكود بتاعك وطبعاً مش هينفع نعمل Copy-Past أكيد أنت عارف ليه.
طبعاً أول حل هيجي في بالك أنت تعمل include أو تعمل require و دا فعلاً حل مناسب جداً لو أنت بتعمل مشروع صغير،
بس حتى لو المشروع بتاعك مش ضخم فأنت هتقابلك مشكلة في المستقبل وهي إن المشروع بتاعك كل فترة بيكبر منك وكُل ما المشروع بيكبر أنت عمال تعمل include  و require للكل الملفات اللي محتاجها ودا هيسبب مشكلتين:
أول مشكلة أن هيخليك مش هتقدر تعمل Maintain  للكود بتاعك بسهولة.
المشكلة التانية إنك بقيت بتضطر تعمل include لملفات أنت مش محتاجها كتير أو محتاج جزء صغير منها ودا هيسبب حاجة إسمها:
Memory footprint تقدر تقرأ عنها من الرابط دا

طيب وإيه الحل؟
الحل إنك تعمل include للملفات أو الـ Classes لما تبقا بس محتاجها، ودا أبسط تعريف للــ Autoloading

فكرة الـ Autoloading إن الــAutoloder بيعمل Check لو الكلاس إللي انت طالب تستخدمه موجود في الفعل؟ ولا لا؟ لو موجود خلاص هو مش هيعمل حاجة، لكن لو مش موجود هيروح يعمله include مرة واحدة فقط.
و بكدة إنت مش محتاج كل شوية تعمل autoload للمفات بتاعتك بشكل  Manual أنت بس محتاج تعمل require للـ ِAutoloader بتاعك و هو هيقوم باللازم.

إزاي أعمل autoloading  بدون الـ Composer? إزاي أصلا أقدر أعمل Autoload?

تقدر تعمل Autoloading في لغة PHP عن طريق الـFunction : spl_autoload_register()

الدالة دي بتسمح لك إنك تمرر ليها الـFunctions إللي هيتم تنفيذها بشكلل متتابع لما تحاول تـ load أيClass مش موجود

يعني أنت هتكتب سطر كود واحد داخل الدالة دي، كل دوره إنه يعمل  include لأي كلاس يجيله :


في المثال إللي فوق دا إحنا عملنا register للـFunction بتاعتنا إللي عرفناها بإسمcustom_autoloader()

لما تيجي بعد تعمل أوبجكت من الكلاس إللي إسمه TestClass وهو مش موجود أو لم يتم عمل include له هيحصل إيه.؟
PHP قبل ما تقول إن الكلاس دا مش موجود هتروح تـExecute لكل الـ register Functions بالترتيب لحد ما توصل للـ custom_autoloader() هتلاقي إنها لقت كلاس موجود بالإسم دا فهتعملك الأوبجكت إللي انت عايزه وفي الحالة دي هي بتفترض إنك كل الـ Classes  بتاعتك موجود داخل مجلد واحد إسمه Classes يعني بالشكل دا :
"Classes/TestClass.php"

المثال إللي فوق كان سهل وبسيط لأنك بتحاول تـ include الـ Classes  بتاعتك من مُجلد واحد إسمه Classes، لكن لو أنت عندك أنواع مختلفة من الـClasses كل نوع في مجلد مختلف؟؟
- طبعاَ دا هيعمل مشكلة لو أنت بتبني حاجة MVC مثلاً لأن مش كل الـ Classes هتبقا في مكان واحد.
الـ Composer سهل علينا الموضوع وعشان كدة هنشوف إزاي ممكن نعمل Autoloading يإستخدام الـComposer

ازاي أقدر أعمل autoloading بإستخدام الـ Composer ?
-هنفترض إنك تعرف يعني إيه Composer و إنك فعلاً عامله  install، عشان كدة هنتكلم على طول عن الأربع طرق إللي بيقدمهم لينا الـ composer عشان نعمل Autoload

1-Files autoloading

2-classmap autoloading

3-PSR-0 autoloading

4-PSR-4 autoloading

الـ official Composer documentation  بيـ Recommend  إنك تسخدم طريقة PSR-4 في الـ Autoloading وإحنا هنتكلم عنها بس بعد ما نتكلم عن الثلاثة أنواع الأخرى.

- أول حاجة هنعملها هتروح على الـ root directory للبروجيكت بتاعك وتعمل ملف إسمه composer.json.

و دا الملف إللي هنكتب فيه كُل الـ directives لكل نوع هنستخدمه مع الـautoloading

بعد كدة هنروح على الـ Terminal  و ننفذ الأمر دا :
composer dump-autoload -o

و الأمر دا وظيفته إنه هيعمل generate للملفات الأساسية إللي الـComposer هيستخدمها في الـAutoloading

بعد ما تنفذ الأمر هتلاحظ إن في مجلد جديد ظهر في البروجيكت بتاعك إسمه vendor

ودا إللي بيحتوي على الملفات إللي الـcomposer عملها generate.

بعد كدة كُل إللي عليك إن الصحفة إللي هتحتاج تعمل فيها autoload هتكتب في أول سطر الكود دا فقط ومن هنا الـComposer بيبدأ يعمل include  للملفات نيابة عنك

require 'vendor/autoload.php'

نيجي بقا للأربع أنواع أو الأربع Directives للـ Autoloading

1- Autoloading : The files Directive:

الطريقة دي بتشتغل بنفس طريقة الـ include و الــ require بالضبط، ودي بتسمح لك إنك تعمل load لملفات أخرى(إللي أنت هتدخل المسارات بتاعها جوا الـdirective كمان شوية) في كل مرة التطبيق بتاعك هيشتغل.

ودي طبعاً مفيدة جداً مع الملفات اللي هي مش Classes

أستخدمها إزاي؟
عشان تستخم الـ Files autoloading هتروح تعمل قائمة أو Array وتدخل فيها مسار كل ملف عايز تعمله autoload و تعطيها للـ directvie as a value

الكلام دا هتكتبه داخل ملف الـ composer.json إللي أنشأناه أول ما بدأنا و هتكتب بالطريقة دي :


زي ما شوفت في الكود بتقدر تعطي للـ files directive قائمة بكل الملفات اللي محتاج تعملها autoload و كالعادة هتروح تنفذ الأمر دا :

composer dump-autoload -o

بعد كدة بتعمل  include  في الصفحة بتاعتك عشان تقدر توصل للعناصر الموجود داخل الملفات دي

require 'vendor/autoload.php';

2- Autoloading : The classmap Directive:

 - حاجة كدة زي files directive بس متطورة شوية، كل إللي محتاجه إنك هتعطي للـ classmap قائمة بردو بس بأسماء الـdirectories إللي أنت عايزه يدور فيها، و الـ Composer هياخد لفة في كل الملفات الموجودة في كل المجلدات إللي أنت بعتهاله و أي كلاس هيلاقيه هياخد إسمه و المسار بتاعه و يروح يسجله جوة array تانية وبكدة يبقا عمل قائمة تحتوي على إسم كل كلاس و مقابل له المسار بتاعه.
لما أنت تيجي تنادي على أي كلاس عشان تاخد منه أوبجكت مثلاً الـ composer هيروح يدور في القائمة دي على إسم الكلاس لو لقاه هيعمل autoload  للملف الموجود أمامه.
إزاي بنكتب الـ classmap directive?


وما تنساش تنفذ الأمر :
composer dump-autoload -o

3 - Autoloading : PSR-0 :

recommended by the  PHP-FIG group for autoloading.

لازم تستخدم معاها الــ Namespaces وأنت بتعرف الـ Classes إللي هتعملها Autoload

و أنت بتنشأ أوبجكت من أي كلاس لازم The Fully Qualified class Name.

/<Vendor Name>\(<Name Space>\)* <Class Name>

كمان لازم تحفظ الملفات بتاعتك بنفس التسلسل و التركيب بتاع الـNamespace.


- هتلاحظ هنا إني كتبت إسم المجل "src"من غير تسلسل الـnamespace
لكن في الحقيقة الـcomposer مش هيروح يدور على الكلاس جو مجلد src
لكن هيدخل يدور جوا المجلدات اللي داخل مجل الـsrc  بالطريقة دي :

"src/App/config/clasename.php"

و دا طبعاً نفس ترتيب الـ Namespace :

"App\config\className"

يعني هيتبع نفس تركيبة الـ Namespace ولو ملقاش نفس التسلسل بنفس الأسماء دا هيعمل مشكلة.
فلما تيجي أنت تعرف كلاس في مجلد "src/App/config/ClassName.php"

هتعرفه بالطريق دي :


و لما تيجي تعمل Autoload هتكتبه بالطريقة دي :


4 - Autoloading : PSR-4 :

هي مشابهة تماماً للـ PSR-0 ولكن الإختلاف إنك مش هتكتب الـ Directories Structure زي الـ Name space بالظبط

بمعنى إنك كنت في الـ PSR-0 بتكتب الـ namespace  نفس الـdirectories Structure بالظبط

فلو عايز تعمل Autoload  للكلاس : App\config

فلازم يكون موجود داخل المجلد src\App\config\Config.php

لكن في الـ PSR-4  أنت بتكتب الـ namespace بعدها (\\)

"App\\" : "src"

دا معناه إن أي حاجة بتيجي بعد الـ (\\) هيروح يدور عليها داخل مجلد src حتى ولو كانت جوة مجلد جوة مجلد تاني ، أو حتى لو كانت جوة الـ src نفسه


الكود دا بيقول للـcomposer إن اي حاجة تيجي بعد الـnamespace إللي إسمها App  روح دور عليها في كل المجلدات الموجود داخل المجلد إللي إسمه App

متنساش تنفذ الأمر :

composer dump-autoload -o

حابب أقول في النهاية إن الـPSR-4 بيستخدمها الغالبية العظمى من مطوري الـPHP نظراً لسهولتها وإنه بتفي بالغرض.

تعليقات

المشاركات الشائعة من هذه المدونة

JavaScript Data Types Summary - ملخص أنواع البيانات في لغة جافا سكريبت

The Difference between getcwd() AND dirname(__FILE__) -- getcwd() و الدالة dirname(__FILE__) الفريق بين الدالة