اتخطّى للمحتوى

المرحلة 01 · الأساسياتدرس 3 من 2116 دقيقة قراءةآخر تحديث:

Lesson 03 / 21

Fundamentalsبالتفصيل.

شرح عميق لكل مفهوم أساسي في Magento 2 backend — مش بس "إيه هو"، لكن كمان "ليه موجود" و"إزاي بيشتغل من جوّه"، مع أمثلة كود عملية. كل مفهوم في كارت تفتحه لوحده.

● In-depth What · Why · How + Code + Analogies

Magento 2 مبني على modules مستقلة بتتكلّم مع بعض بطرق محددة. الـ Dependency Injection بيجيب الـ dependencies للـ class عن طريق الـ constructor وبيتظبط في di.xml، والـ Plugins بتعدّل سلوك public methods، والـ Observers بتتفاعل مع events. بيانات المنتجات بتتخزّن بنظام EAV، والـ Service Contracts بتقدّم interfaces ثابتة بين الـ modules.

01

إيه هو Magento أصلًا؟

قبل التفاصيل، لازم تفهم طبيعة الـ platform اللي بتشتغل عليها.

إيه هو

Magento مش مجرد تطبيق e-commerce جاهز. هو في الحقيقة framework كامل مبني فوق مكوّنات من Symfony وLaminas (Zend)، متخصّص في الـ commerce. اللي بتشوفه كـ"متجر" هو مجموعة modules شغّالة فوق الـ framework ده.

ليه مهم تفهم ده

لأنك كـ backend developer مش بتعدّل "متجر"، أنت بتوسّع framework. كل حاجة قابلة للتخصيص عن طريق نقاط توسعة رسمية (plugins, events, preferences) من غير ما تلمس الـ core. ده اللي بيخلّي الـ upgrades ممكنة.

إزاي بيتقسّم

الكود بيتقسّم لطبقتين: الـ Framework (الأدوات العامة: DI, cache, DB abstraction) والـ Modules (المنطق التجاري: Catalog, Checkout, Customer). أنت بتضيف modules بتاعتك جنبهم.

تشبيه Magento زي نظام تشغيل للمتاجر. النظام (framework) بيوفّر الأساسيات، والبرامج (modules) بتشتغل فوقه. أنت بتكتب "برنامج" جديد يشتغل مع النظام، مش بتعدّل النظام نفسه.
الفرق

Magento Open Source مجاني ومفتوح المصدر. Adobe Commerce (كان اسمه Magento Commerce / Enterprise) نسخة مدفوعة فيها مميزات إضافية زي B2B، Page Builder المتقدم، customer segmentation، وRabbitMQ built-in.

ليه بيسألوا عنه

عشان يعرفوا خبرتك بأي نسخة. المفاهيم الأساسية (DI, plugins, EAV) واحدة في الاتنين، بس بعض المميزات موجودة في Adobe Commerce بس.

i
لو اتسألت "شغّال على أنهي نسخة؟"، اعرف تفرّق: الـ backend architecture واحد، الاختلاف في المميزات الجاهزة زي الـ B2B والـ advanced marketing tools.
• • •
02

فلسفة الـ Modularity

الفكرة اللي بُني عليها Magento كله. لو فهمتها، كل حاجة بعدها بتبقى منطقية.

المبدأ

كل وظيفة في Magento معزولة في module مستقل. الـ Catalog module، الـ Checkout module، الـ Customer module... كلهم قطع منفصلة تقدر تتفعّل أو تتعطّل. حتى وظايفك الجديدة بتبقى module.

ليه التصميم ده

عشان الفصل والاستقلالية: تقدر تعطّل feature مش محتاجها، تستبدل module بآخر، وتوسّع بدون ما تكسر باقي النظام. وكمان بيسمح لفرق مختلفة تشتغل على modules مختلفة في نفس الوقت.

إزاي بتتواصل الـ modules

مش بتنادي بعض مباشرة. بتتواصل عن طريق interfaces (service contracts) وevents. ده بيخلّي كل module معتمد على "عقد" مش على تفاصيل داخلية، فتقدر تغيّر الداخل بدون ما تكسر اللي بيستخدمه.

تشبيه زي قطع الليجو. كل قطعة مستقلة، بس ليها شكل توصيل موحّد (interface). تقدر تشيل قطعة وتحط غيرها طالما بتوصّل بنفس الطريقة.

Magento مبني بشكل صارم على مبادئ SOLID. مش مجرد نظرية — دي بتفسّر ليه الكود متقسّم بالشكل ده.

  • S — Single Responsibility: الـ Model بيمسك الـ data، الـ ResourceModel بيكلّم الـ DB، الـ Block للـ view. كل واحد مسؤولية واحدة.
  • O — Open/Closed: مفتوح للتوسعة (plugins, events)، مقفول للتعديل (متلمسش الـ core).
  • L — Liskov Substitution: أي preference بيستبدل class لازم يحترم نفس الـ interface.
  • I — Interface Segregation: interfaces صغيرة مركّزة زي ProductRepositoryInterface بدل واحد ضخم.
  • D — Dependency Inversion: الكود بيعتمد على interfaces مش على classes، والـ DI بيوصّلهم.
i
لو فهمت الـ D (Dependency Inversion) بالذات، هتفهم ليه الـ Dependency Injection موجود أصلًا — القسم الجاي.
• • •
03

Dependency Injection

أهم مفهوم في الـ backend. خد وقتك فيه — لو فهمته صح، فهمت 60% من Magento.

التعريف

الـ Dependency هي أي object الـ class بتاعك محتاجه عشان يشتغل (زي logger أو repository). الـ Injection معناها إن حد تاني بيجهّزلك الـ objects دي ويسلّمهالك، بدل ما تعملها بنفسك بـ new.

ليه؟ (المشكلة اللي بيحلّها)

لو كتبت new Logger() جوّه الكلاس، بتبقى مربوط بالـ Logger ده تحديدًا للأبد. لو عايز تغيّره، أو تعمله mock في الـ testing، أو module تاني عايز يعدّله — مش هتقدر. الـ DI بيفكّ الارتباط ده: أنت بتقول "أنا محتاج logger" والنظام بيقرر أنهي واحد يديك.

إزاي بتطبّقه

بتطلب الـ dependencies في الـ constructor كـ type-hints على interfaces. Magento بيقرا الـ constructor، يجهّز كل حاجة محتاجها، ويبنيلك الـ object جاهز.

الطريقة الغلط ❌php
class OrderProcessor
{
    public function process()
    {
        // Hard-coded dependency — bad
        $logger = new Logger();
        $logger->info('Processing...');
    }
}
الطريقة الصح ✓php
class OrderProcessor
{
    // Ask for the interface — Magento injects it
    public function __construct(
        private readonly LoggerInterface $logger
    ) {}

    public function process()
    {
        $this->logger->info('Processing...');
    }
}
تشبيه بدل ما تروح تشتري وتطبخ الأكل بنفسك كل مرة (new)، بتطلب من المطعم (الـ DI) اللي بيجهّزلك الأكل ويوصّله. أنت بس بتقول "عايز أكل"، مش شغلك تعرف اتعمل إزاي.
ASKليه type-hint على interface مش class؟
الإجابة: عشان تعتمد على "العقد" مش على "التنفيذ". لو اعتمدت على interface، أي حد يقدر يديك implementation مختلفة (للتخصيص أو الـ testing) طالما بتحترم العقد. ده جوهر الـ Dependency Inversion.
• • •
04

Object Manager & di.xml

الآلة اللي بتشغّل الـ DI من ورا الكواليس، والملف اللي بتتحكم بيه فيها.

إيه هو

الـ Object Manager هو الـ class المسؤول عن إنشاء كل الـ objects في Magento وحقن الـ dependencies بتاعتهم. لما تطلب object في الـ constructor، هو اللي بيبنيه ويجهّزه.

ليه ممنوع تستخدمه مباشرة

ممكن تنادي ObjectManager::getInstance()->create(...) يدوي، بس ده ممنوع في الكود العادي لأنه بيخفي الـ dependencies (محدش يعرف الكلاس محتاج إيه بمجرد ما يبص على الـ constructor)، وبيكسّر الـ testing، وبيتخطّى الـ plugins.

إمتى مسموح

في أماكن محدودة بس: داخل الـ factories، الـ tests، وبعض نقاط الـ bootstrap. غير كده، دايمًا استخدم constructor injection.

!
استخدام الـ Object Manager مباشرة في business code هو أشهر "علامة حمرا" في الـ code review وفي الإنترفيو. لو شفته في كود، ده كود سيء.
وظيفته

الـ di.xml هو الملف اللي بتقول فيه للـ Object Manager "إزاي تبني الحاجات": أنهي class يمثّل أنهي interface، أنهي plugins تشتغل، وأنهي arguments تتحقن.

أهم 3 حاجات فيه

1) preference — يربط interface بـ class. 2) type / plugin — يضيف interceptor. 3) virtualType — يعمل نسخة مخصّصة من class. 4) arguments — يحقن قيم أو objects محددة.

etc/di.xmlxml
<config>
  <!-- 1. interface → class -->
  <preference
    for="Vendor\Module\Api\NotifierInterface"
    type="Vendor\Module\Model\Notifier"/>

  <!-- 2. inject a value into a class -->
  <type name="Vendor\Module\Model\Notifier">
    <arguments>
      <argument name="maxRetries" xsi:type="number">3</argument>
    </arguments>
  </type>
</config>
ASKالـ di.xml بتاع الـ area بيتجاوز الـ global؟
الإجابة: آه. الـ etc/di.xml بيتطبّق على كل الـ areas، لكن الـ etc/adminhtml/di.xml أو etc/frontend/di.xml بيتجاوزه في الـ area بتاعه. ده بيسمح بسلوك مختلف في الـ admin عن الـ frontend.
• • •
05

Factories & Proxies

حلّان ذكيان لمشكلتين في الـ DI: إنشاء نُسخ متعددة، وتأجيل التحميل.

المشكلة

الـ constructor injection بيديك نسخة واحدة مشتركة (singleton). بس أحيانًا محتاج تعمل objects جديدة كتير — زي لما تعمل loop وتنشئ product جديد كل مرة. النسخة المشتركة مش هتنفع هنا.

الحل: Factory

الـ Factory هو class مهمته الوحيدة إنه ينشئ نُسخ جديدة. أنت مش بتكتبه — Magento بيولّده أوتوماتيك في generated/. بس بتحط SomethingFactory في الـ constructor وتنادي ->create().

Using a Factoryphp
public function __construct(
    // This class is auto-generated
    private readonly ProductFactory $productFactory
) {}

public function createProducts()
{
    foreach ($data as $row) {
        // Fresh instance each time
        $product = $this->productFactory->create();
        $product->setData($row);
    }
}
تشبيه الـ constructor injection زي موظف ثابت واحد بيخدمك. الـ Factory زي ماكينة بتطلّعلك نسخة جديدة كل ما تضغط الزرار.
المشكلة

بعض الـ dependencies تقيلة جدًا في الإنشاء. لو حطيتها في الـ constructor، هتتبنى كل مرة حتى لو الكود مش هيستخدمها في الغالب — ده هدر في الأداء.

الحل: Proxy

الـ Proxy هو غلاف خفيف بياخد مكان الـ dependency التقيلة. بيتبنى بسرعة، ومبيبنيش الـ object الحقيقي إلا أول ما تنادي method منه فعلًا (lazy loading).

etc/di.xmlxml
<type name="Vendor\Module\Model\LightService">
  <arguments>
    <!-- inject a Proxy instead of the heavy class -->
    <argument name="heavy" xsi:type="object">
      Vendor\Module\Model\HeavyService\Proxy
    </argument>
  </arguments>
</type>
تشبيه الـ Proxy زي مفتاح النور. مش بتشغّل المحطة الكهربائية كلها لما تدخل الأوضة — بس لما تضغط المفتاح فعلًا. لحد كده، المحطة "متأجّلة".
ASKالفرق بين Factory و Proxy؟
الإجابة: الـ Factory بيحل مشكلة "محتاج نُسخ متعددة جديدة". الـ Proxy بيحل مشكلة "الـ dependency تقيلة ومش دايمًا مستخدمة". مختلفين تمامًا في الغرض.
• • •
06

Plugins (Interceptors)

الطريقة الأساسية لتعديل سلوك Magento بأمان. افهمها بعمق لأنها بتتسأل في كل إنترفيو.

الفكرة

الـ Plugin (أو Interceptor) بيسمحلك تتدخّل قبل، بعد، أو حوالين أي public method في أي class — من غير ما تعدّل الكلاس نفسه.

السحر: إزاي ممكن أصلًا

لما تعرّف plugin، Magento بيولّد class جديد اسمه Interceptor بيورّث من الكلاس الأصلي وبيلفّ الـ methods بتاعته. الـ Object Manager بيديك الـ Interceptor ده بدل الأصلي — فأي نداء بيمرّ على الـ plugins بتاعتك الأول. عشان كده لازم يكون الـ object متبني عن طريق الـ DI.

i
ده بيفسّر ليه الـ plugins مبتشتغلش على objects متعملة بـ new — مفيش Interceptor اتولّد لها. ومبتشتغلش على private/final/static methods لأن الوراثة مبتقدرش تلفّهم.
وظيفته

بيشتغل قبل الـ method الأصلية، وبيقدر يعدّل الـ arguments اللي داخلة ليها. بيرجّع الـ arguments المعدّلة (أو مبيرجّعش حاجة لو مش عايز يغيّرها).

before pluginphp
// Original: setName(string $name)
public function beforeSetName(
    Product $subject,
    string $name
) {
    // Modify the incoming argument
    return [trim($name)];
}
وظيفته

بيشتغل بعد الـ method، وبياخد الـ result اللي رجّعته ويقدر يعدّله. ده الأكثر استخدامًا والأأمن لأنه مبيتدخّلش في تنفيذ الـ method نفسها.

after pluginphp
// Original: getName(): string
public function afterGetName(
    Product $subject,
    $result  // the returned value
) {
    return strtoupper($result);
}
وظيفته

بيلفّ الـ method بالكامل. بياخد $proceed (دالة بتشغّل الأصلية) وأنت بتقرر تناديها إمتى، أو تعدّل قبلها وبعدها، أو متناديهاش خالص.

ليه بحذر

لأنه الأتقل أداءً، ولو نسيت تنادي $proceed() بتكسّر باقي الـ plugins بصمت. استخدمه بس لو محتاج تمنع تنفيذ الأصلية بشرط معيّن.

around pluginphp
public function aroundSave(
    Product $subject,
    callable $proceed,
    ...$args
) {
    if ($this->isBlocked()) {
        return null; // skip original entirely
    }
    return $proceed(...$args); // run original
}
ASKالـ sortOrder في الـ plugins بيعمل إيه؟
الإجابة: بيحدد ترتيب تنفيذ الـ plugins لما يكون فيه أكتر من واحد على نفس الـ method. الأقل بيشتغل الأول في الـ before/around، والعكس في الـ after. مهم لما plugins مختلفة بتعتمد على بعض.
• • •
07

Events & Observers

نظام آخر للتوسعة، بمنطق مختلف عن الـ plugins. اعرف الفرق بعمق.

إيه هو

Magento بيطلق (dispatch) events في لحظات مهمة (order placed, customer saved). أي module يقدر يسجّل observer يسمع الـ event ده ويتفاعل معاه.

ليه موجود بجانب الـ plugins

الـ plugin بيتدخّل في method محددة. الـ event بيعلن عن لحظة حصلت بدون ما يهمه مين بيسمع. ده نمط publish/subscribe — الكود اللي بيطلق الـ event مش عارف ولا مهتم مين هيتفاعل.

إزاي بتوصّله

بتعرّف الـ observer في events.xml، والـ observer class بينفّذ execute() اللي بياخد الـ Observer object وياخد منه البيانات.

etc/events.xmlxml
<event name="sales_order_place_after">
  <observer name="vendor_notify"
    instance="Vendor\Module\Observer\NotifyOnOrder"/>
</event>
تشبيه الـ event زي إعلان في مكبّر صوت: "تم عمل أوردر!". مين عايز يسمع ويتصرّف يتصرّف. المذيع مش عارف مين موجود ولا مهتم. الـ plugin بالعكس زي إنك تعدّل على مكتب موظف معيّن بالتحديد.
  • محتاج تغيّر input/output بتاع method؟ → Plugin
  • محتاج تتفاعل مع حدث (تبعت إيميل، تحدّث مخزون)؟ → Observer
  • محتاج تمنع method من الاشتغال؟ → around Plugin
  • عايز شغلك يفضل معزول عن تفاصيل الـ method؟ → Observer
i
قاعدة نهائية: لو بتغيّر "إيه اللي بيرجع" استخدم Plugin. لو بتعمل "حاجة إضافية لما يحصل كذا" استخدم Observer.
• • •
08

الـ Data Layer

إزاي Magento بيتعامل مع البيانات — الثلاثي المقدّس: Model, ResourceModel, Collection.

التقسيم

Magento بيفصل التعامل مع البيانات لتلات مسؤوليات منفصلة، تطبيقًا لمبدأ Single Responsibility.

  • Model — بيمثّل entity واحدة (منتج واحد مثلًا). بيمسك البيانات والمنطق التجاري بس مبيلمسش الـ DB.
  • ResourceModel — الطبقة الوحيدة اللي بتكلّم الـ database فعليًا (load, save, delete). بتترجم بين الـ Model والـ SQL.
  • Collection — بتتعامل مع مجموعة entities. بتبني query بـ filters و sorting وبترجّع نتائج كتير.
ليه الفصل ده

عشان لو غيّرت طريقة التخزين (DB مختلفة مثلًا)، بتعدّل الـ ResourceModel بس. الـ Model والمنطق التجاري يفضلوا زي ما هما. الفصل بيحمي المنطق من تفاصيل التخزين.

how they connectphp
// Model delegates DB work to its ResourceModel
class Log extends AbstractModel
{
    protected function _construct()
    {
        // bind model to its resource
        $this->_init(ResourceModel\Log::class);
    }
}
تشبيه الـ Model زي موظف بيعرف معلومات عميل واحد. الـ ResourceModel زي أمين المخزن اللي بس هو اللي بيدخل الأرشيف. الـ Collection زي تقرير بيجمع كل العملاء بشروط معيّنة.
المفهوم

الـ Collection مبتنفّذش الـ query وقت ما تبنيها. بتفضل بتضيف شروط لحد ما تحتاج البيانات فعلًا (أول iteration أو getItems()) — ساعتها بتتنفّذ مرة واحدة.

ليه ده مهم للأداء

عشان تقدر تبني الـ query على مراحل بدون ما تعمل عدة استعلامات، وعشان متعملش query لو مش هتستخدم النتيجة. بس ده كمان فخ: لو عملت count() و loop، ممكن تعمل استعلامين من غير ما تحس.

!
متعملش عمليات تقيلة جوّه loop على collection، ومتجيبش كل الأعمدة بـ ('*') في production. دايمًا addFieldToFilter وsetPageSize.
• • •
09

نظام الـ EAV

أكتر مفهوم بيربك المبتدئين، وأكتر سؤال متكرر. خد وقتك تفهمه بعمق.

الاسم

EAV = Entity – Attribute – Value. بدل جدول واحد عريض فيه عمود لكل خاصية، البيانات بتتوزّع: جدول للـ entities، جدول بيعرّف الـ attributes، وجداول بتخزّن الـ values حسب نوعها (varchar, int, decimal, text, datetime).

المشكلة اللي بيحلّها

المنتج في Magento ممكن يكون ليه مئات الخصائص، والـ admin بيقدر يضيف خصائص جديدة من اللوحة في أي وقت. لو كان جدول عادي، كل خاصية جديدة هتحتاج ALTER TABLE — ده مستحيل عمليًا. الـ EAV بيسمح بخصائص لا نهائية بدون تعديل الـ schema.

الثمن

القراءة بتحتاج JOINs كتير عشان تجمّع بيانات entity واحدة من كل جداول الـ values. ده بيخلّيه أبطأ من الجدول المسطّح — وعشان كده Magento بيعمل flat / indexed tables للـ storefront.

EAV structure (simplified)sql
-- entity
catalog_product_entity      (entity_id, sku)

-- values split by type
..._entity_varchar   (entity_id, attribute_id, value)
..._entity_int       (entity_id, attribute_id, value)
..._entity_decimal   (entity_id, attribute_id, value)

-- attribute definitions
eav_attribute        (attribute_id, attribute_code, ...)
تشبيه الجدول العادي زي استمارة ثابتة بخانات محدّدة. الـ EAV زي دفتر فاضي بتكتب فيه أي خاصية جديدة في أي وقت — مرن جدًا، بس تجميع المعلومة بياخد وقت أطول.
ASKأنهي entities EAV وأنهي flat؟
الإجابة: EAV: Product, Category, Customer, Customer Address (محتاجين مرونة). Flat: Orders, Quotes, Invoices (محتاجين سرعة كتابة عالية وخصائصهم ثابتة). الاختيار دايمًا مقايضة بين المرونة والأداء.
• • •
10

Service Contracts

الطبقة اللي بتخلّي Magento قابل للتطوير والصمود مع الـ upgrades. المفهوم اللي بيميّز الـ senior.

التعريف

الـ Service Contract هو مجموعة interfaces بتعرّف الـ "عقد" العام للتعامل مع entity. بتتكوّن من نوعين: Data interfaces (شكل البيانات: getters/setters) وService interfaces / Repositories (العمليات: save, getById, delete, getList).

المشكلة اللي بتحلّها

لو كل module بيتعامل مع البيانات عن طريق الـ Models مباشرة، أي تغيير داخلي في الـ Model هيكسّر كل اللي بيستخدمه. الـ Service Contract بيوفّر واجهة ثابتة — التفاصيل الداخلية تتغيّر، بس العقد يفضل زي ما هو، فالكود اللي بيعتمد عليه مبيتكسرش مع الـ upgrades.

فايدة إضافية قوية

الـ REST والـ GraphQL APIs بيتبنوا أوتوماتيك فوق الـ service contracts. أول ما تعرّف repository صح، تقدر تعرّضه كـ API بمجرد config. عقد واحد بيخدم الكود الداخلي والـ APIs الخارجية.

Api/LogRepositoryInterface.phpphp
interface LogRepositoryInterface
{
    public function save(LogInterface $log): LogInterface;
    public function getById(int $id): LogInterface;
    public function delete(LogInterface $log): bool;
    public function getList(
        SearchCriteriaInterface $criteria
    ): LogSearchResultsInterface;
}
تشبيه الـ Service Contract زي منفذ الكهربا في الحيطة. أنت بتوصّل أي جهاز طالما بيتبع شكل المنفذ. مش مهم اتغيّر إيه ورا الحيطة (الأسلاك) — طالما المنفذ (العقد) ثابت، كل أجهزتك تفضل شغّالة.
ASKليه repository بدل $model->load()؟
الإجابة: load() بقى deprecated للاستخدام العام. الـ repository بيوفّر واجهة ثابتة، typed، testable، مفصولة عن الـ ORM، وقابلة للتعرّض كـ API. تحميل الـ model المباشر بيربطك بالتفاصيل الداخلية اللي ممكن تتغيّر.

الأساسيات بالتفصيل ✓

دلوقتي مش بس عارف "إيه" المفاهيم دي، لكن كمان "ليه" موجودة و"إزاي" بتشتغل من جوّه. ده الفرق بين حد بيحفظ وحد بيفهم — والمُقابِل بيحس بالفرق ده بسهولة.

نصيحة: اقرا كل كارت، وبعدين اقفله وحاول تشرح المفهوم بصوت عالي بكلماتك. لو عرفت، هو راسخ. لو لأ، ارجع للكارت.

// magento 2 backend · detailed fundamentals · 10 concepts

خلّصت الدرس؟علّمه عشان تتابع تقدّمك في الكورس.

كاتب الدرس

Abdulrahman Masoud

عندك سؤال على الدرس أو محتاج مساعدة في مشروع Magento؟ كلّمني.

أسئلة شائعة

ما الفرق بين Plugin و Observer في Magento 2؟

الـ Plugin بيتدخّل في public method محددة (before أو after أو around) عشان يغيّر الـ input أو الـ output أو يمنع التنفيذ. الـ Observer بيسمع event زي sales_order_place_after ويعمل حاجة إضافية، بنمط publish/subscribe. القاعدة: لو بتغيّر "إيه اللي بيرجع" استخدم Plugin، ولو بتعمل "حاجة إضافية لما يحصل كذا" استخدم Observer.

ليه مينفعش أستخدم ObjectManager مباشرة في Magento 2؟

لأن نداء ObjectManager::getInstance() جوّه الكود بيخفي الـ dependencies، فمحدش يعرف الكلاس محتاج إيه من الـ constructor، وبيصعّب الـ testing. ده من أشهر العلامات الحمرا في الـ code review والإنترفيو، والمسموح بيه بس أماكن محدودة زي الـ factories والـ tests وبعض نقاط الـ bootstrap.

ما الفرق بين Factory و Proxy في Magento 2؟

الـ Factory بيحل مشكلة إنك محتاج نُسخ جديدة كتير، لأن الـ constructor injection بيديك نسخة مشتركة، فبتحط ProductFactory في الـ constructor وتنادي create()، وMagento بيولّده أوتوماتيك في generated/. الـ Proxy غلاف خفيف بتحقنه عن طريق di.xml مكان dependency تقيلة، ومبيبنيش الـ object الحقيقي إلا أول ما تنادي method منه (lazy loading).

إيه أنواع الـ plugins في Magento 2؟

فيه 3 أنواع: before بيعدّل الـ arguments قبل الـ method، وafter بيعدّل الـ result وهو الأشيع والأأمن، وaround بيلفّ الـ method كلها عن طريق $proceed. الـ around الأتقل أداءً، ولو نسيت تنادي $proceed() بتكسّر باقي الـ plugins بصمت، فاستخدمه بس لو محتاج تمنع التنفيذ بشرط.

ليه الـ plugin مش شغّال على method معيّنة في Magento 2؟

الـ plugins بتشتغل عن طريق class اسمه Interceptor بيتولّد وبيورّث من الكلاس الأصلي، والـ Object Manager بيديهولك بداله. عشان كده مبتشتغلش على objects متعملة بـ new، ولا على methods من نوع private أو final أو static لأن الوراثة مبتقدرش تلفّهم.

يعني إيه EAV في Magento 2؟

EAV اختصار Entity–Attribute–Value: جدول للـ entities، وجدول eav_attribute بيعرّف الخصائص، وجداول للقيم حسب نوعها (varchar وint وdecimal وغيرهم). ده بيسمح للأدمن يضيف attributes جديدة من غير ALTER TABLE، والثمن إن القراءة محتاجة JOINs كتير. الـ Product والـ Category والـ Customer والـ Customer Address شغّالين EAV، والـ Orders والـ Quotes والـ Invoices جداول flat.

ليه أستخدم repository بدل $model->load() في Magento 2؟

الـ load() بقى deprecated للاستخدام العام وبيربطك بالتفاصيل الداخلية للـ Model. الـ repository جزء من الـ Service Contract وبيديك واجهة ثابتة وtyped وسهلة في الـ testing ومفصولة عن الـ ORM، وتقدر تعرّضها كـ REST API عن طريق config، فكودك مبيتكسرش مع الـ upgrades.