Yes, there are lot of plugins using CPTs as data holders (e.g., Advanced Custom Field). Others, though, carefully use the class WP_List_Table to conform to the default interface (e.g., BackWPup).
When registering a post type, we have options to control its visibility and “querybility”: public
, show_ui
, publicly_queryable
and others. This is how ACF registers itself:
register_post_type('acf', array(
'labels' => $labels,
'public' => false,
'show_ui' => true,
'_builtin' => false,
'capability_type' => 'page',
'hierarchical' => true,
'rewrite' => false,
'query_var' => "acf",
'supports' => array(
'title',
),
'show_in_menu' => false,
));
So, yes, it’s perfectly fine to create a CPT that appears only in the backend, and then use it in other parts of the system. For example, the Navigation Menus (wp-admin/nav-menus.php
) is a CPT, and registered like:
register_post_type( 'nav_menu_item', array(
'labels' => $labels,
'public' => false,
'_builtin' => true, /* internal use only. don't use this when registering your own post type. */
'hierarchical' => false,
'rewrite' => false,
'delete_with_user' => false,
'query_var' => false,
) );
Your example, using as a Shortcode, would be something like this used in a Post or Page:
[my_shortcode id="77"]
and what it does is: get whatever information you have in your CPT with ID 77 and display it.
Forget functions.php
for this kind of stuff. Research our archives on plugin-development as there is plenty of material to get started, simple and complex.