انتقل إلى المحتوى الرئيسي

ما هو Weaver ORM؟

Weaver ORM هو نظام ربط كائنات-علائقي (Object-Relational Mapper) لـ PHP 8.4+ مخصص لتطبيقات Symfony، مبني على مبدأ واحد: كائنات النطاق (domain objects) يجب أن تكون خالية تماماً من أي معرفة بقاعدة البيانات. لا توجد تعليقات توضيحية (annotations) على صفوف الكيانات (entity classes)، ولا توليد للوكلاء (proxy generation)، ولا انعكاس في وقت التشغيل (runtime reflection) — فقط كائنات PHP عادية وصفوف مُعيِّن (mapper classes) صريحة تترجم بينها وبين SQL.

المشكلات التي يحلها Weaver

كائنات وكيل Doctrine

يُغلف Doctrine كل كيان مرتبط في صف وكيل (proxy class) يعترض الوصول إلى الخصائص لاستدعاء استعلام SQL عند أول لمسة. في دورات الطلب/الاستجابة التقليدية، يكون هذا غير ملحوظ، لكنه يُمكّن بصمت أنماط استعلامات N+1 ويُعقّد تصحيح الأخطاء (var_dump($post->getAuthor()) يطبع وكيلاً، وليس User).

في العمال PHP طويلة الأمد (RoadRunner وFrankenPHP وSwoole وSymfony Messenger)، يراكم EntityManager حالة قديمة بين الطلبات ويجب إعادة تعيينه يدوياً عند كل حد طلب — خطأ سهل الوقوع وصعب التشخيص.

الترطيب القائم على الانعكاس

يستخدم Doctrine ReflectionProperty لتعيين الخصائص الخاصة/المحمية مباشرةً على كائنات الكيانات، متجاوزاً منطق النطاق. كل طلب يجب إعادة تحليل خصائص PHP أو استدعاء ذاكرة تخزين مؤقت دافئة؛ يجب أن تكون صفوف الوكيل موجودة على القرص.

خريطة هوية غير محدودة

يحتفظ EntityManager في Doctrine بكل كيان محمّل في الذاكرة طوال مدة الطلب. تحميل مجموعات نتائج كبيرة يتسبب في نمو غير محدود للذاكرة. الحل البديل — $em->clear() — يفصل كل شيء، بما في ذلك الكيانات التي نسيت إعادة استمرارها.

ما الذي يفعله Weaver بشكل مختلف

Weaver مبني على أربعة مبادئ:

  1. كائنات PHP عادية ككيانات. صف User لديك لا يعتمد على ORM مطلقاً. لا توجد خصائص، ولا صف أساسي، ولا واجهة. إنه كائن قيمة (value object) أو كائن نطاق (domain object) خالص يمكن اختباره باستخدام وحدات الاختبار دون تشغيل Symfony.

  2. صفوف مُعيِّن صريحة. صف UserMapper منفصل يصف كيف يُعيَّن User إلى جدول users. أنواع الأعمدة، والعلاقات، والمفاتيح الأولية — كلها في مكان واحد، كلها بـ PHP عادية، قابلة للبحث بالكامل وقابلة للتحليل الثابت.

  3. لا وكلاء، لا تحميل كسول ضمني. تُحمَّل العلاقات دائماً بشكل صريح عبر ->with(['relation']). تعرف دائماً بالضبط أي SQL يُنفَّذ ومتى.

  4. آمن للعمال حسب التصميم. المُعيِّنات عديمة الحالة وتُحمَّل مرة واحدة لكل عملية عامل (worker process). كل طلب HTTP أو وظيفة Messenger تحصل على EntityWorkspace خاص بها (وحدة العمل)، لذا لا توجد حالة قابلة للتغيير مشتركة بين الطلبات.

الميزات الرئيسية المميزة

الميزةDoctrine ORMWeaver ORM
توليد صف الوكيلمطلوبغير مطلوب
الانعكاس في وقت التشغيلنعمأبداً
التحميل الكسولضمني (وكيل)صريح فقط
تعليقات/خصائص الكيانعلى صف الكيانصف مُعيِّن منفصل
إعادة تشغيل العملية العاملة عند الإعادةنعملا
منع N+1JOIN FETCH يدويمُطبَّق بواسطة with()
الذاكرة لكل 10 آلاف صف~48 ميغابايت~11 ميغابايت
وقت الترطيب لكل 10 آلاف صف~420 ملي ثانية~95 ملي ثانية
PHPStan / التحليل الثابتجزئي (وكلاء سحرية)كامل (مُعيِّنات صريحة)

المعايير المرجعية: PHP 8.4، PostgreSQL 16، Ubuntu 22.04، 10,000 صف User مع علاقة Profile. تتفاوت النتائج حسب الأجهزة وتعقيد الاستعلام.

نظرة عامة على البنية

Entity (صف PHP عادي — بدون اقتران ORM)

└── Mapper (اسم الجدول، الأعمدة، العلاقات، hydrate/extract)

└── EntityWorkspace → QueryBuilder → PDO/DBAL

يحل EntityWorkspace محل EntityManager في Doctrine. إنه وحدة عمل محدودة النطاق بالطلب تتتبع الكيانات التي تحتاج إلى إدراج أو تحديث أو حذف عند استدعاء flush(). لأنها محدودة النطاق بالطلب، لا يوجد تسرب لخريطة الهوية (identity map) بين الطلبات.

دعم PyroSQL

يأتي Weaver مع دعم اختياري لـ PyroSQL، محرك SQL تحليلي داخلي عالي الأداء. يمكن استخدام PyroSQL كنسخة للقراءة (read replica) لاستعلامات التجميع والتقارير وعمليات مجموعات البيانات الكبيرة دون المساس بقاعدة البيانات العلائقية الأساسية. انظر قسم PyroSQL للتفاصيل.

المتطلبات

الاعتمادالإصدار الأدنى
PHP8.4
Symfony7.0
doctrine/dbal4.0 (طبقة الاتصال فقط)
MySQL8.0
PostgreSQL14
SQLite3.35

اختياري:

  • symfony/messenger — نشر الأحداث غير المتزامن ونمط صندوق البريد الصادر (outbox pattern)
  • symfony/cache — تخزين مؤقت لنتائج الاستعلام
  • mongodb/mongodb + ext-mongodb — دعم مُعيِّن وثيقة MongoDB

ما لا يعدّ Weaver عليه

Weaver ليس بديلاً مباشراً لـ Doctrine. إذا كنت تعتمد بشكل كبير على DQL أو واجهة برمجة معايير Doctrine أو الهجرات القائمة على الخصائص، فستحتاج إلى إعادة كتابة تلك الطبقة. Weaver مناسب بشكل أفضل لـ مشاريع Symfony 7+ الجديدة أو التطبيقات التي تُهاجَر بعيداً عن Doctrine التي تريد SQL صريحاً ومتوقعاً واستمراراً آمناً للعمال.