PHP & Composerمراجعة سريعة.
قبل ما تدخل Magento، فيه أساسيات لازم تكون مرتاح معاها. مش كل PHP — بس اللي هتشوفه فعلًا في كود Magento: مميزات PHP 8 الأساسية، والـ Composer وautoloading والـ namespaces.
كود Magento 2 والـ extensions الحديثة بيستخدموا مميزات PHP 8 زي type declarations و constructor promotion و readonly properties، وكل class عايش جوّه namespace. الـ Composer بيدير الـ packages والاعتماديات، وبيعمل autoloading بمعيار PSR-4 اللي بيربط الـ namespace بمسار الملف، فمش محتاج require يدوي. الأساس ده بيخلّي قراية كود Magento أسهل بكتير.
Type Declarations
تحديد أنواع البيانات — بتشوفها في كل كلاس في Magento.
الـ type declarations بتحدد نوع الـ parameters والـ return والـ properties. بتخلّي الكود أوضح وبتمسك الأخطاء بدري.
class Product { // typed property private string $name; private float $price = 0.0; // typed params + return type public function setPrice(float $price): void { $this->price = $price; } public function getName(): string { return $this->name; } }
?string معناها string أو null. وint|string معناها الاتنين مقبولين (union type من PHP 8).
Constructor Promotion
اختصار PHP 8 اللي Magento بيستخدمه بكثافة في الـ DI.
قبل PHP 8، عشان تحقن dependency كنت بتكتبها 3 مرات: property، parameter، وتعيين. تكرار ممل.
class MyService { private ProductRepository $repo; public function __construct( ProductRepository $repo ) { $this->repo = $repo; // assignment } }
class MyService { // property + param + assignment in one! public function __construct( private readonly ProductRepository $repo ) {} }
مميزات PHP 8 مفيدة
حاجات صغيرة بتشوفها كتير في الكود الحديث.
الـ ?-> بيتجنّب error لو الـ object null. بدل ما تشيك يدوي.
// old: needs null check $country = null; if ($order) { $country = $order->getAddress()->getCountry(); } // PHP 8: nullsafe chain $country = $order?->getAddress()?->getCountry();
زي switch بس أنضف، بيرجع قيمة، وبيقارن بدقة (strict).
$label = match($status) { 1 => 'Pending', 2 => 'Complete', default => 'Unknown', };
نوع بيحدد مجموعة قيم ثابتة ممكنة — بدل الـ constants المبعثرة.
enum Status: string { case Pending = 'pending'; case Complete = 'complete'; }
Namespaces
أساس تنظيم الكود في Magento — وبيرتبط مباشرة بالـ autoloading.
الـ namespace زي "عنوان" للكلاس، بيمنع تضارب الأسماء. ممكن يكون عندك Product في مكانين، والـ namespace بيميّزهم.
// declares the namespace namespace Vendor\Module\Model; // import a class from another namespace use Magento\Catalog\Api\ProductRepositoryInterface; class Product { public function __construct( private readonly ProductRepositoryInterface $repo ) {} }
Composer — الأساس
مدير الحزم اللي Magento كله مبني عليه.
الـ Composer هو مدير الحزم (dependency manager) بتاع PHP. بيدير المكتبات اللي مشروعك محتاجها، بيحمّلها، وبيظبّط الـ autoloading.
الملف اللي بيعرّف مشروعك: اسمه، اعتمادياته، وإعدادات الـ autoload. Magento نفسه والـ modules بتاعتك كلها بتتعرّف هنا.
{
"name": "vendor/module-custom",
"require": {
"php": "~8.1.0",
"magento/framework": "*"
},
"autoload": {
"psr-4": {
"Vendor\\Module\\": ""
}
}
}
- composer install — يحمّل الاعتماديات حسب الـ lock file.
- composer require vendor/pkg — يضيف حزمة جديدة.
- composer dump-autoload — يعيد بناء خريطة الـ autoload.
- composer update — يحدّث الاعتماديات (بحذر في production).
Autoloading & PSR-4
السحر اللي بيخلّي الكلاسات تتحمّل تلقائيًا — قلب Magento.
من غير autoloading، كنت هتكتب require 'path/to/file.php' لكل كلاس تستخدمه. مع آلاف الكلاسات في Magento، ده مستحيل.
الـ PSR-4 معيار بيربط الـ namespace بمسار الملف. لما تستخدم كلاس، الـ autoloader بيترجم الـ namespace لمسار وبيحمّل الملف تلقائيًا.
# PSR-4 mapping: # "Vendor\Module\" => "app/code/Vendor/Module/" # so this class... Vendor\Module\Model\Product # ...auto-loads from this file: app/code/Vendor/Module/Model/Product.php
PHP & Composer ✓
دلوقتي عندك الأساس اللي محتاجه قبل Magento: type declarations، constructor promotion، الـ namespaces، والـ Composer/PSR-4. دي مش كل PHP — بس دي اللي هتشوفها وتستخدمها في Magento يوميًا.
الخلاصة اللي تربط كله: الـ namespace بيطابق مسار الملف، والـ PSR-4 بيحمّله تلقائيًا، والـ Composer بيدير كل ده. بمجرد ما تفهم الربط ده، بنية Magento كلها هتبقى منطقية.
خلّصت الدرس؟علّمه عشان تتابع تقدّمك في الكورس.
أسئلة شائعة
يعني إيه Constructor Promotion في PHP 8؟
قبل PHP 8 كنت بتكتب الـ dependency 3 مرات: property، وparameter، وتعيين جوّه الـ constructor. مع الـ promotion بتكتبها مرة واحدة زي private readonly ProductRepository $repo جوّه أقواس الـ constructor، وPHP بيعمل الـ property والتعيين لوحده. ده مهم جدًا عشان تقرا كود الـ DI في Magento.
إيه فايدة readonly في PHP 8.1؟
الـ readonly معناها إن قيمة الـ property بتتحدد مرة واحدة في الـ constructor وبعدها متتغيّرش. ده بيخلّيها مثالية للـ dependencies اللي بتتحقن ومالهاش تتبدّل طول عمر الـ object.
ما الفرق بين composer install و composer update؟
composer install بيحمّل الاعتماديات بالإصدارات الدقيقة المتثبّتة في composer.lock، فكل بيئة بتركّب نفس النسخ بالظبط. composer update بيحدّث الاعتماديات لإصدارات أحدث، فاستخدمه بحذر في production، ومتعدّلش الـ lock file يدوي.
إزاي PSR-4 autoloading بيشتغل في PHP؟
الـ PSR-4 معيار بيربط الـ namespace بمسار الملف، فلما تستخدم كلاس الـ autoloader بيترجم اسمه لمسار ويحمّل الملف تلقائيًا بدل ما تكتب require لكل كلاس. مثلًا مع mapping Vendor\Module\ على app/code/Vendor/Module/، الكلاس Vendor\Module\Model\Product بيتحمّل من app/code/Vendor/Module/Model/Product.php.
ليه بيظهر class not found في Magento 2؟
أغلب الحالات سببها إن الـ namespace مش مطابق لمسار الملف بدقة، أو إن الكلاس متحطوط في مكان غلط، فالـ autoloader مش بيلاقيه. ولو ضفت كلاس جديد ولسه مش ظاهر، جرّب composer dump-autoload عشان تعيد بناء خريطة الـ autoload.
إيه أهم مميزات PHP 8 اللي بتظهر في كود Magento؟
أهمهم الـ type declarations (ومعاها nullable زي ?string وunion types زي int|string) والـ constructor promotion مع readonly. وهتقابل كمان الـ nullsafe operator ?-> اللي بيتجنّب error لو الـ object null، والـ match اللي بيرجع قيمة وبيقارن strict، والـ enums من PHP 8.1.