الملف يستخدم دوال WordPress الأساسية داخل حلقة The Loop ويحتوي بعض نقاط الضعف (عدم فحص الأخطاء، عدم الهروب/التعقيم، روابط فارغة، طباعة مباشرة بدون تحقّق). سأشرح كل دالة أولاً ثم أعرض قالبًا مُحسَّنًا.
شرح الدوال والعبارات الموجودة في الكود
سأعرض: توقيع الدالة (Parameters)، ما ترجع، شرح سلوكي، بدائل/نصائح، وأفضل ممارسات/ملاحظات.
global $post;
- نوع: عبارة PHP (ليس دالة)
- وظيفته: يتيح الوصول للكائن
$postالعام (وهوWP_Post) داخل نطاق دالة/قالب. - ملاحظات/أفضل ممارسات:
- داخل حلقة WP القياسية (
while ( have_posts() ) { the_post(); ... }) لا تحتاج لذلك عادة لأنthe_post()يعدّل$post. - عند استخدام
WP_Queryمخصص استخدمsetup_postdata( $post )وwp_reset_postdata()أوglobal $postإذا تحتاج الوصول المباشر. - لا تزيل
wp_reset_postdata()بعد استعلام مخصص لتفادي كسر الحلقة الافتراضية.
- داخل حلقة WP القياسية (
get_header( $name = null )
- Parameters:
$name(string|null) — لو وُضعget_header('home')سيحاول تحميلheader-home.phpوإلاheader.php. - ترجع: لا ترجع قيمة؛ تقوم بضم ملف القالب.
- بدائل/ملاحظات:
- بديل مرن:
get_template_part( 'template-parts/header', 'home' )إذا أردت إدارة أجزاء قابلة لإعادة الاستخدام. - أفضل ممارسة: استخدم
get_header()في أعلى ملفات القوالب. لا تخرج HTML قبل استدعاءها إن كان هناك اعتماد على الـheaders.
- بديل مرن:
have_posts()
- Parameters: لا شيء (يستخدم الـWP Loop أو استعلام مخصص).
- ترجع: boolean — هل يوجد منشور متبقي في حلقة الاستعلام الحالي؟
- ملاحظات:
- تُستخدم عادة مع
while ( have_posts() ) : the_post(); endwhile; - عند استخدام
WP_Queryمخصص:while ( $query->have_posts() ) { $query->the_post(); ... }
- تُستخدم عادة مع
the_post()
- Parameters: لا شيء.
- وظيفة: يعدّل الـglobal
$post, يستدعيsetup_postdata( $post )، وتهيئ بيانات القالب (post data). - ملاحظات: لا تستخدم
the_post()خارج حلقة من دون قصد. بعد حلقة مخصصة، نفّذwp_reset_postdata().
get_the_title( $post = 0 )
- Parameters:
$post(ID|WP_Post|0) — افتراضيًا الحالية في الـLoop. - ترجع: string — عنوان المنشور (غير مؤمن).
- مقارنة:
the_title()تطبع العنوان مباشرة،get_the_title()ترجع النص. - أفضل ممارسات: عند الطباعة استخدم
esc_html( get_the_title() )أو تنسيق مناسب للـHTML، أو استخدمthe_title( '<h1>', '</h1>', true )إذا أردت إخراج آمن مع فلترthe_title.
get_the_terms( $post_id, $taxonomy )
- Parameters:
$post_id(int|WP_Post)$taxonomy(string) مثل'category','post_tag', أو تاكسونومي مُعرّفة.
- ترجع: مصفوفة
WP_Termعلى النجاح،falseإن لم توجد، أوWP_Errorفي حالة خطأ. - ملاحظات/أفضل ممارسات:
- يجب فحص النتيجة:
if ( $terms && ! is_wp_error( $terms ) ) { ... } - بدائل:
get_the_category()خاص بالـcategories (يرجع مصفوفة) — أسهل للاستخدام مع التصنيف الافتراضي.wp_get_post_terms( $post_id, $taxonomy, $args )إن أردت تحكماً أكبر (ترتيب، حقول مرجعية…).
- الهروب: عند طباعة اسم التصنيف استخدم
esc_html( $term->name )وعند طباعة الرابط استخدمesc_url( get_term_link( $term ) ).
- يجب فحص النتيجة:
get_term_link( $term, $taxonomy = '' )
- Parameters:
$term(term ID|WP_Term|string slug)$taxonomyاختياري (عند تمرير slug)
- ترجع: URL (string) أو
WP_Error. - ملاحظات: افحص
is_wp_error()قبل الطباعة. استخدمesc_url()عند إخراج الرابط.
get_the_ID()
- Parameters: لا شيء (في الـLoop يرجع ID الحالية).
- ترجع: int — معرف المنشور الحالي.
- ملاحظة: بديل:
get_post()->IDأو$post->IDإذا لديك$post.
get_year_link( $year )
- Parameters:
$year(int|string) مثل2025. - ترجع: رابط أرشيف السنة (URL).
- ملاحظة: عند إخراج الرابط استخدم
esc_url().
get_the_date( $format = '', $post = null )
- Parameters:
$format— تنسيق التاريخ مثل'j M, Y'أو اتركه فارغًا لاستخدام إعدادات WP.$post— ID أو WP_Post (افتراضي: المنشور الحالي).
- ترجع: string (التاريخ منسق).
- نصائح: استخدم تنسيق منطقي للغة. لتدويل النص استخدم
date_i18n()إن لزم.
get_permalink( $post = 0 )
- Parameters:
$post(ID|WP_Post|null) - ترجع: string — رابط ثابت للمنشور/صفحة.
- ملاحظات:
- عند بناء روابط لمشاركة على الشبكات الاجتماعية، تأكد من ترميز/تعقيم الرابط:
esc_url( add_query_arg( 'u', rawurlencode( get_permalink() ), 'https://www.facebook.com/sharer/sharer.php' ) ).
- عند بناء روابط لمشاركة على الشبكات الاجتماعية، تأكد من ترميز/تعقيم الرابط:
get_the_author_meta( $field = '', $user_id = false )
- Parameters:
$field— مثل'display_name','description','ID','user_email'، إلخ.$user_id— اختياري، افتراضيًا مؤلف الـpost الحالي.
- ترجع: string أو قيمة الحقل.
- نصائح أمان: لا تخرج الحقول الحساسة (مثل البريد) علناً بدون مبرر. للروابط إلى صفحة الكاتب استخدم
get_author_posts_url( $user_id ).
the_post_thumbnail( $size = 'post-thumbnail', $attr = '' )
- Parameters:
$size— مثل'thumbnail','medium','large', أو مصفوفة أبعاد أو اسم حجم مخصص.$attr— مصفوفة أو string من سمات<img>(alt, class, loading …).
- وظيفة: تطبع HTML لصورة المرفق المميزة (featured image).
- بدائل:
get_the_post_thumbnail( $post_id, $size, $attr )— يعيد HTML بدلاً من الطباعة. - نصائح: تحقق أولاً
has_post_thumbnail()لتفادي طباعة فراغ. أضفloading="lazy"وaltمناسب، أو استخدمwp_get_attachment_image_srcset()للتحكم بالـsrcset.
the_content( $more_link_text = null, $strip_teaser = false )
- Parameters:
$more_link_text— نص رابط “اقرأ المزيد”.$strip_teaser— boolean.
- وظيفة: يطبع محتوى المنشور بعد تطبيق فلترات
the_content(shortcodes, oEmbeds, autop, wpautop…). - ملاحظات:
the_content()يعالج أمانياً إلى حد ما (يعتمد على فلترthe_contentوwp_kses_post()عند الحاجة). إذا أردت جلب المحتوى كسلسلة استخدمget_the_content()ثمapply_filters('the_content', $content).
get_next_post() و get_previous_post()
- Parameters: لا شيء (تعمل على المنشور الحالي).
- ترجع: كائن
WP_Postأوnull. - بدائل:
get_adjacent_post( $in_same_term, $excluded_terms, $previous )(أكثر مرونة) أو استخدامprevious_post_link()وnext_post_link()(تطبع مباشرة روابط جاهزة). - نصائح:
- افحص القيمة قبل الاستخدام:
if ( $prev = get_previous_post() ) { ... }لأنها قد تُعيدnull. - استخدم
get_permalink( $prev )وget_the_title( $prev )أوesc_html( $prev->post_title ).
- افحص القيمة قبل الاستخدام:
get_footer( $name = null )
- مثل
get_header()لكن لضمfooter.phpأوfooter-$name.php.
ملاحظات أمنية وأفضل ممارسات عامة
- التحقّق من الأخطاء: دوال مثل
get_the_terms()وget_term_link()قد تُعيدWP_Error. افحص دائمًاis_wp_error(). - التعقيم (Escaping):
- الروابط:
esc_url( $url ) - نصوص داخل HTML:
esc_html( $text ) - سمات:
esc_attr( $value ) - إذا كنت تسمح بــHTML محدد:
wp_kses_post()أوwp_kses( $html, $allowed )
- الروابط:
- الفرق بين
get_وthe_:get_ترجع قيمة،the_تطبع — استخدمget_إذا تريد تعقيم/تعديل قبل الطباعة. - الترجمة (i18n): إستخدم
__(),_e(),esc_html__()عند طباعة نصوص ثابتة (مثلاً'Tags:') لتمكين الترجمة. - التحقّقات قبل الطباعة: تحقق أن متغيّر الـpost أو الكائنات موجودة قبل الوصول لخصائصها (
if ( $prev_post ) ...). - استعمال HTML سليم و semantic tags: عناوين
<h1>..</h1>,<nav>للروابط السابقة/التالية، وصفات وصول (aria-*). - الصور: استخدم أحجام مناسبة للصور (
the_post_thumbnail('large'))، استخدمloading="lazy", تحقق من وجود الصورةhas_post_thumbnail().
أخطاء واضحة في الشيفرة الحالية (ومقترحات إصلاح)
- عدم فحص
$categoriesقبل الforeach → قد يؤدي إلى تحذير إذا كانتfalseأوWP_Error.
إصلاح:if ( $categories && ! is_wp_error( $categories ) ) { foreach (...) { ... } } - طباعة
$tag->nameداخل سلسلة محاطة بعلامات اقتباس مفردة (في النسخة المعلّقة) — سيطبع$tag->nameكسلسلة حرفية. يجب فك الــconcatenation أو استخدام double quotes مع المتغير. - روابط الكاتب فارغة (
<a href="">) — لو أردت الربط بصفحة الكاتب استخدمget_author_posts_url( get_the_author_meta('ID') ). - عدم فحص
get_next_post()وget_previous_post()— يمكن أن تكونnull. الكود الحالي يفترض وجودهم. - عدم تعقيم المخرجات — عناوين، روابط، أسماء التصنيفات، إلخ تُطبع مباشرة. يجب استخدام
esc_html,esc_url. - تنسيق التاريخ
get_the_date("d M,Y",get_the_ID())— مسافة بعد الفاصلة مفقودة وget_the_ID()غير ضرورية داخل الـLoop.
نسخة مُحسنة (مُقترح للقالب) — مع التعقيم والفحوصات والـi18n
<?php
global $post;
get_header();
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
?>
<div class="post-bunner">
<div class="container">
<h2 class="post-title"><?php echo esc_html( get_the_title() ); ?></h2>
</div>
</div>
<?php
// Categories
$categories = get_the_terms( get_the_ID(), 'category' );
if ( $categories && ! is_wp_error( $categories ) ) {
echo '<div class="post-categories">';
foreach ( $categories as $category ) {
$term_link = get_term_link( $category );
if ( ! is_wp_error( $term_link ) ) {
printf(
'<span class="badge text-bg-secondary"><a href="%s">%s</a></span> ',
esc_url( $term_link ),
esc_html( $category->name )
);
}
}
echo '</div>';
}
// Date (link to year archive)
$year_link = get_year_link( (int) get_the_date( 'Y' ) );
printf(
'<p><a href="%s">%s</a></p>',
esc_url( $year_link ),
esc_html( get_the_date( 'j M, Y' ) )
);
// Share URL (Facebook)
$share_url = esc_url( add_query_arg( 'u', get_permalink(), 'https://www.facebook.com/sharer/sharer.php' ) );
?>
<p><a href="<?php echo $share_url; ?>"><?php esc_html_e( 'Share on Facebook', 'your-textdomain' ); ?></a></p>
<!-- Tags -->
<div class="tags">
<p><?php esc_html_e( 'Tags:', 'your-textdomain' ); ?></p>
<?php
$tags = get_the_terms( get_the_ID(), 'post_tag' );
if ( $tags && ! is_wp_error( $tags ) ) {
foreach ( $tags as $tag ) {
$tag_link = get_term_link( $tag );
if ( ! is_wp_error( $tag_link ) ) {
printf(
'<span class="badge text-bg-secondary m-1"><a href="%s">%s</a></span>',
esc_url( $tag_link ),
esc_html( $tag->name )
);
}
}
} else {
echo '<span class="no-tags">' . esc_html__( 'No tags', 'your-textdomain' ) . '</span>';
}
?>
</div>
<!-- Author -->
<?php
$author_id = get_the_author_meta( 'ID' );
printf(
'<p>By: <a href="%s">%s</a></p>',
esc_url( get_author_posts_url( $author_id ) ),
esc_html( get_the_author_meta( 'display_name', $author_id ) )
);
// Author bio (optional)
$author_desc = get_the_author_meta( 'description', $author_id );
if ( $author_desc ) {
printf( '<p class="author-desc">%s</p>', esc_html( $author_desc ) );
}
?>
<div class="container">
<?php
if ( has_post_thumbnail() ) {
// use get_the_post_thumbnail if you want to capture or modify the markup
the_post_thumbnail( 'large', array( 'loading' => 'lazy', 'class' => 'img-fluid', 'alt' => esc_attr( get_the_title() ) ) );
}
?>
</div>
<div class="container content">
<div class="post-content">
<?php the_content(); ?>
<hr>
<nav class="post-navigation" aria-label="<?php esc_attr_e( 'Post Navigation', 'your-textdomain' ); ?>">
<?php
$prev_post = get_previous_post();
if ( $prev_post ) {
printf(
'<div class="nav-previous"><a href="%s" rel="prev">%s</a></div>',
esc_url( get_permalink( $prev_post ) ),
esc_html( get_the_title( $prev_post ) )
);
}
$next_post = get_next_post();
if ( $next_post ) {
printf(
'<div class="nav-next"><a href="%s" rel="next">%s</a></div>',
esc_url( get_permalink( $next_post ) ),
esc_html( get_the_title( $next_post ) )
);
}
?>
</nav>
</div>
<aside class="post-sidebar">
<!-- Sidebar: ضع هنا ودجت أو محتوى ديناميكي -->
<?php if ( is_active_sidebar( 'single-post-sidebar' ) ) : ?>
<?php dynamic_sidebar( 'single-post-sidebar' ); ?>
<?php else : ?>
<p><?php esc_html_e( 'Sidebar content here', 'your-textdomain' ); ?></p>
<?php endif; ?>
</aside>
</div>
<?php
} // end while
} // end if have_posts()
get_footer();
PHPتحسينات إضافية وتلميحات عملية
- استخدم
wp_nonceعند تنفيذ أفعال قابلة للتغيير (ليس هنا لأن القالب للعرض فقط). - تقليل عدد الاستدعاءات داخل الحلقة: لا تعيد استدعاء
get_the_ID()مرات كثيرة — خزّنها في متغيّر محلي إذا استُخدمت بكثرة. - استخدم
template parts(مثلget_template_part( 'template-parts/content', 'single' );) لتقسيم القالب وجعله قابل لإعادة الاستخدام والاختبار. - تحسين الأداء: استخدم أحجام صور مُناسبة، CDN للصور، وخادم تخزين مؤقت (caching).
- SEO & Accessibility: ضع
rel="prev"/rel="next"للروابط، استخدم عناوين منطقية، أضف وصف بديل (alt) للصور مفيد وسليم. - التحقق من الترميزات: عند بناء روابط الشبكات الاجتماعية، كن واعيًا للـURL encoding — استخدم
rawurlencode()أوadd_query_arg().
خاتمة قصيرة
قدمت شرحًا مفصلاً لكل دالة وردت في ملفك، مع برامترات، نواتج، بدائل، ونصائح أمان وأداء، ثم قدّمت قالبًا محسّنًا قابل للنسخ واللصق. إن أردت، أستطيع الآن:
- تحويل القالب إلى جزءين (
template-parts) أو - إضافة دعم breadcrumb أو structured data (JSON-LD) للـSEO، أو
- مراجعة قالبك بالكامل وتطبيق تحسينات CSS/JS (مثلاً Bootstrap-friendly) — أخبرني أي خيار تريده وسأنفذه مباشرة.
📝 معلومات البوست (Post Info)
the_ID()
→ تطبع معرف البوست مباشرة (بديل لـget_the_ID()التي ترجع القيمة).post_class( $class = '', $post_id = null )
→ تطبع CSS classes ديناميكية للبوست (مثلpost,type-post,category-news).
→ مفيدة جدًا لتخصيص الاستايل حسب نوع البوست أو التصنيف.the_excerpt()/get_the_excerpt()
→ ملخص البوست (excerpt) بدلًا من المحتوى الكامل.
→ مفيد في أماكن مثل المقالات ذات الصلة أو previews.edit_post_link( $text, $before, $after )
→ تطبع رابط “تعديل” للبوست يظهر فقط للمستخدمين المسموح لهم.get_post_meta( $post_id, $key, $single )
→ تجلب الحقل المخصص (custom field). ممتاز إذا عندك بيانات إضافية للبوست.
👤 معلومات الكاتب
the_author()/get_the_author()
→ بديل أسرع لـget_the_author_meta('display_name').get_author_posts_url( $author_id )
→ رابط صفحة الكاتب (تستخدم معthe_author()لعمل رابط صحيح).the_author_posts_link()
→ تطبع اسم الكاتب كرابط إلى صفحة أرشيف مقالاته مباشرة.
🏷️ التصنيفات والتاجات
the_category( $separator )
→ تطبع روابط التصنيفات التي ينتمي لها البوست.
→ أبسط منget_the_terms().the_tags( $before, $sep, $after )
→ تطبع التاجات كرابط أو نص.
🖼️ الصور والمرفقات
has_post_thumbnail()
→ فحص قبل طباعة الصورة البارزة.wp_get_attachment_image( $attachment_id, $size, $icon, $attr )
→ تعرض صورة من مكتبة الوسائط (غير الصورة البارزة).get_children( $args )
→ للحصول على مرفقات البوست (صور/ملفات). مفيد لعرض جاليري.
🔗 روابط الملاحة
previous_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy )next_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy )
→ تطبع روابط التنقل للبوست السابق/التالي (أسهل منget_previous_post()+ بناء الرابط يدويًا).posts_nav_link()وpaginate_links()
→ للتنقل بين الصفحات (مفيد أكثر في الأرشيفات).
💬 التعليقات
comments_template( $file, $separate_comments )
→ استدعاء قالب التعليقات (عادةًcomments.php).get_comments_number()
→ عدد التعليقات.comments_popup_link()
→ تطبع رابط للتعليقات (مثل “3 Comments” أو “No Comments”).
📌 أخرى مفيدة
get_post_type()/get_post_type_object()
→ معرفة نوع البوست (post, page, custom post).the_time( $format )/get_the_time()
→ وقت نشر البوست (ساعة/دقيقة).the_modified_date()/the_modified_time()
→ تاريخ/وقت آخر تعديل للبوست.get_adjacent_post()
→ دالة أعمّ منget_previous_post()/get_next_post()وتسمح بتحديد taxonomy معين.get_search_form()
→ تضمين نموذج البحث داخل القالب.dynamic_sidebar()
→ لعرض Widgets في مكان جانبي مخصص (بدل كتابة نص ثابت في الـsidebar).
✨ أفضل الممارسات
- عند عرض نصوص: استخدم
esc_html(). - عند عرض روابط: استخدم
esc_url(). - استخدم Template Tags الجاهزة (
the_tags(),the_category(),the_author_posts_link()) بدل كتابة دوال منخفضة المستوى (get_the_terms(), إلخ) إذا لم تكن بحاجة للتحكم الكامل. - اربط الأكواد المتكررة في Template Parts: مثل
get_template_part( 'template-parts/content', 'single' );لسهولة إعادة الاستخدام.
✨ القاعدة العامة لا ستخدام Echo مع الدوال
- دوال تبدأ بـ
the_
→ هذه الدوال تطبع (echo) القيمة مباشرة في مكانها.
✔️ لا تحتاج أن تكتب قبلهاecho.
❌ لو كتبتecho the_title();مثلًا، ستطبع العنوان مرتين (مرة من داخلthe_title()ومرة لأنك طلبت منechoطباعة القيمة المرجعة، وهي غالبًاnull). - دوال تبدأ بـ
get_
→ هذه الدوال ترجع (return) القيمة كسلسلة/مصفوفة بدون أن تطبعها.
✔️ تحتاج تستخدم معهاechoإذا أردت إظهار النتيجة على الشاشة.
📝 أمثلة عملية
1. عنوان البوست
the_title(); // تطبع مباشرة
echo get_the_title(); // نفس النتيجة لكن هنا انت اللي طلبت الطباعة
PHP- الأفضلية:
- لو تحتاج بس تعرض العنوان → استخدم
the_title(). - لو تحتاج تعديل العنوان قبل عرضه (مثلاً إضافة كلمة قبلها) → استخدم
get_the_title()ثمecho.
- لو تحتاج بس تعرض العنوان → استخدم
2. الرابط (permalink)
echo get_permalink(); // لازم echo لأنه يرجع نص فقط
// the_permalink(); // تطبع مباشرة (بدون echo)
PHP3. الوسوم
the_tags(); // تطبع الوسوم كرابط
$tags = get_the_tags();
if ( $tags ) {
foreach( $tags as $tag ) {
echo esc_html( $tag->name );
}
}
PHP4. الصورة البارزة
the_post_thumbnail(); // تطبع <img>
echo get_the_post_thumbnail( get_the_ID(), 'medium' ); // ترجع <img> كسلسلة
PHP⚡ نصائح سريعة
- عند الطباعة المباشرة: استخدم
the_لأنها أنظف وأبسط. - عند المعالجة/التعقيم/إعادة الاستخدام: استخدم
get_.- مثال:
esc_html( get_the_title() )أفضل من الاعتماد علىthe_title()إذا تريد أمان أكثر.
- مثال:
- إذا كنت تشك: تذكر أن
the_غالبًا “تطبع”، وget_غالبًا “ترجع”.
🎯 خلاصة:
- بدون echo → مع دوال
the_(لأنها تطبع وحدها). - مع echo → مع دوال
get_(لأنها ترجع القيمة فقط).