منذ ولادته سنة 2003، لم يتوقف ووردبريس عن النمو وكسب المهتمين والمعجبين مما جعله يصل إلى المرتبة الأولى كأحسن نظام لإدارة المحتوى في العالم، حسب رأيي أرى أنّ هذا التألق يعود بالأساس إلى سلاسته، بساطته، سهولته في الاستعمال وخصوصًا للمجتمع الذي يحيط به، والذي يوفر الدعم والشروحات، إنشاء القوالب والإضافات انطلاقا بالوظائف السلسة التي يوفرها لنا هذا النظام الرائع!
فمن أهم الوظائف المستعملة من خلال المطورين هي أنواع المقالات (post types) نعم إنّها الوظيفة الرائعة التي ستكون موضوعنا لهذا اليوم.
ما هي أنواع المقالات؟
أنواع المقالات هي عناصر يوفرها لنا ووردبريس لكي نتمكن من تصنيف وادارة محتوى موقعنا بسهولة، فهنالك أنواع مقالات تأتي افتراضيًا في ووردبريس هي:
- المقالات (post): هو النوع الافتراضي لنشر المقالات في الموقع.
- الصفحات (page): هو النوع الافتراضي لنشر الصفحات في الموقع.
- المرفقات (attachment): من خلال هذا النوع يمكن إدراج الصور ووصلات الفيديو بالإضافة إلى الملفات العامة ووسائط الصوت الخ…، وتسمى بالوسائط في لوحة تحكم ووردبريس.
- المراجعات (revision): يختص هذا النوع بحفظ نسخ قديمة للمواضيع سوءًا أكانت تلقائية أو على هيئة مسوّدة.
- القوائم (nav_menu_item): هي القوائم التي يمكننا إنشاؤها ليستطيع المستخدم التصفح بسلاسة والوصول إلى المحتوى بشكل سريع ويعتبر هذا النوع مُصنّف ضمن المقالات.
لكن هل تعلم أنّه يمكنك إنشاء أنواع مقالات أخرى ومخصصة لتتوافق مع احتياجاتك؟ نعم، فووردبريس يوفر لنا هذه الخاصية منذ النسخة 2.9 عبر وظيفة register_post_type(). كيف ذلك؟ هذا ما سنتطرق إليه بالتفصيل في هذه المقالة.
عندما تُنهي قراءة هذه المقالة بتركيز فإنّك ستتعلم شيئين مهمين جدًا وهما:
- أنواع المقالات المخصصة (custom post types).
- أنواع التصنيفات المخصصة (custom taxonomies).
إنشاء أنواع مقالات مخصصة
أولاً وقبل البدء في الشرح أريد أن أشير إلى شيء مهم جدًا، وهو أنك إذا كنت تعمل على قالب خاص فمن الطبيعي إضافة الأكواد إلى ملف الوظائف functions.php
أو إنشاء ملف آخر وتكوين عملية الاتصال بواسطة الوظيفة require_once أو include_once، ولكن إذا كنت تعمل على قالب تعمل على تطويره جهة أخرى ويتمّ تحديثه باستمرار، فالأفضل هو إنشاء إضافة مخصصة ( Plugin ) وإضافة الأكواد إليها.
جاهز؟ – فلنبدأ!
function sb_register_post_type() {
$args = array();
register_post_type( 'products', $args );
}
add_action( 'init', 'sb_register_post_type' );
ما الذي فعلناه هنا؟ إنّنا قمنا بإنشاء وظيفة جديدة بمسمى sb_register_post_type
، وفي داخلها انشانا المُتغير $args
ووضعنا قيمته مصفوفة فارغة، بعدها قمنا بتسجيل نوع مقالات مخصص جديد عبر الوظيفة register_post_type أسميناه product واعطيناه الإعداد $args
، ثم قمنا بإضافة الوظيفة sb_register_post_type
إلى الخطاف init
بواسطة وظيفة الحدث add_action
.
هذا أبسيط مثال لإضافة نوع مقال مخصص، ولن يظهر حتى في لوحة تحكم المدير، لماذا؟ لأن المتغير $args
عبارة عن مصفوفة في الأصل فارغة.
لكي نقوم بضبط نوع المقالات المخصص الجديد حسب رغبتنا يجب علينا ان نضيف بعض الإعدادات إلى المتغير $args
، وهذه هي الإعدادات الأكثر استعمالا وهي قابلة للتغير.
/*
******************************************
My super Custom Post Type
******************************************
*/
function sb_register_post_type() {
$labels = array(
'name' => _x( 'Products', 'post type general name', 'text-domain' ),
'singular_name' => _x( 'Product', 'post type singular name', 'text-domain' ),
'parent_item_colon' => __( 'Parent Product:', 'text-domain' ),
'menu_name' => __( 'Products', 'text-domain' ),
'add_new' => __( 'Add New', 'text-domain' ),
'add_new_item' => __( 'Add New Product', 'text-domain' ),
'edit_item' => __( 'Edit Product', 'text-domain' ),
'new_item' => __( 'New Product', 'text-domain' ),
'all_items' => __( 'All Products', 'text-domain' ),
'view_item' => __( 'View Product', 'text-domain' ),
'search_items' => __( 'Search Products', 'text-domain' ),
'not_found' => __( 'No products found', 'text-domain' ),
'not_found_in_trash' => __( 'No products found in the Trash', 'text-domain' ),
);
$args = array(
'label' => __( 'products', 'text-domain' ),
'labels' => $labels,
'description' => __( 'Description of my super products', 'text-domain' ),
'public' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-cart',
'supports' => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'revisions', 'custom-fields', 'post-formats' ),
'has_archive' => true,
);
register_post_type( 'products', $args );
}
add_action( 'init', 'sb_register_post_type' );
ما الذي أضفناه وماذا سيحدث؟ لا تقلق سأشرح لك ذلك، فما فعلناه هنا هو نفس الشيء الذي فعلناه في المثال السابق، والفرق هو أنّ في هذه المرة المتغير $args
أصبح مصفوفة مليئة بالإعدادات اللازمة، في الأول قمنا بإنشاء المتغير $labels
وقمنا بتخزين تسميات عناصر نوع المقالات المخصص فيه بوسطة المصفوفة، وهذا فقط لتبسيط الكود وتسهيل قراءته، وبعدها قمنا بإنشاء المتغير $args
الذي سيشمل كل الإعدادات.
- labels: هذا العنصر قمنا بإعطائه كقيمة المتغير
$labels
الذي هو بالتالي عبارة عن مصفوفة. - description: هنا يتم وضع وصف لنوع المقال المخصص.
- public: هذا الخيار يشمل عدد كبير من الإعدادات وكلها تتعلق بالرؤية أو الظهور.
- menu_position: هنا يتم تحديد المرتبة التي سيظهر بها في لوحة التحكم، فكلما كان الرقم أكبر كلما كانت المرتبة أقل.
- menu_icon: هنا نقوم بوضع أيقونة مخصصة باستعمال أحد أيقونات Dashicons وهي الأيقونات الخطية المعتمدة رسميًا في لوحة تحكم ووردبريس.
- supports: هنا يتم تحديث الوظائف الافتراضية الموجود في ووردبريس، والتي نريد أن يدعمها هذا النوع من المقالات ففي الكود الذي وضعنها أمرناه بدعم العنوان، محرر المقالات، المقتطف، تحديد الكاتب، التعليقات، المراجعات، بنية المقالة، والحقول المخصصة.
- has_archive: هنا إذا قمنا بجعل القيمة true فإنّه سيتم إنشاء تركيبة جديدة والتي يمكن من خلالها الحصول على أرشيف للمقالات المخصصة، هكذا مثلاsaidelbakkali.com/products.
هل بدر لذهنك تساؤلاً يتضمن تكرار كلمة text-domain بعد أسماء العناصر؟ ببساطة إنّ تلك الكلمة هي التي تمثل نص النطاق الذي يستعمل في ترجمة النصوص إلى لغات مختلفة حيث أنّه يمكنك تغيير الكلمة حسب رغبتك، وكذلك يمكنك حذفها وكتابة النصوص باللغة التي ستستعملها مباشرةً، على سبيل المثال: إذا أردت أن تستعمل اللغة العربية مباشرةً وأن تكون غير قابلة للترجمة المخصصة فإنّ الكود سيصبح بهذا الشكل:
/*
******************************************
My super Custom Post Type
******************************************
*/
function sb_register_post_type() {
$labels = array(
'name' => 'النتوجات',
'singular_name' => 'نتوج',
'parent_item_colon' => 'النتوج الأب:',
'menu_name' => 'النتوجات',
'add_new' => 'إضافة جديد',
'add_new_item' => 'إضافةنتوج جديد',
'edit_item' => 'تحرير النتوج',
'new_item' => 'نتوج جديد',
'all_items' => 'جيع النتوجات',
'view_item' => 'شاهدة النتوج',
'search_items' => 'البحث عننتوج',
'not_found' => 'لا توجدنتوجات',
'not_found_in_trash' => 'لا توجدنتوجات في سلة المهملات',
);
$args = array(
'label' => 'نتوجات',
'labels' => $labels,
'description' => 'وصف النتوجات',
'public' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-cart',
'supports' => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'revisions', 'custom-fields', 'post-formats' ),
'has_archive' => true,
);
register_post_type( 'products', $args );
}
add_action( 'init', 'sb_register_post_type' );
بعد حفظ التغييرات التي وضعتها في ملف functions.php
أو الإضافة التي قمت بإنشائها من أجل ذلك، فإنّه سيظهر لك عنصر جديد ضمن قائمة لوحة التحكم للوردبريس بالاسم الذي خصصته لنوع مقالاتك.
الآن، وبعد حصولنا على ما أردناه، لدينا تساؤلاً في كيفية عرض هذا النوع الجديد من التدوينات في الموقع؟ إنّ أفضل طريقة لعمل ذلك هي إنشاء قالب صفحة مخصص ثم نسخ محتوى ملف index.php
داخله، وبعدها تغيير حلقة التحميل ( Loop ) بشيءُّ مخصص على سبيل المثال:
// WP_Query arguments.
$args = array(
'post_type' => array( 'products' ),
'post_status' => array( 'publish' ),
'nopaging' => false,
'posts_per_page' => '10',
'order' => 'DESC',
'orderby' => 'date',
);
// The Query.
$query = new WP_Query( $args );
إنشاء أنواع التصنيفات المخصصة
ووردبريس افتراضيا يوفرُ لنا ترتيبًا لمقالاتنا على نوعين: تصنيفات، ووسوم، والفرق بين التصنيفات والوسوم – هو أنّ التصنيفات تدعم التسلسل الهرمي ويُعنى بذلك أنّه يمكنك إنشاء تصنيف فرعي لتصنيف آخر وهكذا … بينما الوسوم لا تدعم هذه الخاصية.
يمكننا استعمال التصنيفات الافتراضية لوردبريس في أنواع المقالات المخصصة وذلك بإضافة الإعداد taxonomies إلى المصفوفة $args
هكذا:
'taxonomies' =>array( 'category', 'post_tag' );
لكن ألا تظن أنّه من الأفضل إنشاء أنواع تصنيفات مخصصة لكل نوع مقالات مخصص؟ أنا أعتقد أنّ هذه هي الطريقة الأحسن؛ لأنّنا عن طريقها يمكننا إنشاء تصنيفات تتواقع مع متطلباتنا واحتياجاتنا.
function sb_register_custom_category() {
$args = array();
register_taxonomy( 'product_category', 'products', $args );
}
add_action( 'init', 'sb_register_custom_category', 0 );
العملية تُعتبر مشابهة لأنواع المقالات المخصصة ففي الأول قمنا بإنشاء وظيفة أسميناها sb_register_custom_category ووضعنا داخلها المتغير $args
ثم قمنا بتسجيل نوع التصنيفات المخصص عبر الوظيفة register_taxonomy()
والتي بدورها تأخذ ثلاث إعدادات:
- product_category: هو اسم أو المعرف الذي أعطيناه لنوع التصنيفات المخصص.
- product: هو اسم أو معرف نوع المقالات المخصص الذي سينتمي له نوع التصنيفات المخصص.
- $args: هو المتغير الذي خزنًا فيه كل إعدادات نوع التصنيفات المخصص.
بعدها قمنا بإضافة الوظيفة sb_register_custom_taxonomy
إلى الخطاف init بواسطة وظيفة الحدث add_action
.
الكود النهائي سيكون هكذا:
/*
******************************************
My super Custom Taxonomy
******************************************
*/
function sb_register_custom_taxonomy() {
$labels = array(
'name' => _x( 'Product Categories', 'Taxonomy General Name', 'saidweb' ),
'singular_name' => _x( 'Product Category', 'Taxonomy Singular Name', 'saidweb' ),
'menu_name' => __( 'Product Categories', 'saidweb' ),
'all_items' => __( 'All categories', 'saidweb' ),
'parent_item' => __( 'Parent category', 'saidweb' ),
'parent_item_colon' => __( 'Parent category:', 'saidweb' ),
'new_item_name' => __( 'New Product Category Name', 'saidweb' ),
'add_new_item' => __( 'Add New Product Category', 'saidweb' ),
'edit_item' => __( 'Edit Product Category', 'saidweb' ),
'update_item' => __( 'Update category', 'saidweb' ),
'separate_items_with_commas' => __( 'Separate Product Category with commas', 'saidweb' ),
'search_items' => __( 'Search Product Categories', 'saidweb' ),
'add_or_remove_items' => __( 'Add or remove Product Category', 'saidweb' ),
'choose_from_most_used' => __( 'Choose from the most used Product Category', 'saidweb' ),
'not_found' => __( 'Not Found', 'saidweb' ),
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
);
register_taxonomy( 'product_category', array( 'products' ), $args );
}
// Hook into the 'init' action
add_action( 'init', 'sb_register_custom_taxonomy', 0 );
أظن أنّ الكود السابق أصبح سهلاً ومفهومًا؛ وذلك لأنّنا شاهدنا مثله فيمن قبل ضمن مثال أنواع المقالات المخصصة، وللمعلومية اعداد labels يأخذ قيمة المصفوفة الأولى التي تشمل تسميات التصنيف، و hierarchical إذا قمنا بجعلها true فستدعم التسلسل الهرمي مثل التصنيفات الافتراضية – أمّا إذا جعلناها false فستكون مثل الوسوم أي لا تدعم التسلسل الهرمي.
هل تتذكر ما قلنا سابقًا حول ترجمة العبارات ؟، إذا كنت تتذكر ذلك حقًا، فإنّ النتيجة النهائية ستصبح هكذا:
حلول أخرى لإنشاء أنواع المقالات المخصصة
طبعا، إذا لم تكن من محبي كتابة الأكواد، فلا عليك هناك من فكر فيك من قبل وأنشأ لك أدوات تسهل عليك العمل.
إضافة Custom Post Type UI: هذه الإضافة توفر لك وسيلة سهلة الاستعمال لإنشاء وإدارة أنواع المقالات والتصنيفات المخصصة.
إضافة Types: هذه الإضافة هي عبارة عن ثلاثة في واحد، هي من أفضل الإضافات التي جربتها حتى الآن، توفر لك فرصة إنشاء أنواع مقالات مخصصة، تصنيفات مخصصة وحقول مخصصة. أنصحك بتجربتها.
موقع WP Hasty: هذا الموقع يمنحك مجموعة من التطبيقات لتوليد أكواد تعمل على ووردبريس, لن أقوم بذكر كل ما يمكنك القام به فيه لأنها أشياء كثيرة، أدخل وشاهد بنفسك لن تخسر شيء.
هنا نكون قد وصلنا إلى نهاية موضوع اليوم، صراحة كنت أريد التكلم أيضا عن العلب المخصصة (Meta Box) لكن هذا سيجعل المقالة طويلة جدا، في النهاية قررت تركه إلى تدوينة أخرى إن شاء الله.
أتمنى أن تكون قد استفدت من الموضع وان أكون قد أوفيت بما يعد به العنوان.
آه!! لا تنسى المشاركة لكي يستفيد شخص آخر مثلك.