Custom Content Type في JetEngine: بديل أسرع من CPT

طبقة بيانات مضغوطة تحل محل برج جداول متناثر، تعبيرًا عن Custom Content Type في JetEngine

عندك موقع دليل أو بورد وظائف، وكل يوم بيدخله مئات الطلبات والتقييمات والحجوزات؟ لو كلها متخزنة كمقالات، يبقى جدول wp_postmeta عندك بيكبر كل ساعة، والموقع بيبطأ من غير ما تعرف السبب. الحل اللي Crocoblock بتقدمه اسمه Custom Content Type، وده اللي هنفكّه النهارده حتة حتة.

المشكلة: كيف يخزّن ووردبريس الحقول المخصصة؟

كل أنواع المحتوى في ووردبريس، الافتراضية منها والمخصصة، تُحفظ في جدولين: wp_posts للبيانات الأساسية (العنوان والتاريخ والحالة)، وwp_postmeta لكل الحقول الإضافية.

النقطة الحرجة أن كل حقل يأخذ صفًا مستقلًا في wp_postmeta. مقالة واحدة بها 20 حقلًا تعني صفًا في wp_posts و20 صفًا في wp_postmeta. أضف 100 عنصر فقط، وستجد 2100 صف يجب على قاعدة البيانات أن تمر عليها.

ومع نمو البيانات يزيد زمن البحث داخل الجداول، فتبطأ الصفحات والفلاتر ولوحة التحكم معًا. هذه ليست مشكلة في المواقع الصغيرة، لكنها تظهر بوضوح في مواقع الأدلة والحجوزات والعضويات.

ما هو نوع المحتوى المستقل (Custom Content Type)؟

نوع المحتوى المستقل (Custom Content Type)، واختصاره CCT، وحدة في إضافة JetEngine موجودة منذ الإصدار 2.5.0. فكرته بسيطة: مجموعة حقول تحددها أنت، ولها جدول خاص بها في قاعدة البيانات.

كل عنصر تضيفه، سواء كان تقييمًا أو طلب توظيف أو حجزًا، يُحفظ كصف واحد يحتوي كل حقوله. بذلك تشغل 100 عنصر 100 صف فقط، مهما كان عدد الحقول، ولا تلمس wp_posts أو wp_postmeta إطلاقًا.

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

بياناتك لا تضيع لو أوقفت JetEngine

لأن البيانات محفوظة في جداول عادية، تبقى موجودة حتى لو عطّلت الإضافة. يكفي استعلام SQL بسيط لقراءتها:

global $wpdb; 
$ccts = $wpdb->get_results( "SELECT * FROM wp_jet_cct_testing WHERE _ID <= 20" ); 

استبدل testing باسم جدولك، وعدّل الشرط _ID <= 20 أو احذفه لجلب الجدول كاملًا.

إنشاء العناصر وتعديلها بالكود

مع تفعيل JetEngine، يوفر كل نوع محتوى مستقل معالج عناصر (item handler) تستخدمه من كود PHP، مثلًا عند ربط الموقع بنظام CRM أو بنموذج مخصص:

$type = Jet_EngineModulesCustom_Content_TypesModule::instance()
    ->manager
    ->get_content_types( 'inquiries' );

$handler = $type->get_item_handler();

$item_id = $handler->update_item( [
    'property_id' => 42,
    'client_name' => 'J. Smith',
    'status'      => 'new',
] );

فكّر في موقعك كطبقات

أفضل طريقة لفهم CCT هي أن تعتبره طبقة البيانات في المشروع. موقع ديناميكي مبني بـ JetEngine يتكون عادة من الطبقات التالية:

الطبقةالأداة في JetEngineأمثلة
النشرنوع المحتوى المخصص (CPT)العقارات، الوظائف، الدورات
———
البياناتنوع المحتوى المستقل (CCT)الطلبات، التقييمات، الحجوزات
الربطالعلاقات (Relations)وكيل ↔ عقار، مستخدم ↔ طلب
العرضListings وQuery Builder وJetSmartFiltersقوائم وفلاتر وجداول
الوصولREST API وMCP Serverتطبيقات خارجية وأدوات ذكاء اصطناعي

السؤال إذن ليس «CPT أم CCT للموقع كله؟» بل: أي الكيانات محتوى يحتاج صفحة ورابطًا، وأيها بيانات تُعرض داخل صفحات أخرى؟

مثال عملي: موقع عقارات مصري

تخيل موقعًا لشركة عقارات في التجمع الخامس أو الشيخ زايد:

  • العقارات: CPT مع تفعيل Custom Meta Storage، لأنها تحتاج صفحات عامة تفهرسها محركات البحث.
  • الوكلاء: CPT، لأن لكل وكيل صفحة تعريفية.
  • المناطق: تصنيف (Taxonomy) للفلترة.
  • طلبات المعاينة: CCT، فهي لا تحتاج صفحات عامة، وقد تصل لآلاف الطلبات شهريًا.
  • ربط الوكلاء بالعقارات: علاقة متعدد لمتعدد مع حقل يحدد «الوكيل الرئيسي» أو «المساعد».

بهذا التقسيم تبقى جداول المقالات صغيرة، وتنمو الطلبات في جدولها المستقل دون أن تبطئ صفحات العقارات.

CCT أم CPT؟ كيف تختار

القاعدة المختصرة: إذا كان العنصر يحتاج صفحة مستقلة ورابطًا وفهرسة وتصنيفات، فهو CPT. وإذا كان سجلًا يُعرض داخل صفحات أخرى ويُضاف غالبًا من نموذج، فهو CCT.

ماذا عن CPT مع Custom Meta Storage؟

يتيح JetEngine نقل حقول أي CPT إلى جدول مخصص عبر مفتاح Custom Meta Storage (تخزين الحقول في جدول مستقل) في الإعدادات العامة لنوع المحتوى. عندها تُحفظ حقول كل مقالة في صف واحد بدلًا من عشرات الصفوف في wp_postmeta.

هذا يقرّب أداء CPT من CCT، لكن يبقى الفرق في مكان باقي البيانات. المقالة مع Custom Meta Storage تظل مقالة عادية: عنوانها ومحتواها ورابطها في wp_posts، وتحتفظ بالأرشيف والتصنيفات والمراجعات. أما عنصر CCT فلا يملك أي صف في wp_posts.

هل يمكن إعطاء CCT صفحة مستقلة؟

لا ينشئ CCT صفحات افتراضيًا، لكن يمكنك تفعيل خيار Has Single Page (إنشاء صفحة مرتبطة)، ثم اختيار CPT مرتبط وربط حقلي العنوان والمحتوى على الأقل.

بعدها تصمم قالبًا لهذا الـ CPT في Elementor Pro أو JetThemeCore، وتظهر حقول CCT كمصدر في الـ Dynamic Field وفي الوسوم الديناميكية. وتحتفظ بميزة الأداء، لأن الحقول ما زالت في صف واحد بجدول CCT.

ولماذا لا توجد تصنيفات لـ CCT؟

لأن التصنيفات تتطلب جداول إضافية، وهذا يناقض فكرة الجدول الواحد. البديل الأفضل هو العلاقات، فهي تربط عناصر CCT بالمقالات والمستخدمين والتصنيفات وعناصر CCT أخرى.

خطوات إنشاء Custom Content Type

  1. افتح JetEngine > JetEngine وفعّل وحدة Custom Content Type.
  2. ستظهر قائمة جديدة داخل قسم JetEngine، اضغط Add New.
  3. أضف الحقول التي تحتاجها، فكل أنواع الحقول المتاحة لـ CPT متاحة هنا.
  4. اختر أيقونة وموضعًا في القائمة الجانبية، وحدد أعمدة لوحة التحكم والفلاتر.
  5. فعّل نقاط REST API إذا كنت ستقرأ البيانات أو تكتبها من تطبيق خارجي.

ميزة إضافية: يمكن لـ JetEngine إنشاء نموذج جاهز مربوط بحقول CCT بضغطة واحدة، مع إعداد إجراء Insert/Update post تلقائيًا. هكذا يملأ زوار الموقع البيانات من الواجهة دون أن تربط الحقول يدويًا.

عرض بيانات CCT في الواجهة

قالب القائمة (Listing)

ينشأ قالب القائمة لـ CCT كما تنشئه للمقالات: اختر Custom Content Type كمصدر للقالب، ثم أضف ويدجت Dynamic Field أو Dynamic Image.

انتبه لنقطة تربك كثيرين: في حقل Source لا تختر Meta Fields، بل اترك الخيار الافتراضي Title/Term/User/Object Data لتظهر لك حقول CCT.

الفلترة والاستعلامات

  • JetSmartFilters: يعمل مع CCT بنفس طريقة عمله مع CPT.
  • Query Builder (منشئ الاستعلامات): أساسي للحالات المعقدة، مثل عرض أعمال موظف واحد فقط داخل صفحته الشخصية. تنشئ الاستعلام، ثم تختاره من تبويب Custom Query في ويدجت Listing Grid.
  • جداول ورسوم بيانية وتقاويم وخرائط: كلها تبدأ باستعلام مصدره CCT، ثم تختار طريقة العرض.

في Elementor: كل ما سبق يعمل داخل Elementor Pro مباشرة، فالـ Listing Grid ويدجت عادية، وقوالب الصفحات المرتبطة تُبنى من Theme Builder.

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

  • الأدلة والأسواق الإلكترونية: الإعلان نفسه CPT، لكن التقييمات والاستفسارات والمفضلة وسجل الأسعار تنمو أسرع بكثير، فضعها في CCT واربطها بالعلاقات.
  • الحجوزات والطلبات: حجوزات العيادات ومراكز التدريب وطلبات الخدمات تُنشأ من المستخدمين بالآلاف ولا تحتاج صفحات. اعرضها في لوحة المستخدم كجداول أو تقويم وصدّرها من لوحة التحكم.
  • ملفات المستخدمين العامة: مع وحدة Profile Builder تربط عناصر CCT بالمستخدم، مثل الخبرات العملية ومعرض الأعمال في موقع توظيف.
  • نظام تعليقات مخصص: ممكن بالكامل عبر CCT ونموذج من JetFormBuilder.
  • REST API: يمكن إضافة عناصر CCT وقراءتها عن بعد، وهو مفيد لو عندك تطبيق موبايل يقرأ البيانات من ووردبريس.

CCT وأدوات الذكاء الاصطناعي

منذ الإصدار 3.8.0 يوفر JetEngine خادم MCP (MCP Server). تفعّله من JetEngine > JetEngine > MCP Server، فتستطيع أدوات مثل VS Code مع GitHub Copilot قراءة إعدادات موقعك من أنواع محتوى وجداول CCT وعلاقات واستعلامات، وإنشاء هياكل جديدة.

وبما أن عناصر CCT متاحة عبر REST API، يمكن لأدوات بناء التطبيقات بالذكاء الاصطناعي مثل Bolt وLovable إنشاء واجهات تعرض البيانات وتفلترها، بينما يعمل ووردبريس كخلفية. هنا تظهر قيمة الجدول ذي البنية الثابتة: الأداة ترى بياناتك كما هي بدل أن تخمّن.

الأسئلة الشائعة

س: ما الفرق بين CCT وCPT في JetEngine؟
ج: الـ CPT مقالة لها رابط وصفحة وتُخزن في wp_posts وwp_postmeta، أما CCT فجدول مستقل يحفظ كل عنصر بكل حقوله في صف واحد، دون صفحة افتراضية.

س: هل يحسّن CCT سرعة موقع ووردبريس فعلًا؟
ج: نعم، خصوصًا في المواقع التي تحتوي آلاف السجلات وحقولًا كثيرة، لأن الاستعلام يقرأ صفًا واحدًا بدل عشرات الصفوف في wp_postmeta.

س: هل تُفهرس عناصر CCT في جوجل؟
ج: ليس كصفحات مستقلة افتراضيًا، لكن محتواها يُفهرس في الصفحات التي تعرضه. إذا احتجت صفحة لكل عنصر ففعّل Has Single Page أو استخدم CPT.

س: ماذا يحدث لبيانات CCT إذا ألغيت تفعيل JetEngine؟
ج: تبقى في جداولها داخل قاعدة البيانات، ويمكنك قراءتها باستعلام SQL عادي عبر $wpdb.

س: هل توجد إضافة أخرى تقدم ميزة مشابهة؟
ج: أقرب بديل هو إضافة Meta Box مع وحدة MB Custom Table.

الخلاصة

الـ CCT مش بديل للـ CPT، هو القطعة الناقصة في بازل مشروعك: المحتوى اللي محتاج صفحات يفضل CPT، والبيانات اللي بتتراكم من الزوار تروح لجدولها الخاص. جرّبه في أول مشروع فيه حجوزات أو طلبات، وهتحس بالفرق في سرعة الفلاتر ولوحة التحكم.

ولو لسه معندكش JetEngine وعايز تجرّب أنواع المحتوى المستقلة على مشروع حقيقي، تقدر تبدأ من هنا احصل على JetEngine.

مرجع المقال (بالإنجليزية): Custom Content Type: CPT’s Alternative for Better WordPress Performance and Data Structure
المقال ده مش ترجمة حرفية: متكيّف للقارئ العربي ومضاف عليه سياق ووردبريس وElementor وJetEngine.

اترك تعليقاً