מדריך ליצירת סוגי תוכן מותאמים (Custom Post Types)

מהם סוגי תוכן מותאמים (Custom Post Types) וכיצד ליצור אותם.

וורדפרס צברה תאוצה בשנים באחרונות והשיגה לעצמה שם ומוניטין בעולם האינטרנט כמערכת ניהול תוכן (CMS) מהמוצלחות שיש. אחת מפריצות הדרך החשובות של וורדפרס כמערכת ניהול תוכן היא האפשרות ליצור (Custom Post Types (CPT או בעברית סוגי תוכן מותאמים אשר הביאו עימם את האפשרות ליצור סוגי תוכן שונים במערכת ולהרחיב את יכולותיה.

במדריך זה נסביר מהם סוגי תוכן מותאמים, כיצד ליצור סוגי תוכן אלו וכיצד להציג אותם באתר הוורדפרס שלכם.

יש שיאמרו כי נכון לומר ״פוסטים מותאמים אישית״, לדעתי נכון לומר ״סוגי תוכן מותאמים״ מכיוון וזוהי מטרתם – ליצור סוגים חדשים של תוכן המותאמים לצרכים שלכם…

קצת היסטוריה

בפועל, סוגי תוכן מותאמים בוורדפרס קיימים לא מעט זמן, בעצם משנת 2005 כשוורדפרס בגירסה 1.5 הציגה את האפשרות לייצר דפים סטטיים והוסיפה את השדה post_type למסד הנתונים.

הפונקציה wp_insert_post הייתה קיימת מגירסה 1.0 של וורדפרס כך שכשנוסף השדה post_type למסד הנתונים, יכולתם פשוט לקבוע את הערך שלו כשהוספתם פוסט. כמובן שיצירה וניהול סוגי תוכן מותאמים בתקופה זו דרשה לכתוב לא מעט קוד, אך עם התפתחות המערכת נדרש פחות ופחות.

בגירסה 2.9 הפונקציה register_post_type יצאה לאוויר העולם והייתה נגישה לכולם. בנקודה זו, כבר לא נדרש הרבה בכדי ליצור סוגי תוכן מותאמים על מנת לקחת את וורדפרס כמה צעדים קדימה ולגרום לה להיות מערכת ניהול תוכן במלוא מובן המילה.

מהם סוגי תוכן מותאמים?

סוג תוכן מותאם הוא בעצם פוסט עם ערך שונה בשדה post_typeבמסד הנתונים. אם תפרסמו פוסט באתר שלכם, תגשו למסד הנתונים ותשנו את סוג התוכן מ ״post״ ל ״page״, הפוסט יופיע תחת עמודים ולא תחת פוסטים בממשק הניהול.

וורדפרס מגדירה מספר תכונות לכל סוג תוכן. האם ניתן לבצע חיפוש באותו סוג תוכן? האם הוא מוצג בממשק הניהול? האם ניתן לשייך אליו קטגוריות או תגיות, האם הוא מאפשר תגובות? אלו סט של הגדרות אותן ניתן לקבוע עבור כל סוג תוכן.

כברירת מחדל, וורדפרס מגיעה עם מספר סוגי תוכן כגון: עמודים, פוסטים, תפריטים, גירסאות (post revisions) ועמודי קובץ (attachments), לכל אחד מאלו ערך שונה בשדה post_type. וורדפרס מאפשרת לכם בצורה מאד פשוטה ליצור סוג תוכן משלכם כגון ספרים, סרטים, ביקורות, מתכונים וכל מה שתעלו על דעתכם.

יצירת סוג תוכן מותאם בוורדפרס

מתי יש להשתמש בסוגי תוכן מותאמים?

ההחלטה האם יש צורך ליצור סוג תוכן מותאם יכולה להיות מעט בעייתית. לפעמים אתם יכולים לחלק את הפוסטים באמצעות קטגוריות ולהסתפק בכך. אך מהו הגבול? מתי עלינו להשתמש באותן קטגוריות מובנות לאותה חלוקה ומתי נכון יהיה ליצור סוג תוכן חדש?

אין לכך תשובה חד משמעית. ניתן לומר שזה מסתכם להעדפה אישית / פרקטית בהתאם לצורה בה התבנית שלכם בנויה. אך ישנם מספר קווים מנחים שניתן לעבוד לפיהם, אם אחת מהסיטואציות הבאות רלוונטיות כלפיכם, כנראה שיצירה של סוג תוכן מותאם תהיה נכונה:

  • אם אתם מפרסמים לפחות שני סוגים שונים של תוכן. לדוגמה, פוסטים בלוג אישי ומתכוני אוכל.
  • אם מבחינת מבנה ומבחינה ויזואלית, יהיה נכון יותר להפריד שני סוגי שונים של תוכן. לדוגמה בלוג אישי ופורטפוליו.
  • אם סוג התוכן אינו מתאים מבחינה כרונולוגית. לדוגמה, בלוג חברה ושירותים אותם החברה מציעה.
  • אם סוג התוכן יכול להיות מופרד בקלות לאתר משל עצמו ועדיין להשאר קוהרנטי. לדוגמה, בלוג אישי ומוצרים אותם אתם מוכרים באתר.
  • אם השימוש בקטגוריות ותגיות יובילו להיררכית טקסונומיות מסובכת יתר על המידה. לדוגמה, בלוג אישי וביקורות על סרטים.
הצטרפו לרשימת התפוצה!

 אז איך יוצרים סוגי תוכן מותאמים?

המצב האידאלי הוא ליצור סוג תוכן מותאם על ידי שימוש בתוסף ייעודי שתבנו לשם כך, אך זוהי רק המלצה, אם אינכם יודעים איך ליצור תוסף, הוסיפו את הקוד הבא לקובץ functions.php:

// Register Custom Post Type
function snippet_post_type() {

	$args = array();
	register_post_type( 'snippet', $args );

}
add_action( 'init', 'snippet_post_type', 0 );

קוד זה ייצור סוג תוכן חדש אשר ללא אפשרויות כלל. הוא לא יהיה ציבורי ואף לא יופיע בלוח הבקרה של וורדפרס. בכדי לתפור את סוג התוכן לצרכים שלנו, נוסיף כמה הגדרות למערך הריק בקוד מעלה ($args):

// Register Custom Post Type
function snippet_post_type() {

	$labels = array(
		'name'                  => _x( 'Snippets', 'Post Type General Name', 'text_domain' ),
		'singular_name'         => _x( 'Snippet', 'Post Type Singular Name', 'text_domain' ),
		'menu_name'             => __( 'Post Types', 'text_domain' ),
		'name_admin_bar'        => __( 'Post Type', 'text_domain' ),
		'archives'              => __( 'Item Archives', 'text_domain' ),
		'attributes'            => __( 'Item Attributes', 'text_domain' ),
		'parent_item_colon'     => __( 'Parent Item:', 'text_domain' ),
		'all_items'             => __( 'All Items', 'text_domain' ),
		'add_new_item'          => __( 'Add New Item', 'text_domain' ),
		'add_new'               => __( 'Add New', 'text_domain' ),
		'new_item'              => __( 'New Item', 'text_domain' ),
		'edit_item'             => __( 'Edit Item', 'text_domain' ),
		'update_item'           => __( 'Update Item', 'text_domain' ),
		'view_item'             => __( 'View Item', 'text_domain' ),
		'view_items'            => __( 'View Items', 'text_domain' ),
		'search_items'          => __( 'Search Item', 'text_domain' ),
		'not_found'             => __( 'Not found', 'text_domain' ),
		'not_found_in_trash'    => __( 'Not found in Trash', 'text_domain' ),
		'featured_image'        => __( 'Featured Image', 'text_domain' ),
		'set_featured_image'    => __( 'Set featured image', 'text_domain' ),
		'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
		'use_featured_image'    => __( 'Use as featured image', 'text_domain' ),
		'insert_into_item'      => __( 'Insert into item', 'text_domain' ),
		'uploaded_to_this_item' => __( 'Uploaded to this item', 'text_domain' ),
		'items_list'            => __( 'Items list', 'text_domain' ),
		'items_list_navigation' => __( 'Items list navigation', 'text_domain' ),
		'filter_items_list'     => __( 'Filter items list', 'text_domain' ),
	);
	$args = array(
		'label'                 => __( 'Snippet', 'text_domain' ),
		'description'           => __( 'Post Type Description', 'text_domain' ),
		'labels'                => $labels,
		'supports'              => array( 'title', 'editor' ),
		'taxonomies'            => array( 'category', 'post_tag' ),
		'hierarchical'          => false,
		'public'                => true,
		'show_ui'               => true,
		'show_in_menu'          => true,
		'menu_position'         => 5,
		'show_in_admin_bar'     => true,
		'show_in_nav_menus'     => true,
		'can_export'            => true,
		'has_archive'           => true,
		'exclude_from_search'   => false,
		'publicly_queryable'    => true,
		'capability_type'       => 'post',
	);
	register_post_type( 'snippet', $args );

}
add_action( 'init', 'snippet_post_type', 0 );

בקוד מעלה הצגנו הרבה מהארגומנטים שניתן לקבוע כאשר יוצרים סוג תוכן מותאם. אין זו חובה להשתמש בכל הארגומנטים.

קוד זה ייצור סוג תוכן חדש הנקרא snippet ויופיע כתפריט סטנדרטי בלוח הבקרה של וורדפרס. תוכלו להוסיף פוסטים, לצפות ולערוך את הפוסטים של סוג תוכן זה בלוח הבקרה וכמובן לראות את הפוסטים שפירסמתם באתר שלכם. כפי שציינתי, ישנם לא מעט פרמטרים שניתן להגדיר כשיוצרים סוג תוכן חדש, אסביר על חלקם כאן. לרשימת האפשרויות והפרמטרים המלאה תנו ב WordPress Codex.

ניתן מבט על חלק מהפרמטרים:

  • labels – פרמטר זה צריך להיות מערך המגדיר את התוויות שיהיו לסוג התוכן בלוח הבקרה של וורדפרס.
  • description – תיאור קצר על סוג התוכן, מה הוא עושה ומדוע אנחנו משתמשים בו.
  • exclude_from_search – יגדיר האם סוג התוכן יופיע בתוצאות החיפוש כשיתבצע חיפוש באתר.
  • menu_position – מיקום התפריט בלוח הבקרה של וורדפרס (ברירת המחדל היא מתחת לתפריט תגובות).
  • supports – מגדיר במה יתמוך סוג התוכן שיצרתם, לדוגמא כותרת, תקציר, תגובות, גירסאות וכו׳…
  • has_archive – מאפשר להציג ארכיון (archive) לסוג תוכן זה.

הצגת סוג התוכן המותאם

ישנם לא מעט ניואנסים להסבר עד כה אך זה אמור לתת לכם את הבסיס ליצירת סוג תוכן מותאם בוורדפרס. מה שנשאר לנו הוא להסביר כיצד להציג את סוג התוכן שיצרתם למשתמש באתר – כרשימה של פוסטים בעמוד הארכיון וכעמוד יחיד המציג את הפוסט עצמו.

הצגת דף הארכיון (רשימת הפוסטים) של סוג התוכן שיצרתם

במידה ויצרתם סוג תוכן מותאם כשהפרמטר has_archive שווה ל true, וורדפרס (במצבה הדיפולטיבי) תציג סוג תוכן זה על ידי שימוש בקובץ archive.php. אם סוג התוכן שיצרנו נקרא snippets, תוכלו לגשת ל http:/mysite.co.il/snippet בכדי לראות את רשימת הפוסטים שיצרתם.

ההיררכיה של טעינת הקבצים בוורדפרס עובדת בצורה הבאה: במידה וקיים קובץ בשם archive-[post_type].php – או במקרה שלנו archive-snippet.php וורדפרס תשתמש בקובץ זה על מנת להציג את ארכיון הפוסטים של סוג התוכן המדובר. במידה וקובץ זה אינו קיים (והוא אינו קיים כברירת מחדל), וורדפרס תשתמש בקובץ archive.phpבכדי להציג את התוכן. וכשזה לא קיים תשתמש בקובץ index.php.

לכן, במידה ואתם רוצים לשנות את מבנה דף הארכיון של סוג התוכן snippet שיצרנו, נכון יהיה ליצור קובץ חדש בתבנית שלכם בשםarchive-snippet.php ולהעתיק אליו את הקוד מ archive.php. כעת תוכלו לשנות את הקובץ החדש שיצרתם בהתאם לדרישות העיצוב כאוות נפשכם.

הצגת דף הפוסט עצמו של סוג התוכן שיצרתם

בדומה לדרך בה עובדת ההיררכיה עבור עמוד הארכיון, כך גם עובדת ההיררכיה עבור דף הפוסט עצמו. כשאני אומר דף הפוסט אני מתכוון לעמוד המציג את סוג התוכן שיצרתם, כלומר – העמוד שיוצג כשתלחצו על כל אחד מהפוסטים בדף הארכיון.

במקרה של דף זה, וורדפרס כברירת מחדל תשתמש בקובץ single.php על מנת להציג את העמוד. אם תרצו לעצב או לשנות את ההתנהגות או המבנה של אותו עמוד, צרו קובץ חדש בשם single-snippet.php בתבנית שלכם, העתיקו אליו את הקוד מ single.php ובצעו את השינויים כרצונכם.

הצגת הפוסטים באמצעות הלולאה של וורדפרס

במקרים רבים, תרצו להציג רשימה של הפוסטים של סוג תוכן מסויים בתבנית עמוד משלכם (page template). כאשר עושים זאת, הדרך הנוחה ביותר להציג את אותה רשימה היא באמצעות WP_Query והלולאה של וורדפרס. לא נרחיב על הלולאה של וורדפרס במאמר זה, אך בכדי להציג את רשימת הפוסטים של סוג תוכן מסויים בתבנית עמוד כלשהו תשתמשו בקוד הבא:

<?php
if ( get_query_var( 'paged' ) ) {
	$paged = get_query_var( 'paged' );
}
if ( get_query_var( 'page' ) ) {
	$paged = get_query_var( 'page' );
}

$query = new WP_Query( array( 'post_type' => 'snippet', 'paged' => $paged ) );

if ( $query->have_posts() ) : ?>
	<?php while ( $query->have_posts() ) : $query->the_post(); ?>
        <div class="entry">
            <h2 class="title"><?php the_title(); ?></h2>
			<?php the_content(); ?>
        </div>
	<?php endwhile;
	wp_reset_postdata(); ?>
    <!-- show pagination here -->
<?php else : ?>
    <!-- show 404 error here -->
<?php endif; ?>

תוכלו לשנות את סוג התוכן שיוצג בשורה מספר 9. כמו כן, המשתנה $paged נחוץ בכדי שהעימוד הממוספר יעבוד כראוי (Pagination).

מילים אחרונות

כפי שאתם רואים, יצירת סוגי תוכן והרחבת האפשרויות לניהול התוכן בוורדפרס הוא תהליך די פשוט עקב האופי המודולרי של המערכת והפונקציות שהיא מספקת. ההבנה מתי נכון להשתמש בסוג תוכן מותאם, מתי להשתמש בטקסונומיות, וחשוב מכל – מתי אין להשתמש בהם דורשת מעט ניסיון. הדרך היחידה לללמוד היא על ידי עשייה, אז גשו ותתחילו בניסויים…

 

רועי יוסף
רועי יוסף

מפתח וורדפרס, מאמין ביצירת הזדמנויות לעסקים קטנים, סטארטאפים נועזים ואנשים עצמאים לשנות את העולם. אוהב טיפוגרפיה, צבעים וכל מה שבינהם ומכוון לספק אתרי וורדפרס עם ביצועים גבוהים, תמיכה בכל הדפדפנים, בעלי קוד ולידי, סמנטי ונקי. צרו איתי קשר.

{ 9 תגובות… הוסף אחת }
  • רמי 8 ביולי 2015, 10:58

    רועי, פוסט יפה מאוד, כל הכבוד על ההשקעה.

    מספר הערות:

    1. ראשית אין להשתמש בעברית בקוד, יש להשתמש באנגלית ולהוסיף ולהשתמש בפונקציות התרגום של וורדפרס בשילוב של textdomain.
    2. ולמה לכתוב קוד כשאפשר להשתמש בגנרטור לייצור הקוד – https://generatewp.com/post-type/
    3. ואם כבר אתה נמנע מלהשתמש בתוספים כדי ליצור סוגי פוסטים, מדוע להשתמש בתוסף ACF כדי ליצור metabox? אפשר לכתוב קוד כדי להוסיף שדות נוספים ולהרחיב את הפונקציונאליות.

    חוץ מזה, אחלה פוסט!

    • מנהל מערכת 8 ביולי 2015, 11:13

      היי רמי, תודה רבה על התגובה 🙂
      לגבי סעיף 1, אתה בהחלט צודק ורצוי להשתמש בפונקציית התרגום. אדאג להוסיף את האפשרות בהקדם.
      לגבי סעיף 3, ציינתי שניתן להוסיף metaboxes בקוד ואף יותר מזה… למה להסביר על ACF ? כי הוא פלאגין מגניב מי כמוך יודע…

      • רמי 8 ביולי 2015, 16:18

        שמעתי הרבה מחמאות על ACF ואני בהחלט מפרגן ליוצרים, אבל אני מעדיף לכתוב את הקוד שלי בעצמי.

        שימוש בתוספים כמו ACF מוסיף הרבה תקורה לאתר שלך. הרי התוסף מביא פתרון כולל לכל הצרכים של כל המשתמשים, גם דברים שאתה לא צריך. ואפילו אם לא תשתמש בתוסף אלא בספרייה שיוצרת Meta Box או Custom Post Types או Taxonomy עדיין יש תקורה רבה והמון דברים מיותרים (קרוב ל-90% מהקוד לא יהיה רלוונטי לפרוייקט שלך).

        לעומת זאת, כשאתה כותב קוד בעצמך, אתה כותב רק את מה שהאתר שלך צריך ולא יותר מזה. קוד רזה, חסכוני וללא תקורה מיותרת.

        • מנהל מערכת 8 ביולי 2015, 19:33

          תמיד עדיף לכתוב קוד בעצמך מאשר להשתמש בפלאגין, על זה אין ויכוח כלל. עם זאת, זה לא תמיד מתאפשר, כמו שלא תמיד נכתוב את התבנית בעצמינו למרות שלבטח עדיף… בכל אופן ACF הוא פלאגין שכתוב מאד נכון מבחינת קוד והממשק שלו נוח ומלא אפשרויות קיסטום.. כשזה מגיע ל Custom Fields אני תמיד מעדיף להשתמש בו מאשר לכתוב את הקוד בעצמי.

          • רמי 9 ביולי 2015, 0:30

            בעבר הרבה מפתחים אמרו לי את זה על post types ועל taxonomies עד ששחררתי את הגנרטורים האוטומטיים ב-GenerateWP.com , היום הם כבר לא משתמשים בתוספים.

            עוד מעט אנחנו נשחרר MetaBox Generator ואז גם השימוש ב-ACF יפחת.

          • רמי 9 ביולי 2015, 0:33

            אגב, זו פרקטיקה בעייתית למסור ללקוח אתר כשהוא רואה את כל התוספים בהם השתמשת. הוא יכול להיכנס תוסף ולשנות, ואז באותו התלונות – האתר לא עובד… האתר מקולקל…

  • מנהל מערכת 9 ביולי 2015, 1:15

    גנרטור מדליק, אחלה כלי ויוזמה יפה !

    נסה אגב ליצור את הפונקציונליות שה repeater field ב ACF מאפשר לך בקוד משלך, תאמר לי איך הולך לך 🙂 לגבי למסור אתר ללקוח כשהוא רואה את התוספים, ניתן עם פונקציה פשוטה להסתיר זאת מעיניו..

    add_action( 'admin_init', 'my_remove_menu_pages' );
    function my_remove_menu_pages() {
     
        global $user_ID;
     	$user = wp_get_current_user();
    
        if ( current_user_can( 'administrator' ) && ($user && isset($user->user_login) && 'THE_USER_NAME' == $user->user_login)) {
    		remove_menu_page('plugins.php'); // Plugins
        }
    }
    
    • רמי 19 ביולי 2015, 15:52

      שוב אתה חוזר לתוספים?
      מתקין תוסף אחד בשביל להסתיר אחר?
      אתה יודע כמה קוד מיותר יש לך באתר שמאט אותו?

  • ינון 31 במאי 2018, 2:50

    תודה רבה על המאמר ובכללי על הבלוג המושקע מאוד עם תוכן איכותי פצצות. בכלל לא מובן מאליו שאתה משתף בידע זה מאוד עוזר , שוב תודה

השאירו תגובה

פעימות
מדריך שימוש בסיסי ב Advanced Custom Fields
מדריך שימוש בסיסי ב Advanced Custom Fields

קשה לתאר את ההתרגשות שהייתה בי ברגע שגיליתי את נפלאות הפלאגין Advanced Custom Fields או...