SlideShare a Scribd company logo
1 of 72
Relationships Between
Custom Post Types
Randy Hoyt
@randyhoyt                               #orlandowordcamp



About Me




              Randy Hoyt    randyhoyt.com
                            @randyhoyt


             Presentation   randyhoyt.com/wcorlando
@randyhoyt           #orlandowordcamp



Custom Post Types?




    Posts    Pages
@randyhoyt           #orlandowordcamp



Event Calendar




    Posts    Pages          Events
@randyhoyt           #orlandowordcamp



Restaurant Chain




    Posts    Pages         Locations
@randyhoyt           #orlandowordcamp



University Course




    Posts    Pages        Assignments
@randyhoyt                                    #orlandowordcamp




 wp_posts
   ID         post_type       post_title

    1             post        Hello, world!


    2            page         Sample Page


   231       rrh_assignment   Final Exam
@randyhoyt                                    #orlandowordcamp




 wp_posts
   ID         post_type       post_title

    1             post        Hello, world!


    2            page         Sample Page


   231       rrh_assignment   Final Exam




Structured Data in WordPress
http://randyhoyt.com/wcto
@randyhoyt           #orlandowordcamp



Shopping Center
                              Stores




    Posts    Pages
                      Sales       Jobs
@randyhoyt           #orlandowordcamp



Shopping Center
                              Stores




    Posts    Pages
                      Sales       Jobs
@randyhoyt                 #orlandowordcamp



Storing Relationships

1. Post Meta Field
2. Custom Relationship Table
3. Post Parent Field
@randyhoyt           #orlandowordcamp



1. Post Meta Field
                                 Talks




                        Speakers
    Posts    Pages
@randyhoyt   #orlandowordcamp
@randyhoyt         #orlandowordcamp



Post Meta Fields
@randyhoyt                                            #orlandowordcamp



Post Meta Fields

 wp_posts                              wp_postmeta
 ID   post_type     post_title         post_id   meta_key    meta_value

 37   rrh_speaker   Randy Hoyt         37
                                       38        job_title
                                                 speaker     Teacher
                                                             37

 38   rrh_talk      Custom Post Type   37        company     Treehouse
                    Relationships
                                       37        twitter     randyhoyt
@randyhoyt                                            #orlandowordcamp



Post Meta Fields

 wp_posts                              wp_postmeta
 ID   post_type     post_title         post_id   meta_key    meta_value

 37   rrh_speaker   Randy Hoyt         37
                                       38        job_title
                                                 speaker     Teacher
                                                             37

 38   rrh_talk      Custom Post Type   37        company     Treehouse
                    Relationships
                                       37        twitter     randyhoyt

                                       38        speaker     37
@randyhoyt   #orlandowordcamp
@randyhoyt                                         #orlandowordcamp



Library: Custom Meta Boxes
http://r2h.me/wpcmb

Custom Meta Boxes allow you to build clean, understandable
interfaces for entering metadata. There’s a ton of field options:
text, textarea, checkbox, dropdown list, WYSIWYG, and more.
@randyhoyt   #orlandowordcamp
@randyhoyt   #orlandowordcamp
@randyhoyt                        #orlandowordcamp


$meta_boxes[] = array(
    'id' => 'rrh_talk_data',
    'title' => 'Talk Information',
    'pages' => array('rrh_talk'),
    'context' => 'normal',
    'priority' => 'high',
    'show_names' => true,
    'fields' => array(
          array(
                'name' => 'Speaker',
               'id' => 'speaker',
               'type' => 'select',
               'options' => $speakers
          ),
    ),
);
@randyhoyt                         #orlandowordcamp




$posts = query_posts( array(
    'posts_per_page' => -1
    'post_type' => 'rrh_speaker'
));

foreach ($posts as $post) {
    $speakers[] = array(
        'name' => $post->post_title,
        'value' => $post->ID
    );
}

wp_reset_query();
@randyhoyt   #orlandowordcamp
@randyhoyt                           #orlandowordcamp




Template file: single-rrh_talk.php
Retrieve speaker ID from custom field
  $speaker_id = get_post_meta($post->ID,
                                   "speaker", true);

Retrieve speaker info from ID
  $speaker = get_post($speaker_id);


Display speaker title
  echo $speaker->post_title;


Retrieve link to speaker from ID
  $speaker_link = get_permalink($speaker->ID);
@randyhoyt                              #orlandowordcamp




Template file: single-rrh_speaker.php
Retrieve talks with speaker ID in custom field

    $talks = get_posts( array(
            'post_type' => 'rrh_talk',
            'meta_key' => 'speaker',
            'meta_value' => $post->ID
    ));

Loop through all the talks; display talk title

    foreach($talks as $talk) {

         echo $talk->post_title;

    }
@randyhoyt   #orlandowordcamp
@randyhoyt              #orlandowordcamp



2. Relationship Table
                                   Movies




                          People
    Posts    Pages
@randyhoyt              #orlandowordcamp



2. Relationship Table
                                   Movies




                          People
    Posts    Pages
@randyhoyt                                         #orlandowordcamp



Custom Relationship Table

 wp_posts                         <relationship>
                                  wp_postmeta
 ID   post_type   post_title      to_id
                                  post_id    from_id
                                             meta_key   character
                                                        meta_value

 37   movie       Star Wars       37
                                  38         38
                                             speaker    Han
                                                        37 Solo

 38   person      Harrison Ford
@randyhoyt                                       #orlandowordcamp



Plugin: Posts 2 Posts
http://r2h.me/p2p

This plugin provides functions developers can use to create
many-to-many relationships between posts of any type:
posts, pages, and custom post types.
@randyhoyt   #orlandowordcamp
p2p_register_connection_type( array(
        'name' => 'rrh_person_to_movie’,
        'from' => 'rrh_person',
        'to' => 'rrh_movie',
        'fields' => array(
            'role' => array(
                 'title' => 'Role',
                 'type' => 'select',
                'values' => array('Director' ...)
             ),
             'character' => array(
                'title' => 'Character',
                'type' => 'text'
             )
        ),
));
@randyhoyt                                                       #orlandowordcamp



Custom Relationship Table
 wp_posts
 ID         post_type             post_title

 37         person                Harrison Ford

 38         movie                 Star Wars




 wp_p2p                                             wp_p2pmeta
 p2p_id     to_id       from_id   type              p2p_id   meta_key    meta_value

 1          37          38        person_to_movie   1        role        Lead Actor

                                                    1        character   Han Solo
@randyhoyt                            #orlandowordcamp




Template file: single-rrh_movie.php
$connected = new WP_Query(array(
    'connected_type' => 'rrh_person_to_movie',
    'connected_items' => $post,
    'nopaging' => true
));


if ( $connected->have_posts() ) {

    ...

}
if ( $connected->have_posts() ) {

    while ( $connected->have_posts() ) :

        $connected->the_post();

        echo '<li><a href="';
        the_permalink();
        echo '">';
        the_title();
        echo '</a></li>';

    endwhile;

}
@randyhoyt                             #orlandowordcamp




Template file: single-rrh_person.php
@randyhoyt             #orlandowordcamp



3. Post Parent Field
                           Groups




    Posts    Pages
                               Meetings
@randyhoyt                                #orlandowordcamp




 wp_posts
  ID     post_type   post_title                post_parent

   2         page    About                          0


  231        page    Location & Venue               2


  256        page    Developer Hack Day             2


  347        page    Contact                        2
@randyhoyt                           #orlandowordcamp




 wp_posts
  ID     post_type      post_title        post_parent

   2          page      About                  0


  156        revision   About                  2


  157        revision   About                  2


  158        revision   About                  2
@randyhoyt                                           #orlandowordcamp




 wp_posts
  ID     post_type    post_title                          post_parent

  15         forum    Book Discussions                         0


  78         topic    Favorite Tolkien Characters?             15


  123        reply    Reply To: Favorite Tolkien …             78




bbPress
http://bbpress.org/
@randyhoyt                                       #orlandowordcamp



Subordinate Post Type Helpers
http://wordpress.org/extend/plugins/subordinate-post-type-helpers/


This plugin provides a number of helpers functions to aid in the
creation of subordinate relationships between two post types,
one-to-many relationships in which posts of one type are children
of another.
@randyhoyt                                       #orlandowordcamp



Subordinate Post Type Helpers
http://wordpress.org/extend/plugins/subordinate-post-type-helpers/


This plugin provides a number of helpers functions to aid in the
creation of subordinate relationships between two post types, one-
to-many relationships in which posts of one type are children of
another.


register_sub_post_type('meeting', $args, 'group')
                                  ;
Register meetings as a regular post type
register_post_type('meeting', $args)



Register meetings as a subordinate post type
register_sub_post_type('meeting', $args, 'group')
WordPress Codex: register_post_type()
http://codex.wordpress.org/Function_Reference/register_post_type
WordPress Codex: add_submenu_page()
A
http://codex.wordpress.org/Function_Reference/add_submenu_page
http://
add_submenu()




WordPress Codex: remove_menu_page()
A
http://codex.wordpress.org/Function_Reference/remove_menu_page
http://
Add_meta_boxes ()




WordPress Codex: add_meta_box()
A
http://codex.wordpress.org/Function_Reference/add_meta_box
http://
Add_meta_boxes ()




WordPress Codex: query_posts()
A
http://codex.wordpress.org/Function_Reference/query_posts
http://
Add_meta_boxes ()




WordPress Admin and Thickbox
A
<a class="thickbox" … >
http://
Iframe with query string parameters
Post ID parameter is left blank for adding a new meeting …
wp_insert_post()




Iframe with query string parameters
… but post ID parameter is set for editing an existing meeting.
wp_insert_post()




WordPress Codex: wp_insert_post()
http://codex.wordpress.org/Function_Reference/wp_insert_post
wp_insert_post()




WordPress Codex: wp_trash_post()
http://codex.wordpress.org/Function_Reference/wp_trash_post
JavaScript function in page




Return list of meetings to the Edit Group page
<script>

     function list_meetings(display)
     {
         ...
     }
         JavaScript function in page
</script>




Create JavaScript function on the Edit Group page
<script>

     var display = ...

     var win = window.dialogArguments           →
                   || opener || parent || top;
     win.list_meetings(display);

</script>




Call that JavaScript function from the iframe
<script>

     function list_meetings(display)
     {

          jQuery('#list_meetings).empty()          →
          JavaScript function .append(display);
                              in page
          tb_remove();
     }

</script>



That function inserts the list into the Edit Group page
JavaScript function in page
Register meetings as a regular post type
register_post_type('meeting', $args)



Register meetings as a subordinate post type
register_sub_post_type('meeting', $args, 'group')
Retrieve meetings for a group

    $meetings = get_posts( array(
            'post_type' => 'mythsoc_meeting',
            'post_parent' => $post->ID
    ));

Loop through all the meetings; display meeting title

    foreach($meetings as $meeting) {

         echo $meeting->post_title;

    }
@randyhoyt                 #orlandowordcamp



Storing Relationships

1. Post Meta Field
2. Custom Relationship Table
3. Post Parent Field
Relationships Between
Custom Post Types
Randy Hoyt     randyhoyt.com
               @randyhoyt


Presentation   randyhoyt.com/wcorlando

More Related Content

More from randyhoyt

Integrating WordPress With Web APIs
Integrating WordPress With Web APIsIntegrating WordPress With Web APIs
Integrating WordPress With Web APIsrandyhoyt
 
Integrating WordPress With Web APIs
Integrating WordPress With Web APIsIntegrating WordPress With Web APIs
Integrating WordPress With Web APIsrandyhoyt
 
Html5game presentation
Html5game presentationHtml5game presentation
Html5game presentationrandyhoyt
 
Structured Data in WordPress
Structured Data in WordPressStructured Data in WordPress
Structured Data in WordPressrandyhoyt
 
Extending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHPExtending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHPrandyhoyt
 
WordPress Plugins
WordPress PluginsWordPress Plugins
WordPress Pluginsrandyhoyt
 
Working with Images in WordPress
Working with Images in WordPress Working with Images in WordPress
Working with Images in WordPress randyhoyt
 

More from randyhoyt (8)

Integrating WordPress With Web APIs
Integrating WordPress With Web APIsIntegrating WordPress With Web APIs
Integrating WordPress With Web APIs
 
Integrating WordPress With Web APIs
Integrating WordPress With Web APIsIntegrating WordPress With Web APIs
Integrating WordPress With Web APIs
 
Api
ApiApi
Api
 
Html5game presentation
Html5game presentationHtml5game presentation
Html5game presentation
 
Structured Data in WordPress
Structured Data in WordPressStructured Data in WordPress
Structured Data in WordPress
 
Extending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHPExtending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHP
 
WordPress Plugins
WordPress PluginsWordPress Plugins
WordPress Plugins
 
Working with Images in WordPress
Working with Images in WordPress Working with Images in WordPress
Working with Images in WordPress
 

Relationships Between WordPress Post Types

  • 2. @randyhoyt #orlandowordcamp About Me Randy Hoyt randyhoyt.com @randyhoyt Presentation randyhoyt.com/wcorlando
  • 3. @randyhoyt #orlandowordcamp Custom Post Types? Posts Pages
  • 4. @randyhoyt #orlandowordcamp Event Calendar Posts Pages Events
  • 5. @randyhoyt #orlandowordcamp Restaurant Chain Posts Pages Locations
  • 6.
  • 7.
  • 8. @randyhoyt #orlandowordcamp University Course Posts Pages Assignments
  • 9.
  • 10.
  • 11. @randyhoyt #orlandowordcamp wp_posts ID post_type post_title 1 post Hello, world! 2 page Sample Page 231 rrh_assignment Final Exam
  • 12. @randyhoyt #orlandowordcamp wp_posts ID post_type post_title 1 post Hello, world! 2 page Sample Page 231 rrh_assignment Final Exam Structured Data in WordPress http://randyhoyt.com/wcto
  • 13. @randyhoyt #orlandowordcamp Shopping Center Stores Posts Pages Sales Jobs
  • 14. @randyhoyt #orlandowordcamp Shopping Center Stores Posts Pages Sales Jobs
  • 15.
  • 16.
  • 17. @randyhoyt #orlandowordcamp Storing Relationships 1. Post Meta Field 2. Custom Relationship Table 3. Post Parent Field
  • 18. @randyhoyt #orlandowordcamp 1. Post Meta Field Talks Speakers Posts Pages
  • 19. @randyhoyt #orlandowordcamp
  • 20. @randyhoyt #orlandowordcamp Post Meta Fields
  • 21. @randyhoyt #orlandowordcamp Post Meta Fields wp_posts wp_postmeta ID post_type post_title post_id meta_key meta_value 37 rrh_speaker Randy Hoyt 37 38 job_title speaker Teacher 37 38 rrh_talk Custom Post Type 37 company Treehouse Relationships 37 twitter randyhoyt
  • 22. @randyhoyt #orlandowordcamp Post Meta Fields wp_posts wp_postmeta ID post_type post_title post_id meta_key meta_value 37 rrh_speaker Randy Hoyt 37 38 job_title speaker Teacher 37 38 rrh_talk Custom Post Type 37 company Treehouse Relationships 37 twitter randyhoyt 38 speaker 37
  • 23. @randyhoyt #orlandowordcamp
  • 24. @randyhoyt #orlandowordcamp Library: Custom Meta Boxes http://r2h.me/wpcmb Custom Meta Boxes allow you to build clean, understandable interfaces for entering metadata. There’s a ton of field options: text, textarea, checkbox, dropdown list, WYSIWYG, and more.
  • 25. @randyhoyt #orlandowordcamp
  • 26. @randyhoyt #orlandowordcamp
  • 27. @randyhoyt #orlandowordcamp $meta_boxes[] = array( 'id' => 'rrh_talk_data', 'title' => 'Talk Information', 'pages' => array('rrh_talk'), 'context' => 'normal', 'priority' => 'high', 'show_names' => true, 'fields' => array( array( 'name' => 'Speaker', 'id' => 'speaker', 'type' => 'select', 'options' => $speakers ), ), );
  • 28. @randyhoyt #orlandowordcamp $posts = query_posts( array( 'posts_per_page' => -1 'post_type' => 'rrh_speaker' )); foreach ($posts as $post) { $speakers[] = array( 'name' => $post->post_title, 'value' => $post->ID ); } wp_reset_query();
  • 29. @randyhoyt #orlandowordcamp
  • 30. @randyhoyt #orlandowordcamp Template file: single-rrh_talk.php
  • 31. Retrieve speaker ID from custom field $speaker_id = get_post_meta($post->ID, "speaker", true); Retrieve speaker info from ID $speaker = get_post($speaker_id); Display speaker title echo $speaker->post_title; Retrieve link to speaker from ID $speaker_link = get_permalink($speaker->ID);
  • 32. @randyhoyt #orlandowordcamp Template file: single-rrh_speaker.php
  • 33. Retrieve talks with speaker ID in custom field $talks = get_posts( array( 'post_type' => 'rrh_talk', 'meta_key' => 'speaker', 'meta_value' => $post->ID )); Loop through all the talks; display talk title foreach($talks as $talk) { echo $talk->post_title; }
  • 34. @randyhoyt #orlandowordcamp
  • 35. @randyhoyt #orlandowordcamp 2. Relationship Table Movies People Posts Pages
  • 36. @randyhoyt #orlandowordcamp 2. Relationship Table Movies People Posts Pages
  • 37. @randyhoyt #orlandowordcamp Custom Relationship Table wp_posts <relationship> wp_postmeta ID post_type post_title to_id post_id from_id meta_key character meta_value 37 movie Star Wars 37 38 38 speaker Han 37 Solo 38 person Harrison Ford
  • 38. @randyhoyt #orlandowordcamp Plugin: Posts 2 Posts http://r2h.me/p2p This plugin provides functions developers can use to create many-to-many relationships between posts of any type: posts, pages, and custom post types.
  • 39. @randyhoyt #orlandowordcamp
  • 40. p2p_register_connection_type( array( 'name' => 'rrh_person_to_movie’, 'from' => 'rrh_person', 'to' => 'rrh_movie', 'fields' => array( 'role' => array( 'title' => 'Role', 'type' => 'select', 'values' => array('Director' ...) ), 'character' => array( 'title' => 'Character', 'type' => 'text' ) ), ));
  • 41. @randyhoyt #orlandowordcamp Custom Relationship Table wp_posts ID post_type post_title 37 person Harrison Ford 38 movie Star Wars wp_p2p wp_p2pmeta p2p_id to_id from_id type p2p_id meta_key meta_value 1 37 38 person_to_movie 1 role Lead Actor 1 character Han Solo
  • 42. @randyhoyt #orlandowordcamp Template file: single-rrh_movie.php
  • 43. $connected = new WP_Query(array( 'connected_type' => 'rrh_person_to_movie', 'connected_items' => $post, 'nopaging' => true )); if ( $connected->have_posts() ) { ... }
  • 44. if ( $connected->have_posts() ) { while ( $connected->have_posts() ) : $connected->the_post(); echo '<li><a href="'; the_permalink(); echo '">'; the_title(); echo '</a></li>'; endwhile; }
  • 45. @randyhoyt #orlandowordcamp Template file: single-rrh_person.php
  • 46. @randyhoyt #orlandowordcamp 3. Post Parent Field Groups Posts Pages Meetings
  • 47. @randyhoyt #orlandowordcamp wp_posts ID post_type post_title post_parent 2 page About 0 231 page Location & Venue 2 256 page Developer Hack Day 2 347 page Contact 2
  • 48. @randyhoyt #orlandowordcamp wp_posts ID post_type post_title post_parent 2 page About 0 156 revision About 2 157 revision About 2 158 revision About 2
  • 49. @randyhoyt #orlandowordcamp wp_posts ID post_type post_title post_parent 15 forum Book Discussions 0 78 topic Favorite Tolkien Characters? 15 123 reply Reply To: Favorite Tolkien … 78 bbPress http://bbpress.org/
  • 50. @randyhoyt #orlandowordcamp Subordinate Post Type Helpers http://wordpress.org/extend/plugins/subordinate-post-type-helpers/ This plugin provides a number of helpers functions to aid in the creation of subordinate relationships between two post types, one-to-many relationships in which posts of one type are children of another.
  • 51. @randyhoyt #orlandowordcamp Subordinate Post Type Helpers http://wordpress.org/extend/plugins/subordinate-post-type-helpers/ This plugin provides a number of helpers functions to aid in the creation of subordinate relationships between two post types, one- to-many relationships in which posts of one type are children of another. register_sub_post_type('meeting', $args, 'group') ;
  • 52.
  • 53. Register meetings as a regular post type register_post_type('meeting', $args) Register meetings as a subordinate post type register_sub_post_type('meeting', $args, 'group')
  • 57. Add_meta_boxes () WordPress Codex: add_meta_box() A http://codex.wordpress.org/Function_Reference/add_meta_box http://
  • 58. Add_meta_boxes () WordPress Codex: query_posts() A http://codex.wordpress.org/Function_Reference/query_posts http://
  • 59. Add_meta_boxes () WordPress Admin and Thickbox A <a class="thickbox" … > http://
  • 60. Iframe with query string parameters Post ID parameter is left blank for adding a new meeting …
  • 61. wp_insert_post() Iframe with query string parameters … but post ID parameter is set for editing an existing meeting.
  • 64. JavaScript function in page Return list of meetings to the Edit Group page
  • 65. <script> function list_meetings(display) { ... } JavaScript function in page </script> Create JavaScript function on the Edit Group page
  • 66. <script> var display = ... var win = window.dialogArguments → || opener || parent || top; win.list_meetings(display); </script> Call that JavaScript function from the iframe
  • 67. <script> function list_meetings(display) { jQuery('#list_meetings).empty() → JavaScript function .append(display); in page tb_remove(); } </script> That function inserts the list into the Edit Group page
  • 69. Register meetings as a regular post type register_post_type('meeting', $args) Register meetings as a subordinate post type register_sub_post_type('meeting', $args, 'group')
  • 70. Retrieve meetings for a group $meetings = get_posts( array( 'post_type' => 'mythsoc_meeting', 'post_parent' => $post->ID )); Loop through all the meetings; display meeting title foreach($meetings as $meeting) { echo $meeting->post_title; }
  • 71. @randyhoyt #orlandowordcamp Storing Relationships 1. Post Meta Field 2. Custom Relationship Table 3. Post Parent Field
  • 72. Relationships Between Custom Post Types Randy Hoyt randyhoyt.com @randyhoyt Presentation randyhoyt.com/wcorlando

Editor's Notes

  1. Finish 2:00
  2. NEXT: Man with phone
  3. NEXT: Man with phone
  4. NEXT: Man with phone
  5. Mention prefix
  6. Finish 21:00
  7. Finish 21:00
  8. Mention prefix
  9. Finish 21:00
  10. Finish 21:00
  11. Finish 21:00
  12. Finish 21:00
  13. Finish 21:00
  14. Finish 21:00
  15. Finish 21:00
  16. Finish 21:00
  17. Finish 21:00
  18. Finish 21:00
  19. Finish 21:00
  20. Finish 21:00
  21. Finish 21:00
  22. Finish 21:00
  23. Finish 21:00
  24. NEXT:WordPress 0.7
  25. The WordPress API doesn’t give you the ability to do this. It requires some custom code in a plugin.
  26. NEXT:WordPress 0.7
  27. Finish 21:00
  28. Finish 21:00
  29. Finish 21:00