<\/figure>\nMove anything from the left to right, and it’s now programatically attached. This is exactly what we’re after. Now we can hand select, and hand order, any type of post to attach to any other.<\/p>\n
Configuring Things<\/h3>\n Before you get to the UI you can see above, you not only need to install and activate those two plugins, but also tell CMB2 to create the custom meta boxes and apply them to the types of posts you want.<\/p>\n
In our case, our Guides are a custom post type. That’s easy enough to enable:<\/p>\n
register_post_type( 'guides',\r\n array(\r\n 'labels' => array(\r\n 'name' => __( 'Guides' ),\r\n 'singular_name' => __( 'Guide' ),\r\n 'add_new' => __( 'Add Guide' ),\r\n 'add_new_item' => __( 'Add New Guide' ),\r\n 'edit_item' => __( 'Edit Guide' ),\r\n ),\r\n 'public' => true,\r\n 'has_archive' => true,\r\n 'rewrite' => array( 'slug' => 'guides' ),\r\n 'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' )\r\n )\r\n);<\/code><\/pre>\nThen we apply this new custom meta box only to that custom post type (so we don’t have to see it everywhere):<\/p>\n
$cmb = new_cmb2_box( array(\r\n 'id' => 'guide_metabox',\r\n 'title' => __( 'The Guide Metabox', 'cmb2' ),\r\n 'object_types' => array( 'guides', ), \/\/ Post type\r\n 'context' => 'normal',\r\n 'priority' => 'high',\r\n 'show_names' => true, \/\/ Show field names on the left\r\n \/\/ 'cmb_styles' => false, \/\/ false to disable the CMB stylesheet\r\n \/\/ 'closed' => true, \/\/ Keep the metabox closed by default\r\n) );\r\n\r\n\/\/ Regular text field\r\n$cmb->add_field( array(\r\n 'name' => __( 'Things for the Guide', 'cmb2' ),\r\n 'id' => 'attached_cmb2_attached_posts',\r\n 'type' => 'custom_attached_posts',\r\n 'show_on_cb' => 'cmb2_hide_if_no_cats',\r\n 'options' => array(\r\n 'show_thumbnails' => true, \/\/ Show thumbnails on the left\r\n 'filter_boxes' => true, \/\/ Show a text box for filtering the results\r\n 'query_args' => array(\r\n \/\/ 'posts_per_page' => 2,\r\n 'post_type' => array('post', 'page')\r\n ), \/\/ override the get_posts args\r\n ),\r\n) );<\/code><\/pre>\nWe nestle all this code nicely into a functionality plugin, rather than a `functions.php` file, so that changing themes has no bearing on this content.<\/p>\n
A Template for Guides<\/h3>\n Now that a custom post type exists for our guides, adding a file called `single-guides.php` into our active theme is enough to make that the file that renders for like `\/guide\/example\/`.<\/p>\n
In that file, we do whatever normal template-y stuff we’d do on any other template file (e.g. `page.php`, but also loop through all these posts we’ve attached!<\/p>\n
<?php\r\n\r\n $attached = get_post_meta(get_the_ID(), 'attached_cmb2_attached_posts', true);\r\n\r\n foreach ($attached as $attached_post) {\r\n $post = get_post($attached_post); ?>\r\n\r\n <?php include(\"parts\/article-card.php\"); ?>\r\n\r\n<?php } ?><\/code><\/pre>\nAll in all, not that much to it!<\/p>\n <\/figure>\nIt feels great to have some kind of mechanism for surfacing evergreen content like this. That can be quite a challenge for sites with a huge amount of content!<\/p>\n
\nHigh five to Rebekah Monson<\/a>, whom I ripped this idea off of, who uses this to build guides on The New Tropic, like these neighborhood guides<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"A blog post can be anything you want. You could easily write one that links up a bunch of articles on your site. Titles, summaries, links… all hand-crafted HTML. A “guide”, as it were. It will likely be appreciated by your readers, I find, especially when you’re linking up old evergreen content that is still […]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/253363"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=253363"}],"version-history":[{"count":6,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/253363\/revisions"}],"predecessor-version":[{"id":253388,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/253363\/revisions\/253388"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=253363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=253363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=253363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}